From 51bddf5752f9818e9f919c56a0a2e924e8369ae2 Mon Sep 17 00:00:00 2001 From: Illia Aihistov Date: Tue, 7 Jul 2026 17:57:17 +0300 Subject: [PATCH 1/2] refactor: consolidate lint fix registration logic using a new RuleWithFixes interface --- lib/main.dart | 100 +++++------------- .../avoid_final_with_getter_rule.dart | 10 +- ...void_unnecessary_type_assertions_rule.dart | 20 +++- .../double_literal_format_rule.dart | 23 ++-- .../named_parameters_ordering_rule.dart | 15 ++- .../prefer_conditional_expressions_rule.dart | 15 ++- .../lints/prefer_first/prefer_first_rule.dart | 12 ++- .../lints/prefer_last/prefer_last_rule.dart | 8 +- .../use_nearest_context_rule.dart | 20 +++- lib/src/models/rule_with_fixes.dart | 16 +++ 10 files changed, 133 insertions(+), 106 deletions(-) create mode 100644 lib/src/models/rule_with_fixes.dart diff --git a/lib/main.dart b/lib/main.dart index 43c08108..cf3e91fc 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,38 +3,32 @@ import 'package:analysis_server_plugin/registry.dart'; import 'package:solid_lints/src/common/parameter_parser/analysis_options_loader.dart'; import 'package:solid_lints/src/lints/avoid_debug_print_in_release/avoid_debug_print_in_release_rule.dart'; import 'package:solid_lints/src/lints/avoid_final_with_getter/avoid_final_with_getter_rule.dart'; -import 'package:solid_lints/src/lints/avoid_final_with_getter/fixes/avoid_final_with_getter_fix.dart'; import 'package:solid_lints/src/lints/avoid_global_state/avoid_global_state_rule.dart'; +import 'package:solid_lints/src/lints/avoid_late_keyword/avoid_late_keyword_rule.dart'; import 'package:solid_lints/src/lints/avoid_non_null_assertion/avoid_non_null_assertion_rule.dart'; import 'package:solid_lints/src/lints/avoid_returning_widgets/avoid_returning_widgets_rule.dart'; import 'package:solid_lints/src/lints/avoid_unnecessary_return_variable/avoid_unnecessary_return_variable_rule.dart'; import 'package:solid_lints/src/lints/avoid_unnecessary_setstate/avoid_unnecessary_set_state_rule.dart'; import 'package:solid_lints/src/lints/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions_rule.dart'; -import 'package:solid_lints/src/lints/avoid_unnecessary_type_assertions/fixes/avoid_unnecessary_type_assertions_fix.dart'; import 'package:solid_lints/src/lints/avoid_unrelated_type_assertions/avoid_unrelated_type_assertions_rule.dart'; import 'package:solid_lints/src/lints/avoid_unused_parameters/avoid_unused_parameters_rule.dart'; import 'package:solid_lints/src/lints/cyclomatic_complexity/cyclomatic_complexity_rule.dart'; import 'package:solid_lints/src/lints/double_literal_format/double_literal_format_rule.dart'; -import 'package:solid_lints/src/lints/double_literal_format/fixes/double_literal_format_fix.dart'; import 'package:solid_lints/src/lints/function_lines_of_code/function_lines_of_code_rule.dart'; import 'package:solid_lints/src/lints/member_ordering/member_ordering_rule.dart'; -import 'package:solid_lints/src/lints/named_parameters_ordering/fixes/named_parameters_ordering_fix.dart'; import 'package:solid_lints/src/lints/named_parameters_ordering/named_parameters_ordering_rule.dart'; import 'package:solid_lints/src/lints/newline_before_return/newline_before_return_rule.dart'; import 'package:solid_lints/src/lints/no_empty_block/no_empty_block_rule.dart'; import 'package:solid_lints/src/lints/no_equal_then_else/no_equal_then_else_rule.dart'; import 'package:solid_lints/src/lints/no_magic_number/no_magic_number_rule.dart'; import 'package:solid_lints/src/lints/number_of_parameters/number_of_parameters_rule.dart'; -import 'package:solid_lints/src/lints/prefer_conditional_expressions/fixes/prefer_conditional_expressions_fix.dart'; import 'package:solid_lints/src/lints/prefer_conditional_expressions/prefer_conditional_expressions_rule.dart'; import 'package:solid_lints/src/lints/prefer_early_return/prefer_early_return_rule.dart'; -import 'package:solid_lints/src/lints/prefer_first/fixes/prefer_first_fix.dart'; import 'package:solid_lints/src/lints/prefer_first/prefer_first_rule.dart'; -import 'package:solid_lints/src/lints/prefer_last/fixes/prefer_last_fix.dart'; import 'package:solid_lints/src/lints/prefer_last/prefer_last_rule.dart'; import 'package:solid_lints/src/lints/proper_super_calls/proper_super_calls_rule.dart'; -import 'package:solid_lints/src/lints/use_nearest_context/fixes/rename_nearest_context_parameter_fix.dart'; import 'package:solid_lints/src/lints/use_nearest_context/use_nearest_context_rule.dart'; +import 'package:solid_lints/src/models/rule_with_fixes.dart'; /// The entry point for the Solid Lints analyser server plugin. /// @@ -54,88 +48,44 @@ class SolidLintsPlugin extends Plugin { void register(PluginRegistry registry) { final analysisLoader = AnalysisOptionsLoader(); - final avoidUnnecessaryTypeAssertionsRule = - AvoidUnnecessaryTypeAssertionsRule(); - final doubleLiteralFormatRule = DoubleLiteralFormatRule(); - final preferFirstRule = PreferFirstRule(); - final preferConditionalExpressionsRule = PreferConditionalExpressionsRule( - analysisOptionsLoader: analysisLoader, - ); - final preferLastRule = PreferLastRule(); - final lintRules = [ + AvoidDebugPrintInReleaseRule(), AvoidFinalWithGetterRule(), AvoidGlobalStateRule(), + AvoidLateKeywordRule(analysisOptionsLoader: analysisLoader), AvoidNonNullAssertionRule(analysisOptionsLoader: analysisLoader), - avoidUnnecessaryTypeAssertionsRule, - AvoidDebugPrintInReleaseRule(), - doubleLiteralFormatRule, - ProperSuperCallsRule(), - NamedParametersOrderingRule(analysisOptionsLoader: analysisLoader), AvoidReturningWidgetsRule(analysisOptionsLoader: analysisLoader), - MemberOrderingRule(analysisOptionsLoader: analysisLoader), - AvoidUnusedParametersRule(analysisOptionsLoader: analysisLoader), - NumberOfParametersRule(analysisOptionsLoader: analysisLoader), - FunctionLinesOfCodeRule(analysisOptionsLoader: analysisLoader), - CyclomaticComplexityRule(analysisOptionsLoader: analysisLoader), - NoEmptyBlockRule(analysisOptionsLoader: analysisLoader), - UseNearestContextRule(), - NoMagicNumberRule(analysisOptionsLoader: analysisLoader), - preferFirstRule, - preferConditionalExpressionsRule, - preferLastRule, - // TODO: Add more lint rules and use analysisLoader - // for rules that need parameters - // For example: `CyclomaticComplexityRule(analysisLoader)` AvoidUnnecessaryReturnVariableRule(), AvoidUnnecessarySetStateRule(), + AvoidUnnecessaryTypeAssertionsRule(), AvoidUnrelatedTypeAssertionsRule(), + AvoidUnusedParametersRule(analysisOptionsLoader: analysisLoader), + CyclomaticComplexityRule(analysisOptionsLoader: analysisLoader), + DoubleLiteralFormatRule(), + FunctionLinesOfCodeRule(analysisOptionsLoader: analysisLoader), + MemberOrderingRule(analysisOptionsLoader: analysisLoader), + NamedParametersOrderingRule(analysisOptionsLoader: analysisLoader), NewlineBeforeReturnRule(), + NoEmptyBlockRule(analysisOptionsLoader: analysisLoader), NoEqualThenElseRule(), + NoMagicNumberRule(analysisOptionsLoader: analysisLoader), + NumberOfParametersRule(analysisOptionsLoader: analysisLoader), + PreferConditionalExpressionsRule(analysisOptionsLoader: analysisLoader), PreferEarlyReturnRule(), + PreferFirstRule(), + PreferLastRule(), + ProperSuperCallsRule(), + UseNearestContextRule(), ]; for (final lintRule in lintRules) { registry.registerLintRule(lintRule); + if (lintRule is RuleWithFixes) { + final ruleWithFixes = lintRule as RuleWithFixes; + for (final entry in ruleWithFixes.fixesForCodes) { + registry.registerFixForRule(entry.key, entry.value); + } + } } - - for (final code in doubleLiteralFormatRule.diagnosticCodes) { - registry.registerFixForRule(code, DoubleLiteralFormatFix.new); - } - - registry.registerFixForRule( - AvoidFinalWithGetterRule.code, - AvoidFinalWithGetterFix.new, - ); - - registry.registerFixForRule( - avoidUnnecessaryTypeAssertionsRule.diagnosticCode, - AvoidUnnecessaryTypeAssertionsFix.new, - ); - - registry.registerFixForRule( - UseNearestContextRule.code, - RenameNearestContextParameterFix.new, - ); - - registry.registerFixForRule( - preferFirstRule.diagnosticCode, - PreferFirstFix.new, - ); - - registry.registerFixForRule( - preferLastRule.diagnosticCode, - PreferLastFix.new, - ); - - registry.registerFixForRule( - preferConditionalExpressionsRule.diagnosticCode, - PreferConditionalExpressionsFix.new, - ); - - registry.registerFixForRule( - NamedParametersOrderingRule.code, - NamedParametersOrderingFix.new, - ); } } diff --git a/lib/src/lints/avoid_final_with_getter/avoid_final_with_getter_rule.dart b/lib/src/lints/avoid_final_with_getter/avoid_final_with_getter_rule.dart index 727e3dfe..dbc5c144 100644 --- a/lib/src/lints/avoid_final_with_getter/avoid_final_with_getter_rule.dart +++ b/lib/src/lints/avoid_final_with_getter/avoid_final_with_getter_rule.dart @@ -2,7 +2,9 @@ import 'package:analyzer/analysis_rule/analysis_rule.dart'; import 'package:analyzer/analysis_rule/rule_context.dart'; import 'package:analyzer/analysis_rule/rule_visitor_registry.dart'; import 'package:analyzer/error/error.dart'; +import 'package:solid_lints/src/lints/avoid_final_with_getter/fixes/avoid_final_with_getter_fix.dart'; import 'package:solid_lints/src/lints/avoid_final_with_getter/visitors/avoid_final_with_getter_visitor.dart'; +import 'package:solid_lints/src/models/rule_with_fixes.dart'; /// Avoid using final private fields with getters. /// @@ -30,7 +32,7 @@ import 'package:solid_lints/src/lints/avoid_final_with_getter/visitors/avoid_fin /// } /// ``` /// -class AvoidFinalWithGetterRule extends AnalysisRule { +class AvoidFinalWithGetterRule extends AnalysisRule implements RuleWithFixes { /// This lint rule represents /// the error whether we use final private fields with getters. static const lintName = 'avoid_final_with_getter'; @@ -44,11 +46,15 @@ class AvoidFinalWithGetterRule extends AnalysisRule { /// Creates a new instance of [AvoidFinalWithGetterRule] AvoidFinalWithGetterRule() - : super(name: lintName, description: code.problemMessage); + : super(name: lintName, description: code.problemMessage); @override LintCode get diagnosticCode => code; + @override + Iterable> get fixesForCodes => + const [MapEntry(code, AvoidFinalWithGetterFix.new)]; + @override void registerNodeProcessors( RuleVisitorRegistry registry, diff --git a/lib/src/lints/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions_rule.dart b/lib/src/lints/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions_rule.dart index 906c934b..4cdfe922 100644 --- a/lib/src/lints/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions_rule.dart +++ b/lib/src/lints/avoid_unnecessary_type_assertions/avoid_unnecessary_type_assertions_rule.dart @@ -2,15 +2,18 @@ import 'package:analyzer/analysis_rule/analysis_rule.dart'; import 'package:analyzer/analysis_rule/rule_context.dart'; import 'package:analyzer/analysis_rule/rule_visitor_registry.dart'; import 'package:analyzer/error/error.dart'; +import 'package:solid_lints/src/lints/avoid_unnecessary_type_assertions/fixes/avoid_unnecessary_type_assertions_fix.dart'; import 'package:solid_lints/src/lints/avoid_unnecessary_type_assertions/visitors/unnecessary_is_expression_visitor.dart'; import 'package:solid_lints/src/lints/avoid_unnecessary_type_assertions/visitors/unnecessary_where_type_visitor.dart'; +import 'package:solid_lints/src/models/rule_with_fixes.dart'; /// Warns about unnecessary usage of `is` and `whereType` operators. /// /// ### Example: /// {@macro solid_lints.avoid_unnecessary_type_assertions.example_is} /// {@macro solid_lints.avoid_unnecessary_type_assertions.example_where} -class AvoidUnnecessaryTypeAssertionsRule extends AnalysisRule { +class AvoidUnnecessaryTypeAssertionsRule extends AnalysisRule + implements RuleWithFixes { /// The name of 'is' operator static const operatorIsName = 'is'; @@ -26,9 +29,6 @@ class AvoidUnnecessaryTypeAssertionsRule extends AnalysisRule { "Unnecessary usage of the {0}.", ); - @override - DiagnosticCode get diagnosticCode => _unnecessaryTypeAssertionsCode; - /// Creates a new instance of [AvoidUnnecessaryTypeAssertionsRule] AvoidUnnecessaryTypeAssertionsRule() : super( @@ -36,6 +36,18 @@ class AvoidUnnecessaryTypeAssertionsRule extends AnalysisRule { description: "Unnecessary usage of typecast operators.", ); + @override + DiagnosticCode get diagnosticCode => _unnecessaryTypeAssertionsCode; + + @override + Iterable> get fixesForCodes => + const [ + MapEntry( + _unnecessaryTypeAssertionsCode, + AvoidUnnecessaryTypeAssertionsFix.new, + ), + ]; + @override void registerNodeProcessors( RuleVisitorRegistry registry, diff --git a/lib/src/lints/double_literal_format/double_literal_format_rule.dart b/lib/src/lints/double_literal_format/double_literal_format_rule.dart index d90d3726..77b9f9c2 100644 --- a/lib/src/lints/double_literal_format/double_literal_format_rule.dart +++ b/lib/src/lints/double_literal_format/double_literal_format_rule.dart @@ -2,7 +2,9 @@ import 'package:analyzer/analysis_rule/analysis_rule.dart'; import 'package:analyzer/analysis_rule/rule_context.dart'; import 'package:analyzer/analysis_rule/rule_visitor_registry.dart'; import 'package:analyzer/error/error.dart'; +import 'package:solid_lints/src/lints/double_literal_format/fixes/double_literal_format_fix.dart'; import 'package:solid_lints/src/lints/double_literal_format/visitors/double_literal_format_visitor.dart'; +import 'package:solid_lints/src/models/rule_with_fixes.dart'; /// A `double_literal_format` rule which /// checks that double literals should begin with 0. instead of just ., @@ -23,7 +25,8 @@ import 'package:solid_lints/src/lints/double_literal_format/visitors/double_lite /// var a = 5.23, b = 0.16e+5, c = -0.25, d = -0.4e-5; /// ``` /// {@endtemplate} -class DoubleLiteralFormatRule extends MultiAnalysisRule { +class DoubleLiteralFormatRule extends MultiAnalysisRule + implements RuleWithFixes { /// This lint rule represents /// the error whether we use bad formatted double literals. static const lintName = 'double_literal_format'; @@ -96,13 +99,6 @@ class DoubleLiteralFormatRule extends MultiAnalysisRule { uniqueName: 'trailingZero', ); - @override - List get diagnosticCodes => [ - leadingZeroCode, - leadingDecimalCode, - trailingZeroCode, - ]; - /// Creates a new instance of [DoubleLiteralFormatRule] DoubleLiteralFormatRule() : super( @@ -113,6 +109,17 @@ class DoubleLiteralFormatRule extends MultiAnalysisRule { 'should not start with a leading 0', ); + @override + List get diagnosticCodes => [ + leadingZeroCode, + leadingDecimalCode, + trailingZeroCode, + ]; + + @override + Iterable> get fixesForCodes => + diagnosticCodes.map((code) => MapEntry(code, DoubleLiteralFormatFix.new)); + @override void registerNodeProcessors( RuleVisitorRegistry registry, diff --git a/lib/src/lints/named_parameters_ordering/named_parameters_ordering_rule.dart b/lib/src/lints/named_parameters_ordering/named_parameters_ordering_rule.dart index 110ee5de..1c080b85 100644 --- a/lib/src/lints/named_parameters_ordering/named_parameters_ordering_rule.dart +++ b/lib/src/lints/named_parameters_ordering/named_parameters_ordering_rule.dart @@ -1,9 +1,11 @@ import 'package:analyzer/analysis_rule/rule_context.dart'; import 'package:analyzer/analysis_rule/rule_visitor_registry.dart'; import 'package:analyzer/error/error.dart'; +import 'package:solid_lints/src/lints/named_parameters_ordering/fixes/named_parameters_ordering_fix.dart'; import 'package:solid_lints/src/lints/named_parameters_ordering/models/named_parameters_ordering_parameters.dart'; import 'package:solid_lints/src/lints/named_parameters_ordering/models/parameter_type.dart'; import 'package:solid_lints/src/lints/named_parameters_ordering/visitors/named_parameters_ordering_visitor.dart'; +import 'package:solid_lints/src/models/rule_with_fixes.dart'; import 'package:solid_lints/src/models/solid_lint_rule.dart'; /// A lint which allows to enforce a particular named parameter ordering @@ -102,7 +104,8 @@ import 'package:solid_lints/src/models/solid_lint_rule.dart'; /// } /// ``` class NamedParametersOrderingRule - extends SolidLintRule { + extends SolidLintRule + implements RuleWithFixes { /// The name of this lint rule. static const lintName = 'named_parameters_ordering'; @@ -112,9 +115,6 @@ class NamedParametersOrderingRule '{0} named parameters should be before {1} named parameters.', ); - @override - LintCode get diagnosticCode => code; - /// Creates a new instance of [NamedParametersOrderingRule]. NamedParametersOrderingRule({ required super.analysisOptionsLoader, @@ -126,6 +126,13 @@ class NamedParametersOrderingRule parametersParser: NamedParametersOrderingParameters.fromJson, ); + @override + LintCode get diagnosticCode => code; + + @override + Iterable> get fixesForCodes => + const [MapEntry(code, NamedParametersOrderingFix.new)]; + @override void registerNodeProcessors( RuleVisitorRegistry registry, diff --git a/lib/src/lints/prefer_conditional_expressions/prefer_conditional_expressions_rule.dart b/lib/src/lints/prefer_conditional_expressions/prefer_conditional_expressions_rule.dart index 5f501972..bb3d8a3c 100644 --- a/lib/src/lints/prefer_conditional_expressions/prefer_conditional_expressions_rule.dart +++ b/lib/src/lints/prefer_conditional_expressions/prefer_conditional_expressions_rule.dart @@ -1,8 +1,10 @@ import 'package:analyzer/analysis_rule/rule_context.dart'; import 'package:analyzer/analysis_rule/rule_visitor_registry.dart'; import 'package:analyzer/error/error.dart'; +import 'package:solid_lints/src/lints/prefer_conditional_expressions/fixes/prefer_conditional_expressions_fix.dart'; import 'package:solid_lints/src/lints/prefer_conditional_expressions/models/prefer_conditional_expressions_parameters.dart'; import 'package:solid_lints/src/lints/prefer_conditional_expressions/visitors/prefer_conditional_expressions_visitor.dart'; +import 'package:solid_lints/src/models/rule_with_fixes.dart'; import 'package:solid_lints/src/models/solid_lint_rule.dart'; // Inspired by TSLint (https://palantir.github.io/tslint/rules/prefer-conditional-expression/) @@ -56,7 +58,8 @@ import 'package:solid_lints/src/models/solid_lint_rule.dart'; /// } /// ``` class PreferConditionalExpressionsRule - extends SolidLintRule { + extends SolidLintRule + implements RuleWithFixes { /// This lint rule represents the error when an if-else statement /// can be simplified to a conditional expression. static const lintName = 'prefer_conditional_expressions'; @@ -66,9 +69,6 @@ class PreferConditionalExpressionsRule 'Prefer conditional expression.', ); - @override - LintCode get diagnosticCode => _code; - /// Creates a new instance of [PreferConditionalExpressionsRule] PreferConditionalExpressionsRule({ required super.analysisOptionsLoader, @@ -78,6 +78,13 @@ class PreferConditionalExpressionsRule parametersParser: PreferConditionalExpressionsParameters.fromJson, ); + @override + LintCode get diagnosticCode => _code; + + @override + Iterable> get fixesForCodes => + const [MapEntry(_code, PreferConditionalExpressionsFix.new)]; + @override void registerNodeProcessors( RuleVisitorRegistry registry, diff --git a/lib/src/lints/prefer_first/prefer_first_rule.dart b/lib/src/lints/prefer_first/prefer_first_rule.dart index b644cffe..bc52c5de 100644 --- a/lib/src/lints/prefer_first/prefer_first_rule.dart +++ b/lib/src/lints/prefer_first/prefer_first_rule.dart @@ -1,7 +1,9 @@ import 'package:analyzer/analysis_rule/rule_context.dart'; import 'package:analyzer/analysis_rule/rule_visitor_registry.dart'; import 'package:analyzer/error/error.dart'; +import 'package:solid_lints/src/lints/prefer_first/fixes/prefer_first_fix.dart'; import 'package:solid_lints/src/lints/prefer_first/visitors/prefer_first_visitor.dart'; +import 'package:solid_lints/src/models/rule_with_fixes.dart'; import 'package:solid_lints/src/models/solid_lint_rule.dart'; /// Warns about usage of iterable[0] or iterable.elementAt(0) instead of @@ -25,7 +27,7 @@ import 'package:solid_lints/src/models/solid_lint_rule.dart'; /// /// a.first; // OK /// ``` -class PreferFirstRule extends SolidLintRule { +class PreferFirstRule extends SolidLintRule implements RuleWithFixes { /// This lint rule represents the error if number of /// parameters reaches the maximum value. static const lintName = 'prefer_first'; @@ -35,11 +37,15 @@ class PreferFirstRule extends SolidLintRule { "Use first instead of accessing the element at zero index.", ); + /// Creates a new instance of [PreferFirstRule] + PreferFirstRule() : super(name: lintName, description: _code.problemMessage); + @override LintCode get diagnosticCode => _code; - /// Creates a new instance of [PreferFirstRule] - PreferFirstRule() : super(name: lintName, description: _code.problemMessage); + @override + Iterable> get fixesForCodes => + const [MapEntry(_code, PreferFirstFix.new)]; @override void registerNodeProcessors( diff --git a/lib/src/lints/prefer_last/prefer_last_rule.dart b/lib/src/lints/prefer_last/prefer_last_rule.dart index ff75f5ba..525b1bbd 100644 --- a/lib/src/lints/prefer_last/prefer_last_rule.dart +++ b/lib/src/lints/prefer_last/prefer_last_rule.dart @@ -1,7 +1,9 @@ import 'package:analyzer/analysis_rule/rule_context.dart'; import 'package:analyzer/analysis_rule/rule_visitor_registry.dart'; import 'package:analyzer/error/error.dart'; +import 'package:solid_lints/src/lints/prefer_last/fixes/prefer_last_fix.dart'; import 'package:solid_lints/src/lints/prefer_last/visitors/prefer_last_visitor.dart'; +import 'package:solid_lints/src/models/rule_with_fixes.dart'; import 'package:solid_lints/src/models/solid_lint_rule.dart'; /// Warns about usage of `iterable[length - 1]` or @@ -25,7 +27,7 @@ import 'package:solid_lints/src/models/solid_lint_rule.dart'; /// /// a.last; // OK /// ``` -class PreferLastRule extends SolidLintRule { +class PreferLastRule extends SolidLintRule implements RuleWithFixes { /// This lint rule represents the error if iterable /// access can be simplified. static const lintName = 'prefer_last'; @@ -41,6 +43,10 @@ class PreferLastRule extends SolidLintRule { @override LintCode get diagnosticCode => _code; + @override + Iterable> get fixesForCodes => + const [MapEntry(_code, PreferLastFix.new)]; + @override void registerNodeProcessors( RuleVisitorRegistry registry, diff --git a/lib/src/lints/use_nearest_context/use_nearest_context_rule.dart b/lib/src/lints/use_nearest_context/use_nearest_context_rule.dart index 56af784a..c0327e9c 100644 --- a/lib/src/lints/use_nearest_context/use_nearest_context_rule.dart +++ b/lib/src/lints/use_nearest_context/use_nearest_context_rule.dart @@ -2,7 +2,10 @@ import 'package:analyzer/analysis_rule/analysis_rule.dart'; import 'package:analyzer/analysis_rule/rule_context.dart'; import 'package:analyzer/analysis_rule/rule_visitor_registry.dart'; import 'package:analyzer/error/error.dart'; +import 'package:solid_lints/src/lints/use_nearest_context/fixes/rename_nearest_context_parameter_fix.dart'; +import 'package:solid_lints/src/lints/use_nearest_context/fixes/replace_with_nearest_context_parameter_fix.dart'; import 'package:solid_lints/src/lints/use_nearest_context/visitors/use_nearest_context_visitor.dart'; +import 'package:solid_lints/src/models/rule_with_fixes.dart'; /// A rule which checks that we use BuildContext from the nearest available /// scope. @@ -49,7 +52,7 @@ import 'package:solid_lints/src/lints/use_nearest_context/visitors/use_nearest_c /// } /// ``` /// -class UseNearestContextRule extends AnalysisRule { +class UseNearestContextRule extends AnalysisRule implements RuleWithFixes { /// This lint rule represents the error if BuildContext is used not from the /// nearest available scope static const lintName = 'use_nearest_context'; @@ -62,14 +65,21 @@ class UseNearestContextRule extends AnalysisRule { /// Creates a new instance of [UseNearestContextRule]. UseNearestContextRule() - : super( - name: lintName, - description: code.problemMessage, - ); + : super( + name: lintName, + description: code.problemMessage, + ); @override LintCode get diagnosticCode => code; + @override + Iterable> get fixesForCodes => + const [ + MapEntry(code, RenameNearestContextParameterFix.new), + MapEntry(code, ReplaceWithNearestContextParameterFix.new), + ]; + @override void registerNodeProcessors( RuleVisitorRegistry registry, diff --git a/lib/src/models/rule_with_fixes.dart b/lib/src/models/rule_with_fixes.dart new file mode 100644 index 00000000..ed703f3c --- /dev/null +++ b/lib/src/models/rule_with_fixes.dart @@ -0,0 +1,16 @@ +import 'package:analysis_server_plugin/edit/dart/correction_producer.dart'; +import 'package:analyzer/dart/analysis/results.dart'; +import 'package:analyzer/error/error.dart'; + +/// A function that creates a [CorrectionProducer] for a given context. +typedef ProducerGenerator = + CorrectionProducer Function({ + required CorrectionProducerContext context, + }); + +/// An interface for lint rules that have associated quick fixes. +abstract interface class RuleWithFixes { + /// Returns the map entries of diagnostic code and its associated fix + /// generator. + Iterable> get fixesForCodes; +} From a9bc96e3c45cc107e3313cdc5a841871650bc095 Mon Sep 17 00:00:00 2001 From: Illia Aihistov Date: Tue, 7 Jul 2026 18:08:18 +0300 Subject: [PATCH 2/2] refactor: simplify lint rule fix registration by removing redundant type cast variable --- lib/main.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index cf3e91fc..40eaeed6 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -81,8 +81,7 @@ class SolidLintsPlugin extends Plugin { for (final lintRule in lintRules) { registry.registerLintRule(lintRule); if (lintRule is RuleWithFixes) { - final ruleWithFixes = lintRule as RuleWithFixes; - for (final entry in ruleWithFixes.fixesForCodes) { + for (final entry in (lintRule as RuleWithFixes).fixesForCodes) { registry.registerFixForRule(entry.key, entry.value); } }