| 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.
|
|
|