diff --git a/packages/altive_lints/lib/altive_lints.dart b/packages/altive_lints/lib/altive_lints.dart index c7c7d0a..13cc25c 100644 --- a/packages/altive_lints/lib/altive_lints.dart +++ b/packages/altive_lints/lib/altive_lints.dart @@ -5,6 +5,7 @@ import 'src/lints/avoid_hardcoded_color.dart'; import 'src/lints/avoid_hardcoded_japanese.dart'; import 'src/lints/avoid_shrink_wrap_in_list_view.dart'; import 'src/lints/avoid_single_child.dart'; +import 'src/lints/prefer_dedicated_media_query_methods.dart'; import 'src/lints/prefer_space_between_elements.dart'; PluginBase createPlugin() => _AltivePlugin(); @@ -17,6 +18,7 @@ class _AltivePlugin extends PluginBase { const AvoidHardcodedJapanese(), const AvoidShrinkWrapInListView(), const AvoidSingleChild(), + const PreferDedicatedMediaQueryMethods(), const PreferSpaceBetweenElements(), ]; } diff --git a/packages/altive_lints/lib/src/lints/prefer_dedicated_media_query_methods.dart b/packages/altive_lints/lib/src/lints/prefer_dedicated_media_query_methods.dart new file mode 100644 index 0000000..a246991 --- /dev/null +++ b/packages/altive_lints/lib/src/lints/prefer_dedicated_media_query_methods.dart @@ -0,0 +1,56 @@ +import 'package:analyzer/error/listener.dart'; +import 'package:custom_lint_builder/custom_lint_builder.dart'; + +/// A `prefer_dedicated_media_query_methods` rule that encourages +/// the use of dedicated `MediaQuery` methods instead of +/// the generic `MediaQuery.of` or `MediaQuery.maybeOf`. +/// +/// Using specialized methods like `MediaQuery.sizeOf` or +/// `MediaQuery.viewInsetsOf` improves performance by reducing +/// unnecessary widget rebuilds. +/// +/// These methods directly access specific properties, +/// avoiding the overhead associated with the broader +/// context changes that trigger when using `MediaQuery.of`. +/// +/// ### Example +/// +/// #### BAD: +/// +/// ```dart +/// var size = MediaQuery.of(context).size; // LINT +/// var padding = MediaQuery.maybeOf(context)?.padding; // LINT +/// ``` +/// +/// #### GOOD: +/// +/// ```dart +/// var size = MediaQuery.sizeOf(context); +/// var padding = MediaQuery.viewInsetsOf(context); +/// ``` +class PreferDedicatedMediaQueryMethods extends DartLintRule { + const PreferDedicatedMediaQueryMethods() : super(code: _code); + + static const _code = LintCode( + name: 'prefer_dedicated_media_query_methods', + problemMessage: 'Prefer using dedicated MediaQuery methods instead of ' + 'MediaQuery.of or MediaQuery.maybeOf.', + correctionMessage: 'Consider using methods like MediaQuery.sizeOf or ' + 'MediaQuery.viewInsetsOf.', + ); + + @override + void run( + CustomLintResolver resolver, + ErrorReporter reporter, + CustomLintContext context, + ) { + context.registry.addMethodInvocation((node) { + final method = node.methodName.name; + final target = node.target?.toString(); + if (target == 'MediaQuery' && (method == 'of' || method == 'maybeOf')) { + reporter.reportErrorForNode(_code, node); + } + }); + } +} diff --git a/packages/altive_lints/lint_test/lints/prefer_dedicated_media_query_methods.dart b/packages/altive_lints/lint_test/lints/prefer_dedicated_media_query_methods.dart new file mode 100644 index 0000000..b40654c --- /dev/null +++ b/packages/altive_lints/lint_test/lints/prefer_dedicated_media_query_methods.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; + +class MyWidget extends StatelessWidget { + const MyWidget({super.key}); + + @override + Widget build(BuildContext context) { + // expect_lint: prefer_dedicated_media_query_methods + final size = MediaQuery.of(context).size; + // expect_lint: prefer_dedicated_media_query_methods + final viewInsets = MediaQuery.of(context).viewInsets; + return Column( + children: [ + Text('Size: $size'), + Text('ViewInsets: $viewInsets'), + ], + ); + } +}