From 1e651c5d9090d478d16f36f642608811920ac9e3 Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Mon, 15 May 2023 14:31:12 -0700 Subject: [PATCH] Report type_literal_in_constant_pattern more often. --- .../type_literal_in_constant_pattern.dart | 37 +++++++++---------- ...type_literal_in_constant_pattern_test.dart | 28 ++++++-------- 2 files changed, 30 insertions(+), 35 deletions(-) diff --git a/lib/src/rules/type_literal_in_constant_pattern.dart b/lib/src/rules/type_literal_in_constant_pattern.dart index 223fe60b4..73766061f 100644 --- a/lib/src/rules/type_literal_in_constant_pattern.dart +++ b/lib/src/rules/type_literal_in_constant_pattern.dart @@ -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) { @@ -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 { @@ -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); } } } diff --git a/test/rules/type_literal_in_constant_pattern_test.dart b/test/rules/type_literal_in_constant_pattern_test.dart index 5e399c66a..849e2c8ee 100644 --- a/test/rules/type_literal_in_constant_pattern_test.dart +++ b/test/rules/type_literal_in_constant_pattern_test.dart @@ -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) { @@ -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 { @@ -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)) {} } @@ -102,7 +94,9 @@ class A { final Type type; A(this.type); } -'''); +''', [ + lint(35, 3), + ]); } test_constType_matchTypeParameter_boundObjectNullable() async { @@ -117,10 +111,12 @@ void f(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 x) { if (x case int) {} } -'''); +''', [ + lint(43, 3), + ]); } }