Skip to content
This repository was archived by the owner on Nov 20, 2024. It is now read-only.

Commit dfbff42

Browse files
authored
special case assert initializers and const contexts in prefer_is_empty (#2122)
* special case assert initializers and const contexts * ws * + test * more const context tests * check in constructor initializer
1 parent 1bb57eb commit dfbff42

File tree

2 files changed

+63
-6
lines changed

2 files changed

+63
-6
lines changed

lib/src/rules/prefer_is_empty.dart

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
// BSD-style license that can be found in the LICENSE file.
44

55
import 'package:analyzer/dart/ast/ast.dart';
6+
// ignore: implementation_imports
7+
import 'package:analyzer/src/dart/ast/ast.dart' show ExpressionImpl;
68
import 'package:analyzer/dart/ast/token.dart';
79
import 'package:analyzer/dart/ast/visitor.dart';
810
import 'package:analyzer/dart/element/type.dart';
@@ -129,6 +131,24 @@ class _Visitor extends SimpleAstVisitor<void> {
129131
}
130132
final binaryExpression = search as BinaryExpression;
131133

134+
// Don't lint if we're in a const constructor initializer.
135+
final constructorInitializer =
136+
search.parent.thisOrAncestorOfType<ConstructorInitializer>();
137+
if (constructorInitializer != null) {
138+
final constructorDecl =
139+
constructorInitializer.parent as ConstructorDeclaration;
140+
if (constructorDecl.constKeyword != null) {
141+
return;
142+
}
143+
}
144+
145+
// Or in a const context.
146+
// See: https://github.com/dart-lang/linter/issues/1719
147+
final impl = binaryExpression as ExpressionImpl;
148+
if (impl.inConstantContext) {
149+
return;
150+
}
151+
132152
final operator = binaryExpression.operator;
133153

134154
// Comparing constants with length.

test/rules/prefer_is_empty.dart

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,54 @@
44

55
// test w/ `pub run test -N prefer_is_empty`
66

7+
const l = '';
8+
const bool empty = l.length == 0; //OK
9+
10+
class A {
11+
final List<String> a;
12+
const A(this.a) : assert(a.length > 0); //OK
13+
}
14+
15+
class B {
16+
final String b;
17+
const B(this.b) : assert(b.length > 0); //OK
18+
}
19+
20+
class C {
21+
final bool empty;
22+
const C(dynamic l) : empty = l.length == 0; //OK
23+
}
24+
25+
class D {
26+
final bool emptyString;
27+
D(String s) : emptyString = s.length == 0; //LINT
28+
}
29+
30+
class E {
31+
final bool empty;
32+
const E(dynamic l) : empty = l.length == 0; // OK
33+
const E.a(this.empty);
34+
const E.b(dynamic l) : this.a(l.length == 0); // OK
35+
}
36+
37+
class F {
38+
// ignore: avoid_positional_boolean_parameters
39+
const F(bool b);
40+
}
41+
42+
class G extends F {
43+
const G(dynamic l) : super(l.length == 0); // OK
44+
}
45+
746
const int zero = 0;
847
Iterable<int> list = [];
948
Map map = {};
1049

1150
Iterable get iterable => [];
1251

13-
typedef Iterable F();
52+
typedef Fun = Iterable Function();
1453

15-
F a() {
16-
return () => [];
17-
}
54+
Fun a() => () => [];
1855

1956
bool le = list.length > 0; //LINT
2057
bool le2 = [].length > 0; //LINT
@@ -30,14 +67,14 @@ bool mixed = list.length + map.length > 0; //OK
3067
Iterable length = [];
3168
bool ok = length.first > 0; // OK
3269

33-
condition() {
70+
void condition() {
3471
final int a = list.length > 0 ? list.first : 0; //LINT
3572
list..length;
3673
}
3774

3875
bool le7 = [].length > 1; //OK
3976

40-
testOperators() {
77+
void testOperators() {
4178
[].length == 0; // LINT
4279
[].length != 0; // LINT
4380
[].length > 0; // LINT

0 commit comments

Comments
 (0)