From c90a71a27109163b006b397edc5fbccb2db223d1 Mon Sep 17 00:00:00 2001 From: Islam-Shaaban-Ibrahim Date: Thu, 16 Apr 2026 14:36:06 +0200 Subject: [PATCH 1/2] Migrate avoid_late_keyword rule (default behavior) and tests --- .../avoid_late_keyword_rule.dart | 82 ++++++------------- .../visitors/avoid_late_keyword_visitor.dart | 25 ++++++ test/avoid_late_keyword_rule_test.dart | 56 +++++++++++++ 3 files changed, 105 insertions(+), 58 deletions(-) create mode 100644 lib/src/lints/avoid_late_keyword/visitors/avoid_late_keyword_visitor.dart create mode 100644 test/avoid_late_keyword_rule_test.dart diff --git a/lib/src/lints/avoid_late_keyword/avoid_late_keyword_rule.dart b/lib/src/lints/avoid_late_keyword/avoid_late_keyword_rule.dart index 5110bbf7..492749c3 100644 --- a/lib/src/lints/avoid_late_keyword/avoid_late_keyword_rule.dart +++ b/lib/src/lints/avoid_late_keyword/avoid_late_keyword_rule.dart @@ -1,10 +1,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/dart/ast/ast.dart'; -import 'package:analyzer/error/listener.dart'; -import 'package:custom_lint_builder/custom_lint_builder.dart'; -import 'package:solid_lints/src/lints/avoid_late_keyword/models/avoid_late_keyword_parameters.dart'; -import 'package:solid_lints/src/models/rule_config.dart'; -import 'package:solid_lints/src/models/solid_lint_rule.dart'; -import 'package:solid_lints/src/utils/types_utils.dart'; +import 'package:analyzer/dart/ast/visitor.dart'; +import 'package:analyzer/error/error.dart'; +import 'package:solid_lints/src/lints/avoid_late_keyword/visitors/avoid_late_keyword_visitor.dart'; /// Avoid `late` keyword /// @@ -47,63 +47,29 @@ import 'package:solid_lints/src/utils/types_utils.dart'; /// } /// } /// ``` -class AvoidLateKeywordRule extends SolidLintRule { - /// This lint rule represents - /// the error whether we use `late` keyword. - static const lintName = 'avoid_late_keyword'; +class AvoidLateKeywordRule extends AnalysisRule { + static const String _lintName = 'avoid_late_keyword'; - AvoidLateKeywordRule._(super.config); + static const LintCode _code = LintCode( + _lintName, + 'Avoid using the "late" keyword. It may result in runtime exceptions.', + ); - /// Creates a new instance of [AvoidLateKeywordRule] - /// based on the lint configuration. - factory AvoidLateKeywordRule.createRule(CustomLintConfigs configs) { - final rule = RuleConfig( - configs: configs, - name: lintName, - paramsParser: AvoidLateKeywordParameters.fromJson, - problemMessage: (_) => 'Avoid using the "late" keyword. ' - 'It may result in runtime exceptions.', - ); + /// Creates an instance of [AvoidLateKeywordRule]. + AvoidLateKeywordRule() + : super( + name: _lintName, + description: 'Warns against using the late keyword.', + ); - return AvoidLateKeywordRule._(rule); - } + @override + LintCode get diagnosticCode => _code; @override - void run( - CustomLintResolver resolver, - DiagnosticReporter reporter, - CustomLintContext context, + void registerNodeProcessors( + RuleVisitorRegistry registry, + RuleContext context, ) { - context.registry.addVariableDeclaration((node) { - if (_shouldLint(node)) { - reporter.atNode(node, code); - } - }); - } - - bool _shouldLint(VariableDeclaration node) { - final isLateDeclaration = node.isLate; - if (!isLateDeclaration) return false; - - final hasIgnoredType = _hasIgnoredType(node); - if (hasIgnoredType) return false; - - final allowInitialized = config.parameters.allowInitialized; - if (!allowInitialized) return true; - - final hasInitializer = node.initializer != null; - return !hasInitializer; - } - - bool _hasIgnoredType(VariableDeclaration node) { - final ignoredTypes = config.parameters.ignoredTypes.toSet(); - if (ignoredTypes.isEmpty) return false; - - final variableType = node.declaredFragment?.element.type; - if (variableType == null) return false; - - return variableType.hasIgnoredType( - ignoredTypes: ignoredTypes, - ); + registry.addVariableDeclaration(this, AvoidLateKeywordVisitor(this)); } } diff --git a/lib/src/lints/avoid_late_keyword/visitors/avoid_late_keyword_visitor.dart b/lib/src/lints/avoid_late_keyword/visitors/avoid_late_keyword_visitor.dart new file mode 100644 index 00000000..4200f5bd --- /dev/null +++ b/lib/src/lints/avoid_late_keyword/visitors/avoid_late_keyword_visitor.dart @@ -0,0 +1,25 @@ +import 'package:analyzer/dart/ast/ast.dart'; +import 'package:analyzer/dart/ast/visitor.dart'; +import 'package:solid_lints/src/lints/avoid_late_keyword/avoid_late_keyword_rule.dart'; + +/// Visitor for [AvoidLateKeywordRule]. +class AvoidLateKeywordVisitor extends SimpleAstVisitor { + /// The rule to which the visitor belongs. + final AvoidLateKeywordRule rule; + + /// Creates an instance of [AvoidLateKeywordVisitor]. + AvoidLateKeywordVisitor(this.rule); + + @override + void visitVariableDeclaration(VariableDeclaration node) { + if (!node.isLate) { + return; + } + + if (node.initializer != null) { + return; + } + + rule.reportAtNode(node); + } +} diff --git a/test/avoid_late_keyword_rule_test.dart b/test/avoid_late_keyword_rule_test.dart new file mode 100644 index 00000000..d01da4c7 --- /dev/null +++ b/test/avoid_late_keyword_rule_test.dart @@ -0,0 +1,56 @@ +import 'package:analyzer_testing/analysis_rule/analysis_rule.dart'; +import 'package:solid_lints/src/lints/avoid_late_keyword/avoid_late_keyword_rule.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +void main() { + defineReflectiveSuite(() { + defineReflectiveTests(AvoidLateKeywordRuleTest); + }); +} + +@reflectiveTest +class AvoidLateKeywordRuleTest extends AnalysisRuleTest { + @override + void setUp() { + rule = AvoidLateKeywordRule(); + super.setUp(); + } + + void test_reports_uninitialized_late_field() async { + await assertDiagnostics( + r''' +class Test { + late final int field; +} +''', + [lint(30, 5)], + ); + } + + void test_reports_uninitialized_late_local_variable() async { + await assertDiagnostics( + r''' +void m() { + late final String value; +} +''', + [lint(31, 5)], + ); + } + + void test_does_not_report_initialized_late_variable() async { + await assertNoDiagnostics(r''' +class Test { + late final int field = 1; +} +'''); + } + + void test_does_not_report_non_late_variable() async { + await assertNoDiagnostics(r''' +class Test { + final int field = 1; +} +'''); + } +} From 730d708904423002ccd1a028f61b700d6898c1c3 Mon Sep 17 00:00:00 2001 From: Andrew Bekhiet Date: Thu, 4 Jun 2026 02:15:30 +0300 Subject: [PATCH 2/2] feat: read parameter by extending SolidLintRule fix: add old behavior test: migrate avoid late keyword rule tests --- .../avoid_late_keyword_rule.dart | 22 +- .../visitors/avoid_late_keyword_visitor.dart | 43 ++- .../allow_initialized/analysis_options.yaml | 10 - ...d_late_keyword_allow_initialized_test.dart | 84 ----- .../no_generics/analysis_options.yaml | 10 - .../avoid_late_keyword_no_generics_test.dart | 52 --- .../with_generics/analysis_options.yaml | 14 - ...avoid_late_keyword_with_generics_test.dart | 114 ------ test/avoid_late_keyword_rule_test.dart | 330 +++++++++++++++++- 9 files changed, 360 insertions(+), 319 deletions(-) delete mode 100644 lint_test/avoid_late_keyword/allow_initialized/analysis_options.yaml delete mode 100644 lint_test/avoid_late_keyword/allow_initialized/avoid_late_keyword_allow_initialized_test.dart delete mode 100644 lint_test/avoid_late_keyword/no_generics/analysis_options.yaml delete mode 100644 lint_test/avoid_late_keyword/no_generics/avoid_late_keyword_no_generics_test.dart delete mode 100644 lint_test/avoid_late_keyword/with_generics/analysis_options.yaml delete mode 100644 lint_test/avoid_late_keyword/with_generics/avoid_late_keyword_with_generics_test.dart diff --git a/lib/src/lints/avoid_late_keyword/avoid_late_keyword_rule.dart b/lib/src/lints/avoid_late_keyword/avoid_late_keyword_rule.dart index 492749c3..0b288a0d 100644 --- a/lib/src/lints/avoid_late_keyword/avoid_late_keyword_rule.dart +++ b/lib/src/lints/avoid_late_keyword/avoid_late_keyword_rule.dart @@ -1,10 +1,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/dart/ast/ast.dart'; -import 'package:analyzer/dart/ast/visitor.dart'; import 'package:analyzer/error/error.dart'; +import 'package:solid_lints/src/lints/avoid_late_keyword/models/avoid_late_keyword_parameters.dart'; import 'package:solid_lints/src/lints/avoid_late_keyword/visitors/avoid_late_keyword_visitor.dart'; +import 'package:solid_lints/src/models/solid_lint_rule.dart'; /// Avoid `late` keyword /// @@ -47,7 +46,7 @@ import 'package:solid_lints/src/lints/avoid_late_keyword/visitors/avoid_late_key /// } /// } /// ``` -class AvoidLateKeywordRule extends AnalysisRule { +class AvoidLateKeywordRule extends SolidLintRule { static const String _lintName = 'avoid_late_keyword'; static const LintCode _code = LintCode( @@ -56,10 +55,11 @@ class AvoidLateKeywordRule extends AnalysisRule { ); /// Creates an instance of [AvoidLateKeywordRule]. - AvoidLateKeywordRule() - : super( + AvoidLateKeywordRule({required super.analysisOptionsLoader}) + : super.withParameters( name: _lintName, description: 'Warns against using the late keyword.', + parametersParser: AvoidLateKeywordParameters.fromJson, ); @override @@ -70,6 +70,14 @@ class AvoidLateKeywordRule extends AnalysisRule { RuleVisitorRegistry registry, RuleContext context, ) { - registry.addVariableDeclaration(this, AvoidLateKeywordVisitor(this)); + final parameters = + getParametersForContext(context) ?? const AvoidLateKeywordParameters(); + + final visitor = AvoidLateKeywordVisitor(this, parameters); + + registry.addVariableDeclaration( + this, + visitor, + ); } } diff --git a/lib/src/lints/avoid_late_keyword/visitors/avoid_late_keyword_visitor.dart b/lib/src/lints/avoid_late_keyword/visitors/avoid_late_keyword_visitor.dart index 4200f5bd..fc1fa960 100644 --- a/lib/src/lints/avoid_late_keyword/visitors/avoid_late_keyword_visitor.dart +++ b/lib/src/lints/avoid_late_keyword/visitors/avoid_late_keyword_visitor.dart @@ -1,25 +1,48 @@ import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/visitor.dart'; import 'package:solid_lints/src/lints/avoid_late_keyword/avoid_late_keyword_rule.dart'; +import 'package:solid_lints/src/lints/avoid_late_keyword/models/avoid_late_keyword_parameters.dart'; +import 'package:solid_lints/src/utils/types_utils.dart'; /// Visitor for [AvoidLateKeywordRule]. class AvoidLateKeywordVisitor extends SimpleAstVisitor { - /// The rule to which the visitor belongs. - final AvoidLateKeywordRule rule; + final AvoidLateKeywordRule _rule; + + final AvoidLateKeywordParameters _parameters; /// Creates an instance of [AvoidLateKeywordVisitor]. - AvoidLateKeywordVisitor(this.rule); + AvoidLateKeywordVisitor(this._rule, this._parameters); @override void visitVariableDeclaration(VariableDeclaration node) { - if (!node.isLate) { - return; - } + if (!_shouldReport(node)) return; + + _rule.reportAtNode(node); + } + + bool _shouldReport(VariableDeclaration node) { + final isLateDeclaration = node.isLate; + if (!isLateDeclaration) return false; + + final hasIgnoredType = _hasIgnoredType(node); + if (hasIgnoredType) return false; + + final allowInitialized = _parameters.allowInitialized; + if (!allowInitialized) return true; + + final hasInitializer = node.initializer != null; + return !hasInitializer; + } + + bool _hasIgnoredType(VariableDeclaration node) { + final ignoredTypes = _parameters.ignoredTypes.toSet(); + if (ignoredTypes.isEmpty) return false; - if (node.initializer != null) { - return; - } + final variableType = node.declaredFragment?.element.type; + if (variableType == null) return false; - rule.reportAtNode(node); + return variableType.hasIgnoredType( + ignoredTypes: ignoredTypes, + ); } } diff --git a/lint_test/avoid_late_keyword/allow_initialized/analysis_options.yaml b/lint_test/avoid_late_keyword/allow_initialized/analysis_options.yaml deleted file mode 100644 index 7f92efe8..00000000 --- a/lint_test/avoid_late_keyword/allow_initialized/analysis_options.yaml +++ /dev/null @@ -1,10 +0,0 @@ -analyzer: - plugins: - - ../custom_lint - -custom_lint: - rules: - - avoid_late_keyword: - allow_initialized: false - ignored_types: - - Animation diff --git a/lint_test/avoid_late_keyword/allow_initialized/avoid_late_keyword_allow_initialized_test.dart b/lint_test/avoid_late_keyword/allow_initialized/avoid_late_keyword_allow_initialized_test.dart deleted file mode 100644 index 05af24d1..00000000 --- a/lint_test/avoid_late_keyword/allow_initialized/avoid_late_keyword_allow_initialized_test.dart +++ /dev/null @@ -1,84 +0,0 @@ -// ignore_for_file: prefer_const_declarations, unused_local_variable, prefer_match_file_name -// ignore_for_file: avoid_global_state - -abstract class Animation {} - -class AnimationController implements Animation {} - -class SubAnimationController extends AnimationController {} - -class ColorTween {} - -/// Check "late" keyword fail -/// -/// `avoid_late_keyword` -/// allow_initialized option disabled -class AvoidLateKeyword { - /// ignored_types: Animation - late final Animation animation1; - - /// ignored_types: Animation - late final animation2 = AnimationController(); - - /// ignored_types: Animation - late final animation3 = SubAnimationController(); - - /// expect_lint: avoid_late_keyword - late final ColorTween colorTween1; - - /// expect_lint: avoid_late_keyword - late final colorTween2 = ColorTween(); - - /// expect_lint: avoid_late_keyword - late final colorTween3 = colorTween2; - - /// ignored_types: Animation - late final AnimationController controller1; - - /// expect_lint: avoid_late_keyword - late final field1 = 'string'; - - /// expect_lint: avoid_late_keyword - late final String field2; - - /// expect_lint: avoid_late_keyword - late final String field3 = 'string'; - - /// expect_lint: avoid_late_keyword - late final field4; - - void test() { - /// ignored_types: Animation - late final Animation animation1; - - /// ignored_types: Animation - late final animation2 = AnimationController(); - - /// ignored_types: Animation - late final animation3 = SubAnimationController(); - - /// expect_lint: avoid_late_keyword - late final ColorTween colorTween1; - - /// expect_lint: avoid_late_keyword - late final colorTween2 = ColorTween(); - - /// expect_lint: avoid_late_keyword - late final colorTween3 = colorTween2; - - /// ignored_types: Animation - late final AnimationController controller1; - - /// expect_lint: avoid_late_keyword - late final local1 = 'string'; - - /// expect_lint: avoid_late_keyword - late final String local2; - - /// expect_lint: avoid_late_keyword - late final String local4 = 'string'; - - /// expect_lint: avoid_late_keyword - late final local3; - } -} diff --git a/lint_test/avoid_late_keyword/no_generics/analysis_options.yaml b/lint_test/avoid_late_keyword/no_generics/analysis_options.yaml deleted file mode 100644 index da6add2f..00000000 --- a/lint_test/avoid_late_keyword/no_generics/analysis_options.yaml +++ /dev/null @@ -1,10 +0,0 @@ -analyzer: - plugins: - - ../custom_lint - -custom_lint: - rules: - - avoid_late_keyword: - allow_initialized: false - ignored_types: - - Subscription diff --git a/lint_test/avoid_late_keyword/no_generics/avoid_late_keyword_no_generics_test.dart b/lint_test/avoid_late_keyword/no_generics/avoid_late_keyword_no_generics_test.dart deleted file mode 100644 index 7c166749..00000000 --- a/lint_test/avoid_late_keyword/no_generics/avoid_late_keyword_no_generics_test.dart +++ /dev/null @@ -1,52 +0,0 @@ -// ignore_for_file: prefer_const_declarations, unused_local_variable, prefer_match_file_name -// ignore_for_file: avoid_global_state - -class Subscription {} - -class ConcreteTypeWithNoGenerics {} - -class NotAllowed {} - -/// Check "late" keyword fail -/// -/// `avoid_late_keyword` -/// allow_initialized option disabled -class AvoidLateKeyword { - /// expect_lint: avoid_late_keyword - late final NotAllowed na1; - - /// ignored_types: Subscription - late final Subscription subscription1; - - /// ignored_types: Subscription - late final Subscription subscription2; - - /// ignored_types: Subscription - late final Subscription> subscription3; - - /// ignored_types: Subscription - late final Subscription>> subscription4; - - /// ignored_types: Subscription - late final Subscription> subscription5; - - void test() { - /// expect_lint: avoid_late_keyword - late final NotAllowed na1; - - /// ignored_types: Subscription - late final Subscription subscription1; - - /// ignored_types: Subscription - late final Subscription subscription2; - - /// ignored_types: Subscription - late final Subscription> subscription3; - - /// ignored_types: Subscription - late final Subscription>> subscription4; - - /// ignored_types: Subscription - late final Subscription> subscription5; - } -} diff --git a/lint_test/avoid_late_keyword/with_generics/analysis_options.yaml b/lint_test/avoid_late_keyword/with_generics/analysis_options.yaml deleted file mode 100644 index 47219688..00000000 --- a/lint_test/avoid_late_keyword/with_generics/analysis_options.yaml +++ /dev/null @@ -1,14 +0,0 @@ -analyzer: - plugins: - - ../custom_lint - -custom_lint: - rules: - - avoid_late_keyword: - allow_initialized: true - ignored_types: - - ColorTween - - AnimationController - - Subscription> - - Subscription> - - Subscription diff --git a/lint_test/avoid_late_keyword/with_generics/avoid_late_keyword_with_generics_test.dart b/lint_test/avoid_late_keyword/with_generics/avoid_late_keyword_with_generics_test.dart deleted file mode 100644 index 9778438e..00000000 --- a/lint_test/avoid_late_keyword/with_generics/avoid_late_keyword_with_generics_test.dart +++ /dev/null @@ -1,114 +0,0 @@ -// ignore_for_file: prefer_const_declarations, unused_local_variable, prefer_match_file_name -// ignore_for_file: avoid_global_state - -class ColorTween {} - -class AnimationController {} - -class SubAnimationController extends AnimationController {} - -class Allowed {} - -class NotAllowed {} - -class Subscription {} - -class ConcreteTypeWithNoGenerics {} - -/// Check "late" keyword fail -/// -/// `avoid_late_keyword` -/// allow_initialized option enabled -class AvoidLateKeyword { - /// ignored_types: ColorTween - late final ColorTween colorTween; - - /// ignored_types: AnimationController - late final AnimationController controller1; - - /// ignored_types: AnimationController - late final SubAnimationController controller2; - - /// ignored_types: AnimationController - late final controller3 = AnimationController(); - - /// ignored_types: AnimationController - late final controller4 = SubAnimationController(); - - /// allow_initialized: true - late final field1 = 'string'; - - /// expect_lint: avoid_late_keyword - late final String field2; - - /// expect_lint: avoid_late_keyword - late final field3; - - /// expect_lint: avoid_late_keyword - late final NotAllowed na1; - - /// allow_initialized: true - late final a = Allowed(); - - /// expect_lint: avoid_late_keyword - late final Subscription subscription1; - - /// ignored_types: Subscription - late final Subscription subscription2; - - /// ignored_types: Subscription> - late final Subscription> subscription3; - - /// ignored_types: Subscription> - late final Subscription>> subscription4; - - /// ignored_types: Subscription> - late final Subscription> subscription5; - - /// ignored_types: Subscription> - late final Subscription> subscription6; - - /// expect_lint: avoid_late_keyword - late final Subscription> subscription7; - - void test() { - /// ignored_types: ColorTween - late final ColorTween colorTween; - - /// ignored_types: AnimationController - late final AnimationController controller1; - - /// ignored_types: AnimationController - late final SubAnimationController controller2; - - /// ignored_types: AnimationController - late final controller3 = AnimationController(); - - /// ignored_types: AnimationController - late final controller4 = SubAnimationController(); - - /// allow_initialized: true - late final local1 = 'string'; - - /// expect_lint: avoid_late_keyword - late final String local2; - - /// expect_lint: avoid_late_keyword - late final local3; - - /// expect_lint: avoid_late_keyword - late final NotAllowed na1; - - /// allow_initialized: true - late final a = Allowed(); - - /// expect_lint: avoid_late_keyword - late final Subscription subscription1; - - /// ignored_types: Subscription - late final Subscription subscription2; - - /// ignored_types: Subscription> - late final Subscription> subscription3; - } -} diff --git a/test/avoid_late_keyword_rule_test.dart b/test/avoid_late_keyword_rule_test.dart index d01da4c7..778f9f9d 100644 --- a/test/avoid_late_keyword_rule_test.dart +++ b/test/avoid_late_keyword_rule_test.dart @@ -1,56 +1,350 @@ import 'package:analyzer_testing/analysis_rule/analysis_rule.dart'; +import 'package:analyzer_testing/utilities/utilities.dart'; +import 'package:solid_lints/src/common/parameter_parser/analysis_options_loader.dart'; import 'package:solid_lints/src/lints/avoid_late_keyword/avoid_late_keyword_rule.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; void main() { defineReflectiveSuite(() { defineReflectiveTests(AvoidLateKeywordRuleTest); + defineReflectiveTests(AvoidLateKeywordNoGenericsTest); + defineReflectiveTests(AvoidLateKeywordWithGenericsTest); }); } @reflectiveTest class AvoidLateKeywordRuleTest extends AnalysisRuleTest { + final String _typesDefinitions = ''' +abstract class Animation {} + +class AnimationController implements Animation {} + +class SubAnimationController extends AnimationController {} + +class ColorTween {} +'''; + @override void setUp() { - rule = AvoidLateKeywordRule(); + rule = AvoidLateKeywordRule( + analysisOptionsLoader: + AnalysisOptionsLoader(resourceProvider: resourceProvider), + ); super.setUp(); + + newAnalysisOptionsYamlFile( + testPackageRootPath, + ''' +${analysisOptionsContent(rules: [rule.name])} +plugins: + solid_lints: + diagnostics: + ${rule.name}: + allow_initialized: false + ignored_types: + - Animation +''', + ); + } + + Future test_does_not_report_ignored_types_fields() async { + await assertNoDiagnostics( + ''' +class Test { + late final Animation animation1; + late final animation2 = AnimationController(); + late final animation3 = SubAnimationController(); + late final AnimationController controller1; +} +$_typesDefinitions + ''', + ); + } + + Future test_does_not_report_ignored_types_local_variables() async { + await assertNoDiagnostics( + ''' +void test() { + late final Animation animation1; + late final animation2 = AnimationController(); + late final animation3 = SubAnimationController(); + late final AnimationController controller1; +} +$_typesDefinitions + ''', + ); } - void test_reports_uninitialized_late_field() async { + Future test_reports_non_ignored_types_fields() async { await assertDiagnostics( - r''' + ''' class Test { - late final int field; + late final ColorTween colorTween1; + late final colorTween2 = ColorTween(); + late final colorTween3 = colorTween2; + late final field1 = 'string'; + late final String field2; + late final String field3 = 'string'; + late final field4; +} +$_typesDefinitions + ''', + [ + lint(37, 11), + lint(63, 26), + lint(104, 25), + lint(144, 17), + lint(183, 6), + lint(211, 17), + lint(243, 6), + ], + ); + } + + Future test_reports_non_ignored_types_local_variables() async { + await assertDiagnostics( + ''' +void test() { + late final ColorTween colorTween1; + late final colorTween2 = ColorTween(); + late final colorTween3 = colorTween2; + late final local1 = 'string'; + late final String local2; + late final String local4 = 'string'; + late final local3; +} +$_typesDefinitions + ''', + [ + lint(38, 11), + lint(64, 26), + lint(105, 25), + lint(145, 17), + lint(184, 6), + lint(212, 17), + lint(244, 6), + ], + ); + } } + +@reflectiveTest +class AvoidLateKeywordNoGenericsTest extends AnalysisRuleTest { + final String _typesDefinitions = ''' +class Subscription {} + +class ConcreteTypeWithNoGenerics {} + +class NotAllowed {} +'''; + + @override + void setUp() { + rule = AvoidLateKeywordRule( + analysisOptionsLoader: + AnalysisOptionsLoader(resourceProvider: resourceProvider), + ); + super.setUp(); + + newAnalysisOptionsYamlFile( + testPackageRootPath, + ''' +${analysisOptionsContent(rules: [rule.name])} +plugins: + solid_lints: + diagnostics: + ${rule.name}: + allow_initialized: false + ignored_types: + - Subscription ''', - [lint(30, 5)], ); } - void test_reports_uninitialized_late_local_variable() async { + Future test_does_not_report_ignored_types_fields() async { + await assertNoDiagnostics( + ''' +class Test { + late final Subscription subscription1; + late final Subscription subscription2; + late final Subscription> subscription3; + late final Subscription>> subscription4; + late final Subscription> subscription5; +} +$_typesDefinitions + ''', + ); + } + + Future test_does_not_report_ignored_types_local_variables() async { + await assertNoDiagnostics( + ''' +void test() { + late final Subscription subscription1; + late final Subscription subscription2; + late final Subscription> subscription3; + late final Subscription>> subscription4; + late final Subscription> subscription5; +} +$_typesDefinitions + ''', + ); + } + + Future test_reports_non_ignored_types_fields() async { + await assertDiagnostics( + ''' +class Test { + late final NotAllowed na1; +} +$_typesDefinitions + ''', + [ + lint(37, 3), + ], + ); + } + + Future test_reports_non_ignored_types_local_variables() async { await assertDiagnostics( - r''' -void m() { - late final String value; + ''' +void test() { + late final NotAllowed na1; } +$_typesDefinitions + ''', + [ + lint(38, 3), + ], + ); + } +} + +@reflectiveTest +class AvoidLateKeywordWithGenericsTest extends AnalysisRuleTest { + final String _typesDefinitions = ''' +class ColorTween {} + +class AnimationController {} + +class SubAnimationController extends AnimationController {} + +class Allowed {} + +class NotAllowed {} + +class Subscription {} + +class ConcreteTypeWithNoGenerics {} +'''; + + @override + void setUp() { + rule = AvoidLateKeywordRule( + analysisOptionsLoader: + AnalysisOptionsLoader(resourceProvider: resourceProvider), + ); + super.setUp(); + + newAnalysisOptionsYamlFile( + testPackageRootPath, + ''' +${analysisOptionsContent(rules: [rule.name])} +plugins: + solid_lints: + diagnostics: + ${rule.name}: + allow_initialized: true + ignored_types: + - ColorTween + - AnimationController + - Subscription> + - Subscription> + - Subscription ''', - [lint(31, 5)], ); } - void test_does_not_report_initialized_late_variable() async { - await assertNoDiagnostics(r''' + Future test_does_not_report_ignored_types_fields() async { + await assertNoDiagnostics( + ''' class Test { - late final int field = 1; + late final ColorTween colorTween; + late final AnimationController controller1; + late final SubAnimationController controller2; + late final controller3 = AnimationController(); + late final controller4 = SubAnimationController(); + late final Subscription subscription2; + late final Subscription> subscription3; + late final Subscription>> subscription4; + late final Subscription> subscription5; + late final Subscription> subscription6; + late final field1 = 'string'; + late final a = Allowed(); } -'''); +$_typesDefinitions + ''', + ); } - void test_does_not_report_non_late_variable() async { - await assertNoDiagnostics(r''' + Future test_does_not_report_ignored_types_local_variables() async { + await assertNoDiagnostics( + ''' +void test() { + late final ColorTween colorTween; + late final AnimationController controller1; + late final SubAnimationController controller2; + late final controller3 = AnimationController(); + late final controller4 = SubAnimationController(); + late final Subscription subscription2; + late final Subscription> subscription3; + late final local1 = 'string'; + late final a = Allowed(); +} +$_typesDefinitions + ''', + ); + } + + Future test_reports_non_ignored_types_fields() async { + await assertDiagnostics( + ''' class Test { - final int field = 1; + late final String field2; + late final field3; + late final NotAllowed na1; + late final Subscription subscription1; + late final Subscription> subscription7; } -'''); +$_typesDefinitions + ''', + [ + lint(33, 6), + lint(54, 6), + lint(86, 3), + lint(125, 13), + lint(188, 13), + ], + ); + } + + Future test_reports_non_ignored_types_local_variables() async { + await assertDiagnostics( + ''' +void test() { + late final String local2; + late final local3; + late final NotAllowed na1; + late final Subscription subscription1; +} +$_typesDefinitions + ''', + [ + lint(34, 6), + lint(55, 6), + lint(87, 3), + lint(126, 13), + ], + ); } }