Skip to content

Commit

Permalink
Report type_literal_in_constant_pattern more often. (dart-lang/linter…
Browse files Browse the repository at this point in the history
  • Loading branch information
scheglov authored May 15, 2023
1 parent 5b5f65c commit 0d85a0b
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 35 deletions.
37 changes: 18 additions & 19 deletions lib/src/rules/type_literal_in_constant_pattern.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,30 @@ import '../analyzer.dart';
const _desc = r"Don't use constant patterns with type literals.";

const _details = r'''
Use `== TypeName` or `TypeName _` instead of type literals in patterns.
If you meant to test if the object has type `Foo`, instead write `Foo _`.
**BAD:**
```dart
void f(Type x) {
if (x case int) {
print('int');
void f(Object? x) {
if (x case num) {
print('int or double');
}
}
```
**GOOD:**
```dart
void f(Type x) {
if (x case == int) {
print('int');
void f(Object? x) {
if (x case num _) {
print('int or double');
}
}
```
If you do mean to test that the matched value (which you expect to have the
type `Type`) is equal to the type literal `Foo`, then this lint can be
silenced using `const (Foo)`.
**BAD:**
```dart
void f(Object? x) {
Expand All @@ -42,12 +46,11 @@ void f(Object? x) {
**GOOD:**
```dart
void f(Object? x) {
if (x case int _) {
if (x case const (int)) {
print('int');
}
}
```
''';

class TypeLiteralInConstantPattern extends LintRule {
Expand Down Expand Up @@ -86,18 +89,14 @@ class _Visitor extends SimpleAstVisitor {

@override
visitConstantPattern(ConstantPattern node) {
// `const (MyType)` is fine.
if (node.constKeyword != null) {
return;
}

var expressionType = node.expression.staticType;
if (expressionType != null && expressionType.isDartCoreType) {
var matchedValueType = node.matchedValueType;
if (matchedValueType != null) {
var typeSystem = context.typeSystem;
matchedValueType = typeSystem.resolveToBound(matchedValueType);
if (!matchedValueType.isDartCoreType) {
if (typeSystem.isSubtypeOf(expressionType, matchedValueType)) {
rule.reportLint(node);
}
}
}
rule.reportLint(node);
}
}
}
28 changes: 12 additions & 16 deletions test/rules/type_literal_in_constant_pattern_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,6 @@ void f(dynamic x) {
]);
}

test_constType_matchNum() async {
await assertDiagnostics(r'''
void f(num x) {
if (x case int) {}
}
''', [
error(WarningCode.CONSTANT_PATTERN_NEVER_MATCHES_VALUE_TYPE, 29, 3),
]);
}

test_constType_matchObject() async {
await assertDiagnostics(r'''
void f(Object x) {
Expand All @@ -77,11 +67,13 @@ void f(Object? x) {
}

test_constType_matchType() async {
await assertNoDiagnostics(r'''
await assertDiagnostics(r'''
void f(Type x) {
if (x case int) {}
}
''');
''', [
lint(30, 3),
]);
}

test_constType_matchType_explicitConst() async {
Expand All @@ -93,7 +85,7 @@ void f(Type x) {
}

test_constType_matchType_nested() async {
await assertNoDiagnostics(r'''
await assertDiagnostics(r'''
void f(A x) {
if (x case A(type: int)) {}
}
Expand All @@ -102,7 +94,9 @@ class A {
final Type type;
A(this.type);
}
''');
''', [
lint(35, 3),
]);
}

test_constType_matchTypeParameter_boundObjectNullable() async {
Expand All @@ -117,10 +111,12 @@ void f<T extends Object?>(T x) {

/// Nobody will write such code, but just in case.
test_constType_matchTypeParameter_boundType() async {
await assertNoDiagnostics(r'''
await assertDiagnostics(r'''
void f<T extends Type>(T x) {
if (x case int) {}
}
''');
''', [
lint(43, 3),
]);
}
}

0 comments on commit 0d85a0b

Please sign in to comment.