grab_lints 0.3.2 copy "grab_lints: ^0.3.2" to clipboard
grab_lints: ^0.3.2 copied to clipboard

Lint rules to help avoid common misuse of Grab.

example/lib/main.dart

// ignore_for_file: avoid_single_cascade_in_expression_statements, invalid_override, mixin_application_not_implemented_interface, non_abstract_class_inherits_abstract_member

//=========================================================
// This file works as both a demonstration and tests.
// Your editor shows no error if lint warnings are being
// successfully suppressed by the `expect_lint` comments.
//=========================================================

import 'package:flutter/material.dart';
import 'package:grab/grab.dart';

final valueNotifier = ValueNotifier(0);
final changeNotifier1 = MyChangeNotifier1(0);
final changeNotifier2 = MyChangeNotifier2(0);
final changeNotifier3 = MyChangeNotifier3(0);
final textController = TextEditingController();

class MyChangeNotifier1 extends ChangeNotifier {
  MyChangeNotifier1(this.value);

  final int value;
}

class MyChangeNotifier2 extends MyChangeNotifier1 {
  MyChangeNotifier2(super.value);
}

class MyChangeNotifier3 with ChangeNotifier {
  MyChangeNotifier3(this.value);

  final int value;
}

void main() => runApp(const App());

class App extends StatelessWidget {
  const App({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: const Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            _StatelessWidget1(),
            _StatelessWidget2(),
            _StatelessWidget3(),
            _StatelessWidget4(),
            _StatefulWidget1(),
            _StatefulWidget2(),
            _StatefulWidget3(),
            _StatefulWidget4(),
          ],
        ),
        floatingActionButton: FloatingActionButton(
          child: const Icon(Icons.add),
          onPressed: () => valueNotifier.value++,
        ),
      ),
    );
  }
}

// expect_lint: unnecessary_grab_mixin
class _StatelessWidget1 extends StatelessWidget with Grab {
  const _StatelessWidget1();

  @override
  Widget build(BuildContext context) {
    return const SizedBox.shrink();
  }
}

class _StatelessWidget2 extends StatelessWidget with Grab {
  const _StatelessWidget2();

  @override
  Widget build(BuildContext context) {
    // Using grab in an if condition or a block is fine.
    if (valueNotifier.grab(context).isEven) {
      valueNotifier.grab(context);
    }

    return Center(
      child: SizedBox.square(
        dimension: 500.0,
        child: Column(
          children: [
            Padding(
              // Using grab in a deeply nested location is fine
              // as long as it is not in a callback.
              padding: EdgeInsets.all(valueNotifier.grab(context).toDouble()),
              child: Text('${valueNotifier.grab(context)}'),
            ),
            ...[
              Text('${valueNotifier.grab(context)}'),
            ],
          ],
        ),
      ),
    );
  }
}

// expect_lint: wrong_grab_mixin
class _StatelessWidget3 extends StatelessWidget with Grabful {
  const _StatelessWidget3();

  @override
  Widget build(BuildContext context) {
    // expect_lint: missing_grab_mixin
    final count = valueNotifier.grab(context);
    _func(context);

    return Center(
      child: Column(
        children: [
          Text('$count'),
          Builder(
            builder: (context) {
              // expect_lint: avoid_grab_in_callback
              valueNotifier.grab(context);

              return const SizedBox.shrink();
            },
          ),
        ],
      ),
    );
  }

  void _func(BuildContext context) {
    // expect_lint: avoid_grab_outside_build
    valueNotifier.grab(context);
  }
}

class _StatelessWidget4 extends StatelessWidget {
  const _StatelessWidget4();

  @override
  Widget build(BuildContext context) {
    // Either Grab or StatelessGrabMixin is necessary.
    // expect_lint: missing_grab_mixin
    final count = valueNotifier.grab(context);
    // expect_lint: missing_grab_mixin
    changeNotifier1.grab(context);
    // expect_lint: missing_grab_mixin
    changeNotifier2.grab(context);
    // expect_lint: missing_grab_mixin
    changeNotifier3.grab(context);
    // expect_lint: missing_grab_mixin
    textController.grab(context);

    // Works for grabAt() too.
    // expect_lint: missing_grab_mixin
    valueNotifier.grabAt(context, (v) => v);
    // expect_lint: missing_grab_mixin
    changeNotifier1.grabAt(context, (MyChangeNotifier1 n) => n.value);
    // expect_lint: missing_grab_mixin
    changeNotifier2.grabAt(context, (MyChangeNotifier2 n) => n.value);
    // expect_lint: missing_grab_mixin
    changeNotifier3.grabAt(context, (MyChangeNotifier3 n) => n.value);

    // Works for a call with cascade notation.
    // expect_lint: missing_grab_mixin
    valueNotifier..grab(context);

    final ctx = context;

    // Works for a call using a name other than context.
    // expect_lint: missing_grab_mixin
    valueNotifier.grab(ctx);

    return Center(
      child: Text('$count'),
    );
  }
}

