diff --git a/lib/src/lints/no_equal_then_else/no_equal_then_else_rule.dart b/lib/src/lints/no_equal_then_else/no_equal_then_else_rule.dart index eaf8e389..8099a2c8 100644 --- a/lib/src/lints/no_equal_then_else/no_equal_then_else_rule.dart +++ b/lib/src/lints/no_equal_then_else/no_equal_then_else_rule.dart @@ -1,8 +1,8 @@ -import 'package:analyzer/error/listener.dart'; -import 'package:custom_lint_builder/custom_lint_builder.dart'; +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/no_equal_then_else/visitors/no_equal_then_else_visitor.dart'; -import 'package:solid_lints/src/models/rule_config.dart'; -import 'package:solid_lints/src/models/solid_lint_rule.dart'; // Inspired by PVS-Studio (https://www.viva64.com/en/w/v6004/) @@ -41,38 +41,36 @@ import 'package:solid_lints/src/models/solid_lint_rule.dart'; /// /// selectedValue = condition ? valueA : valueB; /// ``` -class NoEqualThenElseRule extends SolidLintRule { - /// This lint rule represents the error if - /// 'if' statements or conditional expression is redundant - static const String lintName = 'no_equal_then_else'; +class NoEqualThenElseRule extends AnalysisRule { + /// The name of the lint rule. + static const String _lintName = 'no_equal_then_else'; - NoEqualThenElseRule._(super.config); + /// The message shown when the lint is triggered. + static const String _lintMessage = 'Then and else branches are equal.'; - /// Creates a new instance of [NoEqualThenElseRule] - /// based on the lint configuration. - factory NoEqualThenElseRule.createRule(CustomLintConfigs configs) { - final rule = RuleConfig( - configs: configs, - name: lintName, - problemMessage: (value) => "Then and else branches are equal.", - ); + /// Lint code + static const _code = LintCode( + _lintName, + _lintMessage, + ); - return NoEqualThenElseRule._(rule); - } + /// Create a new instance of [NoEqualThenElseRule] + NoEqualThenElseRule() + : super( + name: _lintName, + description: _lintMessage, + ); @override - void run( - CustomLintResolver resolver, - DiagnosticReporter reporter, - CustomLintContext context, - ) { - context.registry.addCompilationUnit((node) { - final visitor = NoEqualThenElseVisitor(); - node.accept(visitor); + LintCode get diagnosticCode => _code; - for (final element in visitor.nodes) { - reporter.atNode(element, code); - } - }); + @override + void registerNodeProcessors( + RuleVisitorRegistry registry, + RuleContext context, + ) { + final visitor = NoEqualThenElseVisitor(this); + registry.addIfStatement(this, visitor); + registry.addConditionalExpression(this, visitor); } } diff --git a/lib/src/lints/no_equal_then_else/visitors/no_equal_then_else_visitor.dart b/lib/src/lints/no_equal_then_else/visitors/no_equal_then_else_visitor.dart index 0ec18307..98b90230 100644 --- a/lib/src/lints/no_equal_then_else/visitors/no_equal_then_else_visitor.dart +++ b/lib/src/lints/no_equal_then_else/visitors/no_equal_then_else_visitor.dart @@ -23,14 +23,15 @@ import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/visitor.dart'; +import 'package:solid_lints/src/lints/no_equal_then_else/no_equal_then_else_rule.dart'; -/// The AST visitor that will collect all unnecessary if statements and -/// conditional expressions. -class NoEqualThenElseVisitor extends RecursiveAstVisitor { - final _nodes = []; +/// Visitor for [NoEqualThenElseRule]. +class NoEqualThenElseVisitor extends SimpleAstVisitor { + /// The rule associated with this visitor. + final NoEqualThenElseRule _rule; - /// All unnecessary if statements and conditional expressions. - Iterable get nodes => _nodes; + /// Creates an instance of [NoEqualThenElseVisitor] + NoEqualThenElseVisitor(this._rule); @override void visitIfStatement(IfStatement node) { @@ -39,7 +40,7 @@ class NoEqualThenElseVisitor extends RecursiveAstVisitor { if (node.elseStatement != null && node.elseStatement is! IfStatement && node.thenStatement.toString() == node.elseStatement.toString()) { - _nodes.add(node); + _rule.reportAtNode(node); } } @@ -48,7 +49,7 @@ class NoEqualThenElseVisitor extends RecursiveAstVisitor { super.visitConditionalExpression(node); if (node.thenExpression.toString() == node.elseExpression.toString()) { - _nodes.add(node); + _rule.reportAtNode(node); } } } diff --git a/lint_test/no_equal_then_else_test.dart b/lint_test/no_equal_then_else_test.dart deleted file mode 100644 index c9caa40c..00000000 --- a/lint_test/no_equal_then_else_test.dart +++ /dev/null @@ -1,30 +0,0 @@ -// ignore_for_file: unused_local_variable -// ignore_for_file: cyclomatic_complexity -// ignore_for_file: no_magic_number -// ignore_for_file: prefer_conditional_expressions - -/// Check the `no_equal_then_else` rule -void fun() { - final _valueA = 1; - final _valueB = 2; - - int _result = 0; - - // expect_lint: no_equal_then_else - if (_valueA == 1) { - _result = _valueA; - } else { - _result = _valueA; - } - - if (_valueA == 1) { - _result = _valueA; - } else { - _result = _valueB; - } - - // expect_lint: no_equal_then_else - _result = _valueA == 2 ? _valueA : _valueA; - - _result = _valueA == 2 ? _valueA : _valueB; -} diff --git a/pubspec.yaml b/pubspec.yaml index f85b1309..70168359 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -8,7 +8,7 @@ documentation: https://solid-software.github.io/solid_lints/docs/intro topics: [lints, linter, lint, analysis, analyzer] environment: - sdk: ">=3.5.0 <4.0.0" + sdk: ">=3.9.0 <4.0.0" dependencies: analyzer: ^10.0.1 diff --git a/test/lints/no_equal_then_else/no_equal_then_else_rule_test.dart b/test/lints/no_equal_then_else/no_equal_then_else_rule_test.dart new file mode 100644 index 00000000..8eecbb3f --- /dev/null +++ b/test/lints/no_equal_then_else/no_equal_then_else_rule_test.dart @@ -0,0 +1,88 @@ +import 'package:analyzer_testing/analysis_rule/analysis_rule.dart'; +import 'package:solid_lints/src/lints/no_equal_then_else/no_equal_then_else_rule.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +void main() { + defineReflectiveSuite(() { + defineReflectiveTests(NoEqualThenElseRuleTest); + }); +} + +@reflectiveTest +class NoEqualThenElseRuleTest extends AnalysisRuleTest { + @override + void setUp() { + rule = NoEqualThenElseRule(); + super.setUp(); + } + + @override + String get analysisRule => rule.name; + + void test_reports_then_and_else_equal() async { + await assertDiagnostics( + r''' +void fun() { + final _valueA = 1; + final _valueB = 2; + + int _result = 0; + + if (_valueA == 1) { + _result = _valueA; + } else { + _result = _valueA; + } +} +''', + [lint(78, 80)], + ); + } + + void test_does_not_report_then_and_else_different() async { + await assertNoDiagnostics(r''' +void fun() { + final _valueA = 1; + final _valueB = 2; + + int _result = 0; + + if (_valueA == 1) { + _result = _valueA; + } else { + _result = _valueB; + } +} +'''); + } + + void test_reports_conditional_expression_then_and_else_equal() async { + await assertDiagnostics( + r''' +void fun() { + final _valueA = 1; + final _valueB = 2; + + int _result = 0; + + _result = _valueA == 2 ? _valueA : _valueA; +} +''', + [lint(88, 32)], + ); + } + + void + test_does_not_report_conditional_expression_then_and_else_different() async { + await assertNoDiagnostics(r''' +void fun() { + final _valueA = 1; + final _valueB = 2; + + int _result = 0; + + _result = _valueA == 2 ? _valueA : _valueB; +} +'''); + } +}