Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 29 additions & 31 deletions lib/src/lints/no_equal_then_else/no_equal_then_else_rule.dart
Original file line number Diff line number Diff line change
@@ -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/)

Expand Down Expand Up @@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<void> {
final _nodes = <AstNode>[];
/// Visitor for [NoEqualThenElseRule].
class NoEqualThenElseVisitor extends SimpleAstVisitor<void> {
/// The rule associated with this visitor.
final NoEqualThenElseRule _rule;

/// All unnecessary if statements and conditional expressions.
Iterable<AstNode> get nodes => _nodes;
/// Creates an instance of [NoEqualThenElseVisitor]
NoEqualThenElseVisitor(this._rule);

@override
void visitIfStatement(IfStatement node) {
Expand All @@ -39,7 +40,7 @@ class NoEqualThenElseVisitor extends RecursiveAstVisitor<void> {
if (node.elseStatement != null &&
node.elseStatement is! IfStatement &&
node.thenStatement.toString() == node.elseStatement.toString()) {
_nodes.add(node);
_rule.reportAtNode(node);
}
}

Expand All @@ -48,7 +49,7 @@ class NoEqualThenElseVisitor extends RecursiveAstVisitor<void> {
super.visitConditionalExpression(node);

if (node.thenExpression.toString() == node.elseExpression.toString()) {
_nodes.add(node);
_rule.reportAtNode(node);
}
}
}
30 changes: 0 additions & 30 deletions lint_test/no_equal_then_else_test.dart

This file was deleted.

2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
88 changes: 88 additions & 0 deletions test/lints/no_equal_then_else/no_equal_then_else_rule_test.dart
Original file line number Diff line number Diff line change
@@ -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;
}
''');
}
}
Loading