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

Lint rules to warn you about common misuse of Grab and fix it quickly.

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, unused_element

//=========================================================
// 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);
    }

    int localFunc1() {
      // It is acceptable to using the BuildContext parameter
      // in a local function.
      return valueNotifier.grab(context);
    }

    int localFunc2(BuildContext context) {
      // Warned if the BuildContext param is not directly used.
      // expect_lint: maybe_wrong_build_context_for_grab
      return valueNotifier.grab(context);
    }

    final ctx = context;

    // The BuildContext parameter of the build method should be used directly.
    // expect_lint: maybe_wrong_build_context_for_grab
    valueNotifier.grab(ctx);

    return Center(
      child: SizedBox.square(
        dimension: 500.0,
        child: Column(
          children: [
            Padding(
              // Using grab in a deeply nested location is fine.
              padding: EdgeInsets.all(valueNotifier.grab(context).toDouble()),
              child: Text('${valueNotifier.grab(context)}'),
            ),
            ...[
              Text('${valueNotifier.grab(context)}'),
            ],
            Builder(
              builder: (_) {
                // It is acceptable to using the BuildContext parameter
                // in a callback function.
                // However, note that this causes a rebuild of the parent
                // widget as well as this Builder.
                return Text('${valueNotifier.grab(context)}');
              },
            ),
            Builder(
              builder: (context) {
                // expect_lint: maybe_wrong_build_context_for_grab
                return Text('${valueNotifier.grab(context)}');
              },
            ),
            Builder(
              builder: (context2) {
                final context = context2;

                // expect_lint: maybe_wrong_build_context_for_grab
                return Text('${valueNotifier.grab(context)}');
              },
            ),
          ],
        ),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    _func(context);

    // expect_lint: missing_grab_mixin
    return Text('${valueNotifier.grab(context)}');
  }

  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);

    // 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);

    // expect_lint: missing_grab_mixin
    valueNotifier..grab(context);

    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);
    }

    int localFunc1() {
      // It is acceptable to using the BuildContext parameter
      // in a local function.
      return valueNotifier.grab(context);
    }

    int localFunc2(BuildContext context) {
      // Warned if the BuildContext param is not directly used.
      // expect_lint: maybe_wrong_build_context_for_grab
      return valueNotifier.grab(context);
    }

    final ctx = context;

    // The BuildContext parameter of the build method should be used directly.
    // expect_lint: maybe_wrong_build_context_for_grab
    valueNotifier.grab(ctx);

    return Center(
      child: SizedBox.square(
        dimension: 500.0,
        child: Column(
          children: [
            Padding(
              // Using grab in a deeply nested location is fine.
              padding: EdgeInsets.all(
                valueNotifier.grab(context).toDouble(),
              ),
              child: Text('${valueNotifier.grab(context)}'),
            ),
            ...[
              Text('${valueNotifier.grab(context)}'),
            ],
            Builder(
              builder: (_) {
                // It is acceptable to using the BuildContext parameter
                // in a callback function.
                // However, note that this causes a rebuild of the parent
                // widget as well as this Builder.
                return Text('${valueNotifier.grab(context)}');
              },
            ),
            Builder(
              builder: (context) {
                // expect_lint: maybe_wrong_build_context_for_grab
                return Text('${valueNotifier.grab(context)}');
              },
            ),
            Builder(
              builder: (context2) {
                final context = context2;

                // expect_lint: maybe_wrong_build_context_for_grab
                return 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) {
    _func(context);

    // expect_lint: missing_grab_mixin
    return Text('${valueNotifier.grab(context)}');
  }

  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 Grabful or StatefulGrabMixin 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);

    // 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);

    // expect_lint: missing_grab_mixin
    valueNotifier..grab(context);

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

Publisher

verified publisherkaboc.cc

Weekly Downloads

Lint rules to warn you about common misuse of Grab and fix it quickly.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

analyzer, custom_lint_builder

More

Packages that depend on grab_lints