// expect_lint: unnecessary_grab_mixin
class _StatefulWidget1 extends StatefulWidget with Grabful {
  const _StatefulWidget1();

  @override
  State<_StatefulWidget1> createState() => _StatefulWidget1State();
}

class _StatefulWidget1State extends State<_StatefulWidget1> {
  @override
  Widget build(BuildContext context) {
    return const SizedBox.shrink();
  }
}

class _StatefulWidget2 extends StatefulWidget with Grabful {
  const _StatefulWidget2();

  @override
  State<_StatefulWidget2> createState() => _StatefulWidget2State();
}

class _StatefulWidget2State extends State<_StatefulWidget2> {
  @override
  Widget build(BuildContext context) {
    // Using grab in an if condition or a block is fine.
    if (valueNotifier.grab(context).isEven) {
      valueNotifier.grab(context);
    }

    return Center(
      child: SizedBox.square(
        dimension: 500.0,
        child: Column(
          children: [
            Padding(
              // Using grab in a deeply nested location is fine
              // as long as it is not in a callback.
              padding: EdgeInsets.all(valueNotifier.grab(context).toDouble()),
              child: Text('${valueNotifier.grab(context)}'),
            ),
            ...[
              Text('${valueNotifier.grab(context)}'),
            ],
          ],
        ),
      ),
    );
  }
}

// expect_lint: wrong_grab_mixin
class _StatefulWidget3 extends StatefulWidget with Grab {
  const _StatefulWidget3();

  @override
  State<_StatefulWidget3> createState() => _StatefulWidget3State();
}

class _StatefulWidget3State extends State<_StatefulWidget3> {
  @override
  Widget build(BuildContext context) {
    // expect_lint: missing_grab_mixin
    final count = valueNotifier.grab(context);
    _func(context);

    return Center(
      child: Column(
        children: [
          Text('$count'),
          Builder(
            builder: (context) {
              // expect_lint: avoid_grab_in_callback
              valueNotifier.grab(context);

              return const SizedBox.shrink();
            },
          ),
        ],
      ),
    );
  }

  void _func(BuildContext context) {
    // expect_lint: avoid_grab_outside_build
    valueNotifier.grab(context);
  }
}

class _StatefulWidget4 extends StatefulWidget {
  const _StatefulWidget4();

  @override
  State<_StatefulWidget4> createState() => _StatefulWidget4State();
}

class _StatefulWidget4State extends State<_StatefulWidget4> {
  @override
  Widget build(BuildContext context) {
    // Either Grab or StatelessGrabMixin is necessary.
    // expect_lint: missing_grab_mixin
    final count = valueNotifier.grab(context);
    // expect_lint: missing_grab_mixin
    changeNotifier1.grab(context);
    // expect_lint: missing_grab_mixin
    changeNotifier2.grab(context);
    // expect_lint: missing_grab_mixin
    changeNotifier3.grab(context);
    // expect_lint: missing_grab_mixin
    textController.grab(context);

    // Works for grabAt() too.
    // expect_lint: missing_grab_mixin
    valueNotifier.grabAt(context, (v) => v);
    // expect_lint: missing_grab_mixin
    changeNotifier1.grabAt(context, (MyChangeNotifier1 n) => n.value);
    // expect_lint: missing_grab_mixin
    changeNotifier2.grabAt(context, (MyChangeNotifier2 n) => n.value);
    // expect_lint: missing_grab_mixin
    changeNotifier3.grabAt(context, (MyChangeNotifier3 n) => n.value);

    // Works for a call with cascade notation.
    // expect_lint: missing_grab_mixin
    valueNotifier..grab(context);

    final ctx = context;

    // Works for a call using a name other than context.
    // expect_lint: missing_grab_mixin
    valueNotifier.grab(ctx);

    return Center(
      child: Text('$count'),
    );
  }
}
1
likes
0
points
35
downloads

Publisher

verified publisherkaboc.cc

Weekly Downloads

Lint rules to help avoid common misuse of Grab.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

analyzer, custom_lint_builder

More

Packages that depend on grab_lints