diff --git a/pubspec.yaml b/pubspec.yaml index ee33fea2b..bb954c9ad 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -7,7 +7,7 @@ environment: dependencies: collection: ^1.15.0 - analyzer: ^5.1.0 + analyzer: ^5.13.0 build: '>=1.0.0 <3.0.0' dart_style: ^2.0.0 js: ^0.6.1+1 diff --git a/tools/analyzer_plugin/lib/src/diagnostic/bad_key.dart b/tools/analyzer_plugin/lib/src/diagnostic/bad_key.dart index 5355d0bab..50d5edd65 100644 --- a/tools/analyzer_plugin/lib/src/diagnostic/bad_key.dart +++ b/tools/analyzer_plugin/lib/src/diagnostic/bad_key.dart @@ -139,11 +139,15 @@ class BadKeyDiagnostic extends ComponentUsageDiagnosticContributor { final topLevelKeyType = expression.staticType; // Type can't be resolved; bail out. if (topLevelKeyType == null) return; + // The type is bad because of errors, such as when the user's in the middle of typing an identifier, + // or referencing an identifier that doesn't exist yet. + if (topLevelKeyType is InvalidType) return; final typedProvider = result.typeProvider; // Special-case for Iterables and Maps: check if their (keys and) values are allowed types. final isIterableOrMap = + topLevelKeyType is! DynamicType && // Need to make sure it's not null since null is a subtype of all nullable-types. !topLevelKeyType.isDartCoreNull && [ @@ -151,9 +155,8 @@ class BadKeyDiagnostic extends ComponentUsageDiagnosticContributor { typedProvider.mapType(typedProvider.dynamicType, typedProvider.dynamicType), ].any((type) => result.typeSystem.isSubtypeOf(topLevelKeyType, type)); - final keyTypesToProcess = { - if (isIterableOrMap) ...(topLevelKeyType as InterfaceType).typeArguments else topLevelKeyType, - }; + final keyTypesToProcess = + isIterableOrMap && topLevelKeyType is InterfaceType ? topLevelKeyType.typeArguments : [topLevelKeyType]; for (final type in keyTypesToProcess) { // Provide context if this type was derived from a Map/Iterable type argument. @@ -166,7 +169,7 @@ class BadKeyDiagnostic extends ComponentUsageDiagnosticContributor { type.isDartCoreString || type.isDartCoreSymbol) { // Ignore core types that have good `Object.toString` implementations values. - } else if (type.isDartCoreObject || type.isDynamic) { + } else if (type.isDartCoreObject || type is DynamicType) { collector.addError( dynamicOrObjectCode, result.locationFor(expression), diff --git a/tools/analyzer_plugin/test/integration/diagnostics/bad_key_test.dart b/tools/analyzer_plugin/test/integration/diagnostics/bad_key_test.dart index 7f473b5ef..d1dc7e768 100644 --- a/tools/analyzer_plugin/test/integration/diagnostics/bad_key_test.dart +++ b/tools/analyzer_plugin/test/integration/diagnostics/bad_key_test.dart @@ -82,6 +82,7 @@ class BadKeyDiagnosticTest_NoErrors extends BadKeyDiagnosticTest { (Dom.div()..key = 'greg')(), // Missing RHS (Dom.div()..key = )(), + (Dom.div()..key = undefinedVariable)(), // Missing interpolated expression (Dom.div()..key = '${}')(), // Weird type @@ -94,6 +95,7 @@ class BadKeyDiagnosticTest_NoErrors extends BadKeyDiagnosticTest { unorderedEquals([ isA().havingCode('missing_identifier'), isA().havingCode('missing_identifier'), + isA().havingCode('undefined_identifier'), isA().havingCode('use_of_void_result'), ]), reason: 'should only have the Dart analysis errors we expect');