Index: pkg/analyzer/lib/src/generated/error_verifier.dart |
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart |
index eca427d5390ccb170d4b1cab66e96d115e3eae17..6d4177b0f0e79829e10c2498d14eeead68461ac9 100644 |
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart |
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart |
@@ -79,7 +79,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> { |
/** |
* The options for verification. |
*/ |
- AnalysisOptions _options; |
+ AnalysisOptionsImpl _options; |
/** |
* The object providing access to the types defined by the language. |
@@ -676,6 +676,12 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> { |
} |
@override |
+ Object visitExtendsClause(ExtendsClause node) { |
+ _checkForImplicitDynamicType(node.superclass); |
+ return super.visitExtendsClause(node); |
+ } |
+ |
+ @override |
Object visitFieldDeclaration(FieldDeclaration node) { |
_isInStaticVariableDeclaration = node.isStatic; |
_isInInstanceVariableDeclaration = !_isInStaticVariableDeclaration; |
@@ -747,6 +753,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> { |
} |
_checkForTypeAnnotationDeferredClass(returnType); |
_checkForIllegalReturnType(returnType); |
+ _checkForImplicitDynamicReturn(node, node.element); |
return super.visitFunctionDeclaration(node); |
} finally { |
_enclosingFunction = outerFunction; |
@@ -781,6 +788,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> { |
} else if (expressionType is FunctionType) { |
_checkTypeArguments(expressionType.element, node.typeArguments); |
} |
+ _checkForImplicitDynamicInvoke(node); |
return super.visitFunctionExpressionInvocation(node); |
} |
@@ -799,6 +807,18 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> { |
_isInFunctionTypedFormalParameter = true; |
try { |
_checkForTypeAnnotationDeferredClass(node.returnType); |
+ |
+ // TODO(jmesserly): ideally we'd use _checkForImplicitDynamicReturn, and |
+ // we can get the function element via `node?.element?.type?.element` but |
+ // it doesn't have hasImplicitReturnType set correctly. |
+ if (!_options.implicitDynamic && node.returnType == null) { |
+ DartType parameterType = node.element.type; |
+ if (parameterType is FunctionType && |
+ parameterType.returnType.isDynamic) { |
+ _errorReporter.reportErrorForNode( |
+ StrongModeCode.IMPLICIT_DYNAMIC_RETURN, node, [node.identifier]); |
+ } |
+ } |
return super.visitFunctionTypedFormalParameter(node); |
} finally { |
_isInFunctionTypedFormalParameter = old; |
@@ -812,6 +832,12 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> { |
} |
@override |
+ Object visitImplementsClause(ImplementsClause node) { |
+ node.interfaces.forEach(_checkForImplicitDynamicType); |
+ return super.visitImplementsClause(node); |
+ } |
+ |
+ @override |
Object visitImportDirective(ImportDirective node) { |
ImportElement importElement = node.element; |
if (importElement != null) { |
@@ -848,6 +874,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> { |
_checkForNewWithUndefinedConstructor(node, constructorName, typeName); |
} |
} |
+ _checkForImplicitDynamicType(typeName); |
return super.visitInstanceCreationExpression(node); |
} finally { |
_isInConstInstanceCreation = wasInConstInstanceCreation; |
@@ -873,7 +900,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> { |
} |
_checkForExpectedOneListTypeArgument(node, typeArguments); |
} |
- |
+ _checkForImplicitDynamicTypedLiteral(node); |
_checkForListElementTypeNotAssignable(node); |
return super.visitListLiteral(node); |
} |
@@ -891,7 +918,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> { |
} |
_checkExpectedTwoMapTypeArguments(typeArguments); |
} |
- |
+ _checkForImplicitDynamicTypedLiteral(node); |
_checkForMapTypeNotAssignable(node); |
_checkForNonConstMapAsExpressionStatement(node); |
return super.visitMapLiteral(node); |
@@ -930,6 +957,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> { |
_checkForAllInvalidOverrideErrorCodesForMethod(node); |
_checkForTypeAnnotationDeferredClass(returnTypeName); |
_checkForIllegalReturnType(returnTypeName); |
+ _checkForImplicitDynamicReturn(node, node.element); |
_checkForMustCallSuper(node); |
return super.visitMethodDeclaration(node); |
} finally { |
@@ -951,6 +979,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> { |
} |
_checkTypeArguments( |
node.methodName.staticElement, node.typeArguments, target?.staticType); |
+ _checkForImplicitDynamicInvoke(node); |
return super.visitMethodInvocation(node); |
} |
@@ -1046,6 +1075,15 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> { |
_checkForConstFormalParameter(node); |
_checkForPrivateOptionalParameter(node); |
_checkForTypeAnnotationDeferredClass(node.type); |
+ |
+ // Checks for an implicit dynamic parameter type. |
+ // |
+ // We can skip other parameter kinds besides simple formal, because: |
+ // - DefaultFormalParameter contains a simple one, so it gets here, |
+ // - FieldFormalParameter error should be reported on the field, |
+ // - FunctionTypedFormalParameter is a function type, not dynamic. |
+ _checkForImplicitDynamicIdentifier(node, node.identifier); |
+ |
return super.visitSimpleFormalParameter(node); |
} |
@@ -1116,6 +1154,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> { |
CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_PARAMETER_NAME); |
_checkForTypeParameterSupertypeOfItsBound(node); |
_checkForTypeAnnotationDeferredClass(node.bound); |
+ _checkForImplicitDynamicType(node.bound); |
return super.visitTypeParameter(node); |
} |
@@ -1125,6 +1164,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> { |
Expression initializerNode = node.initializer; |
// do checks |
_checkForInvalidAssignment(nameNode, initializerNode); |
+ _checkForImplicitDynamicIdentifier(node, nameNode); |
// visit name |
nameNode.accept(this); |
// visit initializer |
@@ -1163,6 +1203,12 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> { |
} |
@override |
+ Object visitWithClause(WithClause node) { |
+ node.mixinTypes.forEach(_checkForImplicitDynamicType); |
+ return super.visitWithClause(node); |
+ } |
+ |
+ @override |
Object visitYieldStatement(YieldStatement node) { |
if (_inGenerator) { |
_checkForYieldOfInvalidType(node.expression, node.star != null); |
@@ -3538,6 +3584,113 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> { |
return foundError; |
} |
+ void _checkForImplicitDynamicIdentifier(AstNode node, Identifier id) { |
+ if (_options.implicitDynamic) { |
+ return; |
+ } |
+ VariableElement variable = getVariableElement(id); |
+ if (variable != null && |
+ variable.hasImplicitType && |
+ variable.type.isDynamic) { |
+ ErrorCode errorCode; |
+ if (variable is FieldElement) { |
+ errorCode = StrongModeCode.IMPLICIT_DYNAMIC_FIELD; |
+ } else if (variable is ParameterElement) { |
+ errorCode = StrongModeCode.IMPLICIT_DYNAMIC_PARAMETER; |
+ } else { |
+ errorCode = StrongModeCode.IMPLICIT_DYNAMIC_VARIABLE; |
+ } |
+ _errorReporter.reportErrorForNode(errorCode, node, [id]); |
+ } |
+ } |
+ |
+ void _checkForImplicitDynamicInvoke(InvocationExpression node) { |
+ if (_options.implicitDynamic || |
+ node == null || |
+ node.typeArguments != null) { |
+ return; |
+ } |
+ DartType invokeType = node.staticInvokeType; |
+ DartType declaredType = node.function.staticType; |
+ if (invokeType is FunctionType && declaredType is FunctionType) { |
+ Iterable<DartType> typeArgs = |
+ FunctionTypeImpl.recoverTypeArguments(declaredType, invokeType); |
+ if (typeArgs.any((t) => t.isDynamic)) { |
+ // Issue an error depending on what we're trying to call. |
+ Expression function = node.function; |
+ if (function is Identifier) { |
+ Element element = function.staticElement; |
+ if (element is MethodElement) { |
+ _errorReporter.reportErrorForNode( |
+ StrongModeCode.IMPLICIT_DYNAMIC_METHOD, |
+ node.function, |
+ [element.displayName, element.typeParameters.join(', ')]); |
+ return; |
+ } |
+ |
+ if (element is FunctionElement) { |
+ _errorReporter.reportErrorForNode( |
+ StrongModeCode.IMPLICIT_DYNAMIC_FUNCTION, |
+ node.function, |
+ [element.displayName, element.typeParameters.join(', ')]); |
+ return; |
+ } |
+ } |
+ |
+ // The catch all case if neither of those matched. |
+ // For example, invoking a function expression. |
+ _errorReporter.reportErrorForNode( |
+ StrongModeCode.IMPLICIT_DYNAMIC_INVOKE, |
+ node.function, |
+ [declaredType]); |
+ } |
+ } |
+ } |
+ |
+ void _checkForImplicitDynamicReturn(AstNode node, ExecutableElement element) { |
+ if (_options.implicitDynamic) { |
+ return; |
+ } |
+ if (element is PropertyAccessorElement && element.isSetter) { |
+ return; |
+ } |
+ if (element != null && |
+ element.hasImplicitReturnType && |
+ element.returnType.isDynamic) { |
+ _errorReporter.reportErrorForNode( |
+ StrongModeCode.IMPLICIT_DYNAMIC_RETURN, node, [element.displayName]); |
+ } |
+ } |
+ |
+ void _checkForImplicitDynamicType(TypeName node) { |
+ if (_options.implicitDynamic || |
+ node == null || |
+ node.typeArguments != null) { |
+ return; |
+ } |
+ DartType type = node.type; |
+ if (type is ParameterizedType && |
+ type.typeArguments.isNotEmpty && |
+ type.typeArguments.any((t) => t.isDynamic)) { |
+ _errorReporter.reportErrorForNode( |
+ StrongModeCode.IMPLICIT_DYNAMIC_TYPE, node, [type]); |
+ } |
+ } |
+ |
+ void _checkForImplicitDynamicTypedLiteral(TypedLiteral node) { |
+ if (_options.implicitDynamic || node.typeArguments != null) { |
+ return; |
+ } |
+ DartType type = node.staticType; |
+ // It's an error if either the key or value was inferred as dynamic. |
+ if (type is InterfaceType && type.typeArguments.any((t) => t.isDynamic)) { |
+ ErrorCode errorCode = node is ListLiteral |
+ ? StrongModeCode.IMPLICIT_DYNAMIC_LIST_LITERAL |
+ : StrongModeCode.IMPLICIT_DYNAMIC_MAP_LITERAL; |
+ _errorReporter.reportErrorForNode(errorCode, node); |
+ } |
+ } |
+ |
/** |
* Verify that if the given [identifier] is part of a constructor initializer, |
* then it does not implicitly reference 'this' expression. |