Skip to content

Commit

Permalink
linter: do not report use_is_even in const situations
Browse files Browse the repository at this point in the history
Fixes dart-lang/linter#4915

Change-Id: I4b353b3f8cc064d15bbe366c9008c9a2fc1e1144
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/364620
Commit-Queue: Phil Quitslund <pquitslund@google.com>
Reviewed-by: Phil Quitslund <pquitslund@google.com>
Auto-Submit: Samuel Rawlins <srawlins@google.com>
  • Loading branch information
srawlins authored and Commit Queue committed Apr 26, 2024
1 parent 15c3434 commit 4c888ab
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 15 deletions.
43 changes: 28 additions & 15 deletions pkg/linter/lib/src/rules/use_is_even_rather_than_modulo.dart
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ class _Visitor extends SimpleAstVisitor<void> {
@override
void visitBinaryExpression(BinaryExpression node) {
// This lint error only happens when the operator is equality.
if (node.operator.type != TokenType.EQ_EQ) {
return;
}
if (node.operator.type != TokenType.EQ_EQ) return;
if (node.inConstantContext) return;

var left = node.leftOperand;
var leftType = left.staticType;
var right = node.rightOperand;
Expand All @@ -72,19 +72,32 @@ class _Visitor extends SimpleAstVisitor<void> {
return;
}
// The left side expression has to be modulo by 2 type.
if (left is BinaryExpression) {
var rightChild = left.rightOperand;
var rightChildType = rightChild.staticType;
if (left.operator.type == TokenType.PERCENT &&
rightChild is IntegerLiteral &&
rightChild.value == 2 &&
(rightChildType?.isDartCoreInt ?? false)) {
var value = right.value;
if (value == null) {
return;
}
rule.reportLint(node, arguments: [value == 0 ? 'isEven' : 'isOdd']);
if (left is! BinaryExpression) return;
if (left.operator.type != TokenType.PERCENT) return;

var rightChild = left.rightOperand;

if (rightChild is! IntegerLiteral) return;
if (rightChild.value != 2) return;

// Now we have `x % 2 == y`.
var rightChildType = rightChild.staticType;
if (rightChildType == null) return;
if (!rightChildType.isDartCoreInt) return;

var value = right.value;
if (value == null) return;
var parentAssertInitializer =
node.thisOrAncestorOfType<AssertInitializer>();
if (parentAssertInitializer != null) {
var constructor = parentAssertInitializer.parent;
// `isEven` is not allowed in a const constructor assert initializer.
if (constructor is ConstructorDeclaration &&
constructor.constKeyword != null) {
return;
}
}

rule.reportLint(node, arguments: [value == 0 ? 'isEven' : 'isOdd']);
}
}
15 changes: 15 additions & 0 deletions pkg/linter/test/rules/use_is_even_rather_than_modulo_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,21 @@ var b = a % 3 == 1;
''');
}

test_moduloTwoEqualEqualOne_inConstAssertInitializer() async {
await assertNoDiagnostics(r'''
class C {
const C(int x) : assert(x % 2 == 0);
}
''');
}

test_moduloTwoEqualEqualOne_inConstContext() async {
await assertNoDiagnostics(r'''
const a = 3;
const b = a % 2 == 0;
''');
}

test_moduloTwoEqualEqualOne_intTypedExpression() async {
await assertDiagnostics(r'''
var a = 3;
Expand Down

0 comments on commit 4c888ab

Please sign in to comment.