Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1484)

Unified Diff: packages/analyzer/lib/src/generated/error_verifier.dart

Issue 2990843002: Removed fixed dependencies (Closed)
Patch Set: Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « packages/analyzer/lib/src/generated/error.dart ('k') | packages/analyzer/lib/src/generated/html.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: packages/analyzer/lib/src/generated/error_verifier.dart
diff --git a/packages/analyzer/lib/src/generated/error_verifier.dart b/packages/analyzer/lib/src/generated/error_verifier.dart
index 7c8516e7343bf4a9f0e7f08177a8ee1baaa3c655..13964bab2dead6462c894514154993267ee22831 100644
--- a/packages/analyzer/lib/src/generated/error_verifier.dart
+++ b/packages/analyzer/lib/src/generated/error_verifier.dart
@@ -2,24 +2,37 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-library engine.resolver.error_verifier;
+library analyzer.src.generated.error_verifier;
import 'dart:collection';
import "dart:math" as math;
-import 'package:analyzer/src/generated/static_type_analyzer.dart';
-
-import 'ast.dart';
-import 'constant.dart';
-import 'element.dart';
-import 'element_resolver.dart';
-import 'error.dart';
-import 'java_engine.dart';
-import 'parser.dart' show Parser, ParserErrorCode;
-import 'resolver.dart';
-import 'scanner.dart' as sc;
-import 'sdk.dart' show DartSdk, SdkLibrary;
-import 'utilities_dart.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/dart/element/visitor.dart';
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/member.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/resolver/inheritance_manager.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/error/pending_error.dart';
+import 'package:analyzer/src/generated/constant.dart';
+import 'package:analyzer/src/generated/element_resolver.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/java_engine.dart';
+import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/sdk.dart' show DartSdk, SdkLibrary;
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'package:analyzer/src/task/dart.dart';
+import 'package:analyzer/src/task/strong/checker.dart' as checker
+ show isKnownFunction;
/**
* A visitor used to traverse an AST structure looking for additional errors and
@@ -64,6 +77,11 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*/
InterfaceType _intType;
+ /**
+ * The options for verification.
+ */
+ AnalysisOptionsImpl _options;
+
/**
* The object providing access to the types defined by the language.
*/
@@ -192,7 +210,13 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
* The class containing the AST nodes being visited, or `null` if we are not
* in the scope of a class.
*/
- ClassElement _enclosingClass;
+ ClassElementImpl _enclosingClass;
+
+ /**
+ * The enum containing the AST nodes being visited, or `null` if we are not
+ * in the scope of an enum.
+ */
+ ClassElement _enclosingEnum;
/**
* The method or function that we are currently visiting, or `null` if we are
@@ -253,6 +277,12 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
HashSet<String> _namesForReferenceToDeclaredVariableInInitializer =
new HashSet<String>();
+ /**
+ * The elements that will be defined later in the current scope, but right
+ * now are not declared.
+ */
+ HiddenElements _hiddenElements = null;
+
/**
* A list of types used by the [CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]
* and [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS] error codes.
@@ -265,11 +295,22 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*/
final bool enableSuperMixins;
+ /**
+ * If `true`, asserts are allowed to take a second argument representing the
+ * assertion failure message (see DEP 37).
+ */
+ final bool enableAssertMessage;
+
/**
* Initialize a newly created error verifier.
*/
- ErrorVerifier(this._errorReporter, this._currentLibrary, this._typeProvider,
- this._inheritanceManager, this.enableSuperMixins) {
+ ErrorVerifier(
+ this._errorReporter,
+ this._currentLibrary,
+ this._typeProvider,
+ this._inheritanceManager,
+ this.enableSuperMixins,
+ this.enableAssertMessage) {
this._isInSystemLibrary = _currentLibrary.source.isInSystemLibrary;
this._hasExtUri = _currentLibrary.hasExtUri;
_isEnclosingConstructorConst = false;
@@ -283,11 +324,13 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
_intType = _typeProvider.intType;
_DISALLOWED_TYPES_TO_EXTEND_OR_IMPLEMENT = _typeProvider.nonSubtypableTypes;
_typeSystem = _currentLibrary.context.typeSystem;
+ _options = _currentLibrary.context.analysisOptions;
}
@override
Object visitAnnotation(Annotation node) {
_checkForInvalidAnnotationFromDeferredLibrary(node);
+ _checkForMissingJSLibAnnotation(node);
return super.visitAnnotation(node);
}
@@ -306,16 +349,17 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
@override
Object visitAssertStatement(AssertStatement node) {
_checkForNonBoolExpression(node);
+ _checkAssertMessage(node);
return super.visitAssertStatement(node);
}
@override
Object visitAssignmentExpression(AssignmentExpression node) {
- sc.TokenType operatorType = node.operator.type;
+ TokenType operatorType = node.operator.type;
Expression lhs = node.leftHandSide;
Expression rhs = node.rightHandSide;
- if (operatorType == sc.TokenType.EQ ||
- operatorType == sc.TokenType.QUESTION_QUESTION_EQ) {
+ if (operatorType == TokenType.EQ ||
+ operatorType == TokenType.QUESTION_QUESTION_EQ) {
_checkForInvalidAssignment(lhs, rhs);
} else {
_checkForInvalidCompoundAssignment(node, lhs, rhs);
@@ -336,10 +380,9 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
@override
Object visitBinaryExpression(BinaryExpression node) {
- sc.Token operator = node.operator;
- sc.TokenType type = operator.type;
- if (type == sc.TokenType.AMPERSAND_AMPERSAND ||
- type == sc.TokenType.BAR_BAR) {
+ Token operator = node.operator;
+ TokenType type = operator.type;
+ if (type == TokenType.AMPERSAND_AMPERSAND || type == TokenType.BAR_BAR) {
String lexeme = operator.lexeme;
_checkForAssignability(node.leftOperand, _boolType,
StaticTypeWarningCode.NON_BOOL_OPERAND, [lexeme]);
@@ -351,6 +394,17 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
return super.visitBinaryExpression(node);
}
+ @override
+ Object visitBlock(Block node) {
+ _hiddenElements = new HiddenElements(_hiddenElements, node);
+ try {
+ _checkDuplicateDeclarationInStatements(node.statements);
+ return super.visitBlock(node);
+ } finally {
+ _hiddenElements = _hiddenElements.outerElements;
+ }
+ }
+
@override
Object visitBlockFunctionBody(BlockFunctionBody node) {
bool wasInAsync = _inAsync;
@@ -391,6 +445,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
@override
Object visitCatchClause(CatchClause node) {
+ _checkDuplicateDefinitionInCatchClause(node);
bool previousIsInCatchClause = _isInCatchClause;
try {
_isInCatchClause = true;
@@ -403,18 +458,19 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
@override
Object visitClassDeclaration(ClassDeclaration node) {
- ClassElement outerClass = _enclosingClass;
+ ClassElementImpl outerClass = _enclosingClass;
try {
_isInNativeClass = node.nativeClause != null;
- _enclosingClass = node.element;
- ExtendsClause extendsClause = node.extendsClause;
- ImplementsClause implementsClause = node.implementsClause;
- WithClause withClause = node.withClause;
+ _enclosingClass = AbstractClassElementImpl.getImpl(node.element);
+ _checkDuplicateClassMembers(node);
_checkForBuiltInIdentifierAsName(
node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME);
_checkForMemberWithClassName();
_checkForNoDefaultSuperConstructorImplicit(node);
_checkForConflictingTypeVariableErrorCodes(node);
+ ExtendsClause extendsClause = node.extendsClause;
+ ImplementsClause implementsClause = node.implementsClause;
+ WithClause withClause = node.withClause;
// Only do error checks on the clause nodes if there is a non-null clause
if (implementsClause != null ||
extendsClause != null ||
@@ -455,15 +511,17 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*/
void visitClassDeclarationIncrementally(ClassDeclaration node) {
_isInNativeClass = node.nativeClause != null;
- _enclosingClass = node.element;
+ _enclosingClass = AbstractClassElementImpl.getImpl(node.element);
// initialize initialFieldElementsMap
if (_enclosingClass != null) {
List<FieldElement> fieldElements = _enclosingClass.fields;
_initialFieldElementsMap = new HashMap<FieldElement, INIT_STATE>();
for (FieldElement fieldElement in fieldElements) {
if (!fieldElement.isSynthetic) {
- _initialFieldElementsMap[fieldElement] = fieldElement.initializer ==
- null ? INIT_STATE.NOT_INIT : INIT_STATE.INIT_IN_DECLARATION;
+ _initialFieldElementsMap[fieldElement] =
+ fieldElement.initializer == null
+ ? INIT_STATE.NOT_INIT
+ : INIT_STATE.INIT_IN_DECLARATION;
}
}
}
@@ -473,9 +531,9 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
Object visitClassTypeAlias(ClassTypeAlias node) {
_checkForBuiltInIdentifierAsName(
node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME);
- ClassElement outerClassElement = _enclosingClass;
+ ClassElementImpl outerClassElement = _enclosingClass;
try {
- _enclosingClass = node.element;
+ _enclosingClass = AbstractClassElementImpl.getImpl(node.element);
ImplementsClause implementsClause = node.implementsClause;
// Only check for all of the inheritance logic around clauses if there
// isn't an error code such as "Cannot extend double" already on the
@@ -507,6 +565,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
@override
Object visitCompilationUnit(CompilationUnit node) {
+ _checkDuplicateUnitMembers(node);
_checkForDeferredPrefixCollisions(node);
return super.visitCompilationUnit(node);
}
@@ -555,7 +614,9 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
SimpleIdentifier fieldName = node.fieldName;
Element staticElement = fieldName.staticElement;
_checkForInvalidField(node, fieldName, staticElement);
- _checkForFieldInitializerNotAssignable(node, staticElement);
+ if (staticElement is FieldElement) {
+ _checkForFieldInitializerNotAssignable(node, staticElement);
+ }
return super.visitConstructorFieldInitializer(node);
} finally {
_isInConstructorInitializer = false;
@@ -591,13 +652,13 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
@override
Object visitEnumDeclaration(EnumDeclaration node) {
- ClassElement outerClass = _enclosingClass;
+ ClassElement outerEnum = _enclosingEnum;
try {
- _isInNativeClass = false;
- _enclosingClass = node.element;
+ _enclosingEnum = node.element;
+ _checkDuplicateEnumMembers(node);
return super.visitEnumDeclaration(node);
} finally {
- _enclosingClass = outerClass;
+ _enclosingEnum = outerEnum;
}
}
@@ -620,12 +681,17 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
try {
_inAsync = node.isAsynchronous;
_inGenerator = node.isGenerator;
- FunctionType functionType =
- _enclosingFunction == null ? null : _enclosingFunction.type;
+ FunctionType functionType = _enclosingFunction?.type;
DartType expectedReturnType = functionType == null
? DynamicTypeImpl.instance
: functionType.returnType;
- _checkForReturnOfInvalidType(node.expression, expectedReturnType);
+ ExecutableElement function = _enclosingFunction;
+ bool isSetterWithImplicitReturn = function.hasImplicitReturnType &&
+ function is PropertyAccessorElement &&
+ function.isSetter;
+ if (!isSetterWithImplicitReturn) {
+ _checkForReturnOfInvalidType(node.expression, expectedReturnType);
+ }
return super.visitExpressionFunctionBody(node);
} finally {
_inAsync = wasInAsync;
@@ -633,6 +699,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;
@@ -663,8 +735,36 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
return super.visitFieldFormalParameter(node);
}
+ @override
+ Object visitForEachStatement(ForEachStatement node) {
+ _checkForInIterable(node);
+ return super.visitForEachStatement(node);
+ }
+
+ @override
+ Object visitFormalParameterList(FormalParameterList node) {
+ _checkDuplicateDefinitionInParameterList(node);
+ return super.visitFormalParameterList(node);
+ }
+
+ @override
+ Object visitForStatement(ForStatement node) {
+ if (node.condition != null) {
+ _checkForNonBoolCondition(node.condition);
+ }
+ if (node.variables != null) {
+ _checkDuplicateVariables(node.variables);
+ }
+ return super.visitForStatement(node);
+ }
+
@override
Object visitFunctionDeclaration(FunctionDeclaration node) {
+ ExecutableElement functionElement = node.element;
+ if (functionElement != null &&
+ functionElement.enclosingElement is! CompilationUnitElement) {
+ _hiddenElements.declare(functionElement);
+ }
ExecutableElement outerFunction = _enclosingFunction;
try {
SimpleIdentifier identifier = node.name;
@@ -672,7 +772,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
if (identifier != null) {
methodName = identifier.name;
}
- _enclosingFunction = node.element;
+ _enclosingFunction = functionElement;
TypeName returnType = node.returnType;
if (node.isSetter || node.isGetter) {
_checkForMismatchedAccessorTypes(node, methodName);
@@ -691,6 +791,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
}
_checkForTypeAnnotationDeferredClass(returnType);
_checkForIllegalReturnType(returnType);
+ _checkForImplicitDynamicReturn(node, node.element);
return super.visitFunctionDeclaration(node);
} finally {
_enclosingFunction = outerFunction;
@@ -722,7 +823,10 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
_errorReporter.reportErrorForNode(
StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION_EXPRESSION,
functionExpression);
+ } else if (expressionType is FunctionType) {
+ _checkTypeArguments(expressionType.element, node.typeArguments);
}
+ _checkForImplicitDynamicInvoke(node);
return super.visitFunctionExpressionInvocation(node);
}
@@ -741,6 +845,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;
@@ -753,6 +869,12 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
return super.visitIfStatement(node);
}
+ @override
+ Object visitImplementsClause(ImplementsClause node) {
+ node.interfaces.forEach(_checkForImplicitDynamicType);
+ return super.visitImplementsClause(node);
+ }
+
@override
Object visitImportDirective(ImportDirective node) {
ImportElement importElement = node.element;
@@ -778,19 +900,21 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
TypeName typeName = constructorName.type;
DartType type = typeName.type;
if (type is InterfaceType) {
- InterfaceType interfaceType = type;
- _checkForConstOrNewWithAbstractClass(node, typeName, interfaceType);
- _checkForConstOrNewWithEnum(node, typeName, interfaceType);
+ _checkForConstOrNewWithAbstractClass(node, typeName, type);
+ _checkForConstOrNewWithEnum(node, typeName, type);
if (_isInConstInstanceCreation) {
_checkForConstWithNonConst(node);
_checkForConstWithUndefinedConstructor(
node, constructorName, typeName);
- _checkForConstWithTypeParameters(typeName);
+ if (!_options.strongMode) {
+ _checkForConstWithTypeParameters(typeName);
+ }
_checkForConstDeferredClass(node, constructorName, typeName);
} else {
_checkForNewWithUndefinedConstructor(node, constructorName, typeName);
}
}
+ _checkForImplicitDynamicType(typeName);
return super.visitInstanceCreationExpression(node);
} finally {
_isInConstInstanceCreation = wasInConstInstanceCreation;
@@ -807,16 +931,17 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
Object visitListLiteral(ListLiteral node) {
TypeArgumentList typeArguments = node.typeArguments;
if (typeArguments != null) {
- if (node.constKeyword != null) {
+ if (!_options.strongMode && node.constKeyword != null) {
NodeList<TypeName> arguments = typeArguments.arguments;
- if (arguments.length != 0) {
+ if (arguments.isNotEmpty) {
_checkForInvalidTypeArgumentInConstTypedLiteral(arguments,
CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_LIST);
}
}
_checkForExpectedOneListTypeArgument(node, typeArguments);
- _checkForListElementTypeNotAssignable(node, typeArguments);
}
+ _checkForImplicitDynamicTypedLiteral(node);
+ _checkForListElementTypeNotAssignable(node);
return super.visitListLiteral(node);
}
@@ -825,15 +950,16 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
TypeArgumentList typeArguments = node.typeArguments;
if (typeArguments != null) {
NodeList<TypeName> arguments = typeArguments.arguments;
- if (arguments.length != 0) {
+ if (!_options.strongMode && arguments.isNotEmpty) {
if (node.constKeyword != null) {
_checkForInvalidTypeArgumentInConstTypedLiteral(arguments,
CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP);
}
}
_checkExpectedTwoMapTypeArguments(typeArguments);
- _checkForMapTypeNotAssignable(node, typeArguments);
}
+ _checkForImplicitDynamicTypedLiteral(node);
+ _checkForMapTypeNotAssignable(node);
_checkForNonConstMapAsExpressionStatement(node);
return super.visitMapLiteral(node);
}
@@ -871,6 +997,8 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
_checkForAllInvalidOverrideErrorCodesForMethod(node);
_checkForTypeAnnotationDeferredClass(returnTypeName);
_checkForIllegalReturnType(returnTypeName);
+ _checkForImplicitDynamicReturn(node, node.element);
+ _checkForMustCallSuper(node);
return super.visitMethodDeclaration(node);
} finally {
_enclosingFunction = previousFunction;
@@ -889,6 +1017,9 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
} else {
_checkForUnqualifiedReferenceToNonLocalStaticMember(methodName);
}
+ _checkTypeArguments(
+ node.methodName.staticElement, node.typeArguments, target?.staticType);
+ _checkForImplicitDynamicInvoke(node);
return super.visitMethodInvocation(node);
}
@@ -905,7 +1036,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
@override
Object visitNativeFunctionBody(NativeFunctionBody node) {
- _checkForNativeFunctionBodyInNonSDKCode(node);
+ _checkForNativeFunctionBodyInNonSdkCode(node);
return super.visitNativeFunctionBody(node);
}
@@ -930,9 +1061,9 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
@override
Object visitPrefixExpression(PrefixExpression node) {
- sc.TokenType operatorType = node.operator.type;
+ TokenType operatorType = node.operator.type;
Expression operand = node.operand;
- if (operatorType == sc.TokenType.BANG) {
+ if (operatorType == TokenType.BANG) {
_checkForNonBoolNegationExpression(operand);
} else if (operatorType.isIncrementOperator) {
_checkForAssignmentToFinal(operand);
@@ -984,11 +1115,22 @@ 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);
}
@override
Object visitSimpleIdentifier(SimpleIdentifier node) {
+ _checkForAmbiguousImport(node);
+ _checkForReferenceBeforeDeclaration(node);
_checkForImplicitThisReferenceInInitializer(node);
if (!_isUnqualifiedReferenceToNonLocalStaticMemberAllowed(node)) {
_checkForUnqualifiedReferenceToNonLocalStaticMember(node);
@@ -1006,6 +1148,18 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
}
}
+ @override
+ Object visitSwitchCase(SwitchCase node) {
+ _checkDuplicateDeclarationInStatements(node.statements);
+ return super.visitSwitchCase(node);
+ }
+
+ @override
+ Object visitSwitchDefault(SwitchDefault node) {
+ _checkDuplicateDeclarationInStatements(node.statements);
+ return super.visitSwitchDefault(node);
+ }
+
@override
Object visitSwitchStatement(SwitchStatement node) {
_checkForSwitchExpressionNotAssignable(node);
@@ -1054,15 +1208,23 @@ 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);
}
+ @override
+ Object visitTypeParameterList(TypeParameterList node) {
+ _checkDuplicateDefinitionInTypeParameterList(node);
+ return super.visitTypeParameterList(node);
+ }
+
@override
Object visitVariableDeclaration(VariableDeclaration node) {
SimpleIdentifier nameNode = node.name;
Expression initializerNode = node.initializer;
// do checks
_checkForInvalidAssignment(nameNode, initializerNode);
+ _checkForImplicitDynamicIdentifier(node, nameNode);
// visit name
nameNode.accept(this);
// visit initializer
@@ -1078,6 +1240,15 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
_isInInstanceVariableInitializer = wasInInstanceVariableInitializer;
_namesForReferenceToDeclaredVariableInInitializer.remove(name);
}
+ // declare the variable
+ AstNode grandparent = node.parent.parent;
+ if (grandparent is! TopLevelVariableDeclaration &&
+ grandparent is! FieldDeclaration) {
+ VariableElement element = node.element;
+ if (element != null) {
+ _hiddenElements.declare(element);
+ }
+ }
// done
return null;
}
@@ -1100,6 +1271,12 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
return super.visitWhileStatement(node);
}
+ @override
+ Object visitWithClause(WithClause node) {
+ node.mixinTypes.forEach(_checkForImplicitDynamicType);
+ return super.visitWithClause(node);
+ }
+
@override
Object visitYieldStatement(YieldStatement node) {
if (_inGenerator) {
@@ -1116,24 +1293,267 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
return super.visitYieldStatement(node);
}
+ /**
+ * If the given assert [statement] specifies a message, verify that support
+ * for assertions with messages is enabled.
+ */
+ void _checkAssertMessage(AssertStatement statement) {
+ Expression expression = statement.message;
+ if (expression != null && !enableAssertMessage) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.EXTRA_ARGUMENT_TO_ASSERT, expression);
+ }
+ }
+
+ /**
+ * Given a list of [directives] that have the same prefix, generate an error
+ * if there is more than one import and any of those imports is deferred.
+ *
+ * See [CompileTimeErrorCode.SHARED_DEFERRED_PREFIX].
+ */
+ void _checkDeferredPrefixCollision(List<ImportDirective> directives) {
+ int count = directives.length;
+ if (count > 1) {
+ for (int i = 0; i < count; i++) {
+ Token deferredToken = directives[i].deferredKeyword;
+ if (deferredToken != null) {
+ _errorReporter.reportErrorForToken(
+ CompileTimeErrorCode.SHARED_DEFERRED_PREFIX, deferredToken);
+ }
+ }
+ }
+ }
+
+ /**
+ * Check that there are no members with the same name.
+ */
+ void _checkDuplicateClassMembers(ClassDeclaration node) {
+ Map<String, Element> definedNames = new HashMap<String, Element>();
+ Set<String> visitedFields = new HashSet<String>();
+ for (ClassMember member in node.members) {
+ // We ignore constructors because they are checked in the method
+ // _checkForConflictingConstructorNameAndMember.
+ if (member is FieldDeclaration) {
+ for (VariableDeclaration field in member.fields.variables) {
+ SimpleIdentifier identifier = field.name;
+ _checkDuplicateIdentifier(definedNames, identifier);
+ String name = identifier.name;
+ if (!field.isFinal &&
+ !field.isConst &&
+ !visitedFields.contains(name)) {
+ _checkDuplicateIdentifier(definedNames, identifier,
+ implicitSetter: true);
+ }
+ visitedFields.add(name);
+ }
+ } else if (member is MethodDeclaration) {
+ _checkDuplicateIdentifier(definedNames, member.name);
+ }
+ }
+ }
+
+ /**
+ * Check that all of the parameters have unique names.
+ */
+ void _checkDuplicateDeclarationInStatements(List<Statement> statements) {
+ Map<String, Element> definedNames = new HashMap<String, Element>();
+ for (Statement statement in statements) {
+ if (statement is VariableDeclarationStatement) {
+ for (VariableDeclaration variable in statement.variables.variables) {
+ _checkDuplicateIdentifier(definedNames, variable.name);
+ }
+ } else if (statement is FunctionDeclarationStatement) {
+ _checkDuplicateIdentifier(
+ definedNames, statement.functionDeclaration.name);
+ }
+ }
+ }
+
+ /**
+ * Check that the exception and stack trace parameters have different names.
+ */
+ void _checkDuplicateDefinitionInCatchClause(CatchClause node) {
+ SimpleIdentifier exceptionParameter = node.exceptionParameter;
+ SimpleIdentifier stackTraceParameter = node.stackTraceParameter;
+ if (exceptionParameter != null && stackTraceParameter != null) {
+ String exceptionName = exceptionParameter.name;
+ if (exceptionName == stackTraceParameter.name) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.DUPLICATE_DEFINITION,
+ stackTraceParameter,
+ [exceptionName]);
+ }
+ }
+ }
+
+ /**
+ * Check that all of the parameters have unique names.
+ */
+ void _checkDuplicateDefinitionInParameterList(FormalParameterList node) {
+ Map<String, Element> definedNames = new HashMap<String, Element>();
+ for (FormalParameter parameter in node.parameters) {
+ _checkDuplicateIdentifier(definedNames, parameter.identifier);
+ }
+ }
+
+ /**
+ * Check that all of the parameters have unique names.
+ */
+ void _checkDuplicateDefinitionInTypeParameterList(TypeParameterList node) {
+ Map<String, Element> definedNames = new HashMap<String, Element>();
+ for (TypeParameter parameter in node.typeParameters) {
+ _checkDuplicateIdentifier(definedNames, parameter.name);
+ }
+ }
+
+ /**
+ * Check that there are no members with the same name.
+ */
+ void _checkDuplicateEnumMembers(EnumDeclaration node) {
+ Map<String, Element> definedNames = new HashMap<String, Element>();
+ ClassElement element = node.element;
+ String indexName = 'index';
+ String valuesName = 'values';
+ definedNames[indexName] = element.getField(indexName);
+ definedNames[valuesName] = element.getField(valuesName);
+ for (EnumConstantDeclaration constant in node.constants) {
+ _checkDuplicateIdentifier(definedNames, constant.name);
+ }
+ }
+
+ /**
+ * Check whether the given [identifier] is already in the set of
+ * [definedNames], and produce an error if it is. If [implicitSetter] is
+ * `true`, then the identifier represents the definition of a setter.
+ */
+ void _checkDuplicateIdentifier(
+ Map<String, Element> definedNames, SimpleIdentifier identifier,
+ {bool implicitSetter: false}) {
+ ErrorCode getError(Element previous, Element current) {
+ if (previous is MethodElement && current is PropertyAccessorElement) {
+ if (current.isGetter) {
+ return CompileTimeErrorCode.GETTER_AND_METHOD_WITH_SAME_NAME;
+ }
+ } else if (previous is PropertyAccessorElement &&
+ current is MethodElement) {
+ if (previous.isGetter) {
+ return CompileTimeErrorCode.METHOD_AND_GETTER_WITH_SAME_NAME;
+ }
+ } else if (previous is PrefixElement) {
+ return CompileTimeErrorCode.PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER;
+ }
+ return CompileTimeErrorCode.DUPLICATE_DEFINITION;
+ }
+
+ Element current = identifier.staticElement;
+ String name = identifier.name;
+ if (current is PropertyAccessorElement && current.isSetter) {
+ name += '=';
+ } else if (current is MethodElement && current.isOperator && name == '-') {
+ if (current.parameters.length == 0) {
+ name = 'unary-';
+ }
+ } else if (implicitSetter) {
+ name += '=';
+ }
+ Element previous = definedNames[name];
+ if (previous != null) {
+ _errorReporter
+ .reportErrorForNode(getError(previous, current), identifier, [name]);
+ } else {
+ definedNames[name] = identifier.staticElement;
+ }
+ }
+
+ /**
+ * Check that there are no members with the same name.
+ */
+ void _checkDuplicateUnitMembers(CompilationUnit node) {
+ Map<String, Element> definedNames = new HashMap<String, Element>();
+ void addWithoutChecking(CompilationUnitElement element) {
+ for (PropertyAccessorElement accessor in element.accessors) {
+ String name = accessor.name;
+ if (accessor.isSetter) {
+ name += '=';
+ }
+ definedNames[name] = accessor;
+ }
+ for (ClassElement type in element.enums) {
+ definedNames[type.name] = type;
+ }
+ for (FunctionElement function in element.functions) {
+ definedNames[function.name] = function;
+ }
+ for (FunctionTypeAliasElement alias in element.functionTypeAliases) {
+ definedNames[alias.name] = alias;
+ }
+ for (TopLevelVariableElement variable in element.topLevelVariables) {
+ definedNames[variable.name] = variable;
+ if (!variable.isFinal && !variable.isConst) {
+ definedNames[variable.name + '='] = variable;
+ }
+ }
+ for (ClassElement type in element.types) {
+ definedNames[type.name] = type;
+ }
+ }
+
+ for (ImportElement importElement in _currentLibrary.imports) {
+ PrefixElement prefix = importElement.prefix;
+ if (prefix != null) {
+ definedNames[prefix.name] = prefix;
+ }
+ }
+ CompilationUnitElement element = node.element;
+ if (element != _currentLibrary.definingCompilationUnit) {
+ addWithoutChecking(_currentLibrary.definingCompilationUnit);
+ for (CompilationUnitElement part in _currentLibrary.parts) {
+ if (element == part) {
+ break;
+ }
+ addWithoutChecking(part);
+ }
+ }
+ for (CompilationUnitMember member in node.declarations) {
+ if (member is NamedCompilationUnitMember) {
+ _checkDuplicateIdentifier(definedNames, member.name);
+ } else if (member is TopLevelVariableDeclaration) {
+ for (VariableDeclaration variable in member.variables.variables) {
+ _checkDuplicateIdentifier(definedNames, variable.name);
+ if (!variable.isFinal && !variable.isConst) {
+ _checkDuplicateIdentifier(definedNames, variable.name,
+ implicitSetter: true);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Check that the given list of variable declarations does not define multiple
+ * variables of the same name.
+ */
+ void _checkDuplicateVariables(VariableDeclarationList node) {
+ Map<String, Element> definedNames = new HashMap<String, Element>();
+ for (VariableDeclaration variable in node.variables) {
+ _checkDuplicateIdentifier(definedNames, variable.name);
+ }
+ }
+
/**
* Verify that the given list of [typeArguments] contains exactly two
* elements.
*
* See [StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS].
*/
- bool _checkExpectedTwoMapTypeArguments(TypeArgumentList typeArguments) {
- // check number of type arguments
+ void _checkExpectedTwoMapTypeArguments(TypeArgumentList typeArguments) {
int num = typeArguments.arguments.length;
- if (num == 2) {
- return false;
+ if (num != 2) {
+ _errorReporter.reportErrorForNode(
+ StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS,
+ typeArguments,
+ [num]);
}
- // report problem
- _errorReporter.reportErrorForNode(
- StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS,
- typeArguments,
- [num]);
- return true;
}
/**
@@ -1145,28 +1565,32 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
* [StaticWarningCode.FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR], and
* [CompileTimeErrorCode.FINAL_INITIALIZED_MULTIPLE_TIMES].
*/
- bool _checkForAllFinalInitializedErrorCodes(
+ void _checkForAllFinalInitializedErrorCodes(
ConstructorDeclaration constructor) {
if (constructor.factoryKeyword != null ||
constructor.redirectedConstructor != null ||
constructor.externalKeyword != null) {
- return false;
+ return;
}
// Ignore if native class.
if (_isInNativeClass) {
- return false;
+ return;
}
- bool foundError = false;
+
HashMap<FieldElement, INIT_STATE> fieldElementsMap =
new HashMap<FieldElement, INIT_STATE>.from(_initialFieldElementsMap);
// Visit all of the field formal parameters
NodeList<FormalParameter> formalParameters =
constructor.parameters.parameters;
for (FormalParameter formalParameter in formalParameters) {
- FormalParameter parameter = formalParameter;
- if (parameter is DefaultFormalParameter) {
- parameter = (parameter as DefaultFormalParameter).parameter;
+ FormalParameter baseParameter(FormalParameter parameter) {
+ if (parameter is DefaultFormalParameter) {
+ return parameter.parameter;
+ }
+ return parameter;
}
+
+ FormalParameter parameter = baseParameter(formalParameter);
if (parameter is FieldFormalParameter) {
FieldElement fieldElement =
(parameter.element as FieldFormalParameterElementImpl).field;
@@ -1176,10 +1600,10 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
} else if (state == INIT_STATE.INIT_IN_DECLARATION) {
if (fieldElement.isFinal || fieldElement.isConst) {
_errorReporter.reportErrorForNode(
- StaticWarningCode.FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR,
+ StaticWarningCode
+ .FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR,
formalParameter.identifier,
[fieldElement.displayName]);
- foundError = true;
}
} else if (state == INIT_STATE.INIT_IN_FIELD_FORMAL) {
if (fieldElement.isFinal || fieldElement.isConst) {
@@ -1187,7 +1611,6 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
CompileTimeErrorCode.FINAL_INITIALIZED_MULTIPLE_TIMES,
formalParameter.identifier,
[fieldElement.displayName]);
- foundError = true;
}
}
}
@@ -1196,36 +1619,32 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
NodeList<ConstructorInitializer> initializers = constructor.initializers;
for (ConstructorInitializer constructorInitializer in initializers) {
if (constructorInitializer is RedirectingConstructorInvocation) {
- return false;
+ return;
}
if (constructorInitializer is ConstructorFieldInitializer) {
- ConstructorFieldInitializer constructorFieldInitializer =
- constructorInitializer;
- SimpleIdentifier fieldName = constructorFieldInitializer.fieldName;
+ SimpleIdentifier fieldName = constructorInitializer.fieldName;
Element element = fieldName.staticElement;
if (element is FieldElement) {
- FieldElement fieldElement = element;
- INIT_STATE state = fieldElementsMap[fieldElement];
+ INIT_STATE state = fieldElementsMap[element];
if (state == INIT_STATE.NOT_INIT) {
- fieldElementsMap[fieldElement] = INIT_STATE.INIT_IN_INITIALIZERS;
+ fieldElementsMap[element] = INIT_STATE.INIT_IN_INITIALIZERS;
} else if (state == INIT_STATE.INIT_IN_DECLARATION) {
- if (fieldElement.isFinal || fieldElement.isConst) {
+ if (element.isFinal || element.isConst) {
_errorReporter.reportErrorForNode(
- StaticWarningCode.FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION,
+ StaticWarningCode
+ .FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION,
fieldName);
- foundError = true;
}
} else if (state == INIT_STATE.INIT_IN_FIELD_FORMAL) {
_errorReporter.reportErrorForNode(
- CompileTimeErrorCode.FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER,
+ CompileTimeErrorCode
+ .FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER,
fieldName);
- foundError = true;
} else if (state == INIT_STATE.INIT_IN_INITIALIZERS) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS,
fieldName,
- [fieldElement.displayName]);
- foundError = true;
+ [element.displayName]);
}
}
}
@@ -1248,42 +1667,39 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
CompileTimeErrorCode.CONST_NOT_INITIALIZED,
constructor.returnType,
[fieldElement.name]);
- foundError = true;
}
}
});
+
if (notInitFinalFields.isNotEmpty) {
- foundError = true;
AnalysisErrorWithProperties analysisError;
- if (notInitFinalFields.length == 1) {
+ List<String> names = notInitFinalFields.map((item) => item.name).toList();
+ names.sort();
+ if (names.length == 1) {
analysisError = _errorReporter.newErrorWithProperties(
StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1,
constructor.returnType,
- [notInitFinalFields[0].name]);
- } else if (notInitFinalFields.length == 2) {
+ names);
+ } else if (names.length == 2) {
analysisError = _errorReporter.newErrorWithProperties(
StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_2,
constructor.returnType,
- [notInitFinalFields[0].name, notInitFinalFields[1].name]);
+ names);
} else {
analysisError = _errorReporter.newErrorWithProperties(
StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_3_PLUS,
- constructor.returnType, [
- notInitFinalFields[0].name,
- notInitFinalFields[1].name,
- notInitFinalFields.length - 2
- ]);
+ constructor.returnType,
+ [names[0], names[1], names.length - 2]);
}
analysisError.setProperty(
ErrorProperty.NOT_INITIALIZED_FIELDS, notInitFinalFields);
_errorReporter.reportError(analysisError);
}
- return foundError;
}
/**
- * Check the given [executableElement] against override-error codes. The
- * [overriddenExecutable] is the element that the executable element is
+ * Check the given [derivedElement] against override-error codes. The
+ * [baseElement] is the element that the executable element is
* overriding. The [parameters] is the parameters of the executable element.
* The [errorNameTarget] is the node to report problems on.
*
@@ -1300,83 +1716,152 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
* [StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES].
*/
bool _checkForAllInvalidOverrideErrorCodes(
- ExecutableElement executableElement,
- ExecutableElement overriddenExecutable,
+ ExecutableElement derivedElement,
+ ExecutableElement baseElement,
List<ParameterElement> parameters,
List<AstNode> parameterLocations,
SimpleIdentifier errorNameTarget) {
+ if (_options.strongMode) {
+ return false; // strong mode already checked for this
+ }
+
bool isGetter = false;
bool isSetter = false;
- if (executableElement is PropertyAccessorElement) {
- PropertyAccessorElement accessorElement = executableElement;
- isGetter = accessorElement.isGetter;
- isSetter = accessorElement.isSetter;
+ if (derivedElement is PropertyAccessorElement) {
+ isGetter = derivedElement.isGetter;
+ isSetter = derivedElement.isSetter;
}
- String executableElementName = executableElement.name;
- FunctionType overridingFT = executableElement.type;
- FunctionType overriddenFT = overriddenExecutable.type;
+ String executableElementName = derivedElement.name;
+ FunctionType derivedFT = derivedElement.type;
+ FunctionType baseFT = baseElement.type;
InterfaceType enclosingType = _enclosingClass.type;
- overriddenFT = _inheritanceManager
- .substituteTypeArgumentsInMemberFromInheritance(
- overriddenFT, executableElementName, enclosingType);
- if (overridingFT == null || overriddenFT == null) {
+ baseFT = _inheritanceManager.substituteTypeArgumentsInMemberFromInheritance(
+ baseFT, executableElementName, enclosingType);
+ if (derivedFT == null || baseFT == null) {
return false;
}
- DartType overridingFTReturnType = overridingFT.returnType;
- DartType overriddenFTReturnType = overriddenFT.returnType;
- List<DartType> overridingNormalPT = overridingFT.normalParameterTypes;
- List<DartType> overriddenNormalPT = overriddenFT.normalParameterTypes;
- List<DartType> overridingPositionalPT = overridingFT.optionalParameterTypes;
- List<DartType> overriddenPositionalPT = overriddenFT.optionalParameterTypes;
- Map<String, DartType> overridingNamedPT = overridingFT.namedParameterTypes;
- Map<String, DartType> overriddenNamedPT = overriddenFT.namedParameterTypes;
+
+ // Handle generic function type parameters.
+ // TODO(jmesserly): this duplicates some code in isSubtypeOf and most of
+ // _isGenericFunctionSubtypeOf. Ideally, we'd let TypeSystem produce
+ // an error message once it's ready to "return false".
+ if (!derivedFT.typeFormals.isEmpty) {
+ if (baseFT.typeFormals.isEmpty) {
+ derivedFT = _typeSystem.instantiateToBounds(derivedFT);
+ } else {
+ List<TypeParameterElement> params1 = derivedFT.typeFormals;
+ List<TypeParameterElement> params2 = baseFT.typeFormals;
+ int count = params1.length;
+ if (params2.length != count) {
+ _errorReporter.reportErrorForNode(
+ StaticWarningCode.INVALID_METHOD_OVERRIDE_TYPE_PARAMETERS,
+ errorNameTarget, [
+ count,
+ params2.length,
+ baseElement.enclosingElement.displayName
+ ]);
+ return true;
+ }
+ // We build up a substitution matching up the type parameters
+ // from the two types, {variablesFresh/variables1} and
+ // {variablesFresh/variables2}
+ List<DartType> variables1 = new List<DartType>();
+ List<DartType> variables2 = new List<DartType>();
+ List<DartType> variablesFresh = new List<DartType>();
+ for (int i = 0; i < count; i++) {
+ TypeParameterElement p1 = params1[i];
+ TypeParameterElement p2 = params2[i];
+ TypeParameterElementImpl pFresh =
+ new TypeParameterElementImpl(p1.name, -1);
+
+ DartType variable1 = p1.type;
+ DartType variable2 = p2.type;
+ DartType variableFresh = new TypeParameterTypeImpl(pFresh);
+
+ variables1.add(variable1);
+ variables2.add(variable2);
+ variablesFresh.add(variableFresh);
+ DartType bound1 = p1.bound ?? DynamicTypeImpl.instance;
+ DartType bound2 = p2.bound ?? DynamicTypeImpl.instance;
+ bound1 = bound1.substitute2(variablesFresh, variables1);
+ bound2 = bound2.substitute2(variablesFresh, variables2);
+ pFresh.bound = bound2;
+ if (!_typeSystem.isSubtypeOf(bound2, bound1)) {
+ _errorReporter.reportErrorForNode(
+ StaticWarningCode.INVALID_METHOD_OVERRIDE_TYPE_PARAMETER_BOUND,
+ errorNameTarget, [
+ p1.displayName,
+ p1.bound,
+ p2.displayName,
+ p2.bound,
+ baseElement.enclosingElement.displayName
+ ]);
+ return true;
+ }
+ }
+ // Proceed with the rest of the checks, using instantiated types.
+ derivedFT = derivedFT.instantiate(variablesFresh);
+ baseFT = baseFT.instantiate(variablesFresh);
+ }
+ }
+
+ DartType derivedFTReturnType = derivedFT.returnType;
+ DartType baseFTReturnType = baseFT.returnType;
+ List<DartType> derivedNormalPT = derivedFT.normalParameterTypes;
+ List<DartType> baseNormalPT = baseFT.normalParameterTypes;
+ List<DartType> derivedPositionalPT = derivedFT.optionalParameterTypes;
+ List<DartType> basePositionalPT = baseFT.optionalParameterTypes;
+ Map<String, DartType> derivedNamedPT = derivedFT.namedParameterTypes;
+ Map<String, DartType> baseNamedPT = baseFT.namedParameterTypes;
// CTEC.INVALID_OVERRIDE_REQUIRED, CTEC.INVALID_OVERRIDE_POSITIONAL and
// CTEC.INVALID_OVERRIDE_NAMED
- if (overridingNormalPT.length > overriddenNormalPT.length) {
+ if (derivedNormalPT.length > baseNormalPT.length) {
_errorReporter.reportErrorForNode(
StaticWarningCode.INVALID_OVERRIDE_REQUIRED, errorNameTarget, [
- overriddenNormalPT.length,
- overriddenExecutable.enclosingElement.displayName
+ baseNormalPT.length,
+ baseElement,
+ baseElement.enclosingElement.displayName
]);
return true;
}
- if (overridingNormalPT.length + overridingPositionalPT.length <
- overriddenPositionalPT.length + overriddenNormalPT.length) {
+ if (derivedNormalPT.length + derivedPositionalPT.length <
+ basePositionalPT.length + baseNormalPT.length) {
_errorReporter.reportErrorForNode(
StaticWarningCode.INVALID_OVERRIDE_POSITIONAL, errorNameTarget, [
- overriddenPositionalPT.length + overriddenNormalPT.length,
- overriddenExecutable.enclosingElement.displayName
+ basePositionalPT.length + baseNormalPT.length,
+ baseElement,
+ baseElement.enclosingElement.displayName
]);
return true;
}
// For each named parameter in the overridden method, verify that there is
// the same name in the overriding method.
- for (String overriddenParamName in overriddenNamedPT.keys) {
- if (!overridingNamedPT.containsKey(overriddenParamName)) {
+ for (String overriddenParamName in baseNamedPT.keys) {
+ if (!derivedNamedPT.containsKey(overriddenParamName)) {
// The overridden method expected the overriding method to have
// overridingParamName, but it does not.
_errorReporter.reportErrorForNode(
StaticWarningCode.INVALID_OVERRIDE_NAMED, errorNameTarget, [
overriddenParamName,
- overriddenExecutable.enclosingElement.displayName
+ baseElement,
+ baseElement.enclosingElement.displayName
]);
return true;
}
}
// SWC.INVALID_METHOD_OVERRIDE_RETURN_TYPE
- if (overriddenFTReturnType != VoidTypeImpl.instance &&
- !_typeSystem.isAssignableTo(
- overridingFTReturnType, overriddenFTReturnType)) {
+ if (baseFTReturnType != VoidTypeImpl.instance &&
+ !_typeSystem.isAssignableTo(derivedFTReturnType, baseFTReturnType)) {
_errorReporter.reportTypeErrorForNode(
!isGetter
? StaticWarningCode.INVALID_METHOD_OVERRIDE_RETURN_TYPE
: StaticWarningCode.INVALID_GETTER_OVERRIDE_RETURN_TYPE,
errorNameTarget,
[
- overridingFTReturnType,
- overriddenFTReturnType,
- overriddenExecutable.enclosingElement.displayName
- ]);
+ derivedFTReturnType,
+ baseFTReturnType,
+ baseElement.enclosingElement.displayName
+ ]);
return true;
}
// SWC.INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE
@@ -1384,33 +1869,32 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
return false;
}
int parameterIndex = 0;
- for (int i = 0; i < overridingNormalPT.length; i++) {
- if (!_typeSystem.isAssignableTo(
- overridingNormalPT[i], overriddenNormalPT[i])) {
+ for (int i = 0; i < derivedNormalPT.length; i++) {
+ if (!_typeSystem.isAssignableTo(baseNormalPT[i], derivedNormalPT[i])) {
_errorReporter.reportTypeErrorForNode(
!isSetter
? StaticWarningCode.INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE
: StaticWarningCode.INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE,
parameterLocations[parameterIndex],
[
- overridingNormalPT[i],
- overriddenNormalPT[i],
- overriddenExecutable.enclosingElement.displayName
- ]);
+ derivedNormalPT[i],
+ baseNormalPT[i],
+ baseElement.enclosingElement.displayName
+ ]);
return true;
}
parameterIndex++;
}
// SWC.INVALID_METHOD_OVERRIDE_OPTIONAL_PARAM_TYPE
- for (int i = 0; i < overriddenPositionalPT.length; i++) {
+ for (int i = 0; i < basePositionalPT.length; i++) {
if (!_typeSystem.isAssignableTo(
- overridingPositionalPT[i], overriddenPositionalPT[i])) {
+ basePositionalPT[i], derivedPositionalPT[i])) {
_errorReporter.reportTypeErrorForNode(
StaticWarningCode.INVALID_METHOD_OVERRIDE_OPTIONAL_PARAM_TYPE,
parameterLocations[parameterIndex], [
- overridingPositionalPT[i],
- overriddenPositionalPT[i],
- overriddenExecutable.enclosingElement.displayName
+ derivedPositionalPT[i],
+ basePositionalPT[i],
+ baseElement.enclosingElement.displayName
]);
return true;
}
@@ -1418,15 +1902,15 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
}
// SWC.INVALID_METHOD_OVERRIDE_NAMED_PARAM_TYPE &
// SWC.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES
- for (String overriddenName in overriddenNamedPT.keys) {
- DartType overridingType = overridingNamedPT[overriddenName];
- if (overridingType == null) {
+ for (String overriddenName in baseNamedPT.keys) {
+ DartType derivedType = derivedNamedPT[overriddenName];
+ if (derivedType == null) {
// Error, this is never reached- INVALID_OVERRIDE_NAMED would have been
// created above if this could be reached.
continue;
}
- DartType overriddenType = overriddenNamedPT[overriddenName];
- if (!_typeSystem.isAssignableTo(overriddenType, overridingType)) {
+ DartType baseType = baseNamedPT[overriddenName];
+ if (!_typeSystem.isAssignableTo(baseType, derivedType)) {
// lookup the parameter for the error to select
ParameterElement parameterToSelect = null;
AstNode parameterLocationToSelect = null;
@@ -1443,9 +1927,9 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
_errorReporter.reportTypeErrorForNode(
StaticWarningCode.INVALID_METHOD_OVERRIDE_NAMED_PARAM_TYPE,
parameterLocationToSelect, [
- overridingType,
- overriddenType,
- overriddenExecutable.enclosingElement.displayName
+ derivedType,
+ baseType,
+ baseElement.enclosingElement.displayName
]);
return true;
}
@@ -1463,7 +1947,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
List<ParameterElementImpl> parameterElts = new List<ParameterElementImpl>();
List<ParameterElementImpl> overriddenParameterElts =
new List<ParameterElementImpl>();
- List<ParameterElement> overriddenPEs = overriddenExecutable.parameters;
+ List<ParameterElement> overriddenPEs = baseElement.parameters;
for (int i = 0; i < parameters.length; i++) {
ParameterElement parameter = parameters[i];
if (parameter.parameterKind.isOptional) {
@@ -1512,12 +1996,14 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
}
if (!result.equalValues(_typeProvider, overriddenResult)) {
_errorReporter.reportErrorForNode(
- StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
- formalParameters[i], [
- overriddenExecutable.enclosingElement.displayName,
- overriddenExecutable.displayName,
- parameterName
- ]);
+ StaticWarningCode
+ .INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
+ formalParameters[i],
+ [
+ baseElement.enclosingElement.displayName,
+ baseElement.displayName,
+ parameterName
+ ]);
foundError = true;
}
}
@@ -1549,11 +2035,13 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
}
if (!result.equalValues(_typeProvider, overriddenResult)) {
_errorReporter.reportErrorForNode(
- StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
- formalParameters[i], [
- overriddenExecutable.enclosingElement.displayName,
- overriddenExecutable.displayName
- ]);
+ StaticWarningCode
+ .INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
+ formalParameters[i],
+ [
+ baseElement.enclosingElement.displayName,
+ baseElement.displayName
+ ]);
foundError = true;
}
}
@@ -1571,11 +2059,12 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
* the parameters of the executable element. The [errorNameTarget] is the node
* to report problems on.
*/
- bool _checkForAllInvalidOverrideErrorCodesForExecutable(
+ void _checkForAllInvalidOverrideErrorCodesForExecutable(
ExecutableElement executableElement,
List<ParameterElement> parameters,
List<AstNode> parameterLocations,
SimpleIdentifier errorNameTarget) {
+ assert(!_options.strongMode); // strong mode already checked for these
//
// Compute the overridden executable from the InheritanceManager
//
@@ -1583,15 +2072,14 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
.lookupOverrides(_enclosingClass, executableElement.name);
if (_checkForInstanceMethodNameCollidesWithSuperclassStatic(
executableElement, errorNameTarget)) {
- return true;
+ return;
}
for (ExecutableElement overriddenElement in overriddenExecutables) {
if (_checkForAllInvalidOverrideErrorCodes(executableElement,
overriddenElement, parameters, parameterLocations, errorNameTarget)) {
- return true;
+ return;
}
}
- return false;
}
/**
@@ -1599,12 +2087,16 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [_checkForAllInvalidOverrideErrorCodes].
*/
- bool _checkForAllInvalidOverrideErrorCodesForField(
+ void _checkForAllInvalidOverrideErrorCodesForField(
FieldDeclaration declaration) {
+ if (_options.strongMode) {
+ return; // strong mode already checked for this
+ }
+
if (_enclosingClass == null || declaration.isStatic) {
- return false;
+ return;
}
- bool hasProblems = false;
+
VariableDeclarationList fields = declaration.fields;
for (VariableDeclaration field in fields.variables) {
FieldElement element = field.element as FieldElement;
@@ -1615,19 +2107,14 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
PropertyAccessorElement setter = element.setter;
SimpleIdentifier fieldName = field.name;
if (getter != null) {
- if (_checkForAllInvalidOverrideErrorCodesForExecutable(getter,
- ParameterElement.EMPTY_LIST, AstNode.EMPTY_LIST, fieldName)) {
- hasProblems = true;
- }
+ _checkForAllInvalidOverrideErrorCodesForExecutable(
+ getter, ParameterElement.EMPTY_LIST, AstNode.EMPTY_LIST, fieldName);
}
if (setter != null) {
- if (_checkForAllInvalidOverrideErrorCodesForExecutable(
- setter, setter.parameters, <AstNode>[fieldName], fieldName)) {
- hasProblems = true;
- }
+ _checkForAllInvalidOverrideErrorCodesForExecutable(
+ setter, setter.parameters, <AstNode>[fieldName], fieldName);
}
}
- return hasProblems;
}
/**
@@ -1635,27 +2122,29 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [_checkForAllInvalidOverrideErrorCodes].
*/
- bool _checkForAllInvalidOverrideErrorCodesForMethod(
+ void _checkForAllInvalidOverrideErrorCodesForMethod(
MethodDeclaration method) {
+ if (_options.strongMode) {
+ return; // strong mode already checked for this
+ }
if (_enclosingClass == null ||
method.isStatic ||
method.body is NativeFunctionBody) {
- return false;
+ return;
}
ExecutableElement executableElement = method.element;
if (executableElement == null) {
- return false;
+ return;
}
SimpleIdentifier methodName = method.name;
if (methodName.isSynthetic) {
- return false;
+ return;
}
FormalParameterList formalParameterList = method.parameters;
- NodeList<FormalParameter> parameterList =
- formalParameterList != null ? formalParameterList.parameters : null;
+ NodeList<FormalParameter> parameterList = formalParameterList?.parameters;
List<AstNode> parameters =
parameterList != null ? new List.from(parameterList) : null;
- return _checkForAllInvalidOverrideErrorCodesForExecutable(executableElement,
+ _checkForAllInvalidOverrideErrorCodesForExecutable(executableElement,
executableElement.parameters, parameters, methodName);
}
@@ -1673,27 +2162,26 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
bool problemReported = false;
for (TypeName mixinName in withClause.mixinTypes) {
DartType mixinType = mixinName.type;
- if (mixinType is! InterfaceType) {
- continue;
- }
- if (_checkForExtendsOrImplementsDisallowedClass(
- mixinName, CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS)) {
- problemReported = true;
- } else {
- ClassElement mixinElement = (mixinType as InterfaceType).element;
- if (_checkForExtendsOrImplementsDeferredClass(
- mixinName, CompileTimeErrorCode.MIXIN_DEFERRED_CLASS)) {
- problemReported = true;
- }
- if (_checkForMixinDeclaresConstructor(mixinName, mixinElement)) {
- problemReported = true;
- }
- if (!enableSuperMixins &&
- _checkForMixinInheritsNotFromObject(mixinName, mixinElement)) {
- problemReported = true;
- }
- if (_checkForMixinReferencesSuper(mixinName, mixinElement)) {
+ if (mixinType is InterfaceType) {
+ if (_checkForExtendsOrImplementsDisallowedClass(
+ mixinName, CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS)) {
problemReported = true;
+ } else {
+ ClassElement mixinElement = mixinType.element;
+ if (_checkForExtendsOrImplementsDeferredClass(
+ mixinName, CompileTimeErrorCode.MIXIN_DEFERRED_CLASS)) {
+ problemReported = true;
+ }
+ if (_checkForMixinDeclaresConstructor(mixinName, mixinElement)) {
+ problemReported = true;
+ }
+ if (!enableSuperMixins &&
+ _checkForMixinInheritsNotFromObject(mixinName, mixinElement)) {
+ problemReported = true;
+ }
+ if (_checkForMixinReferencesSuper(mixinName, mixinElement)) {
+ problemReported = true;
+ }
}
}
}
@@ -1707,32 +2195,25 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
* [StaticWarningCode.REDIRECT_TO_INVALID_FUNCTION_TYPE], and
* [StaticWarningCode.REDIRECT_TO_MISSING_CONSTRUCTOR].
*/
- bool _checkForAllRedirectConstructorErrorCodes(
+ void _checkForAllRedirectConstructorErrorCodes(
ConstructorDeclaration declaration) {
- //
// Prepare redirected constructor node
- //
ConstructorName redirectedConstructor = declaration.redirectedConstructor;
if (redirectedConstructor == null) {
- return false;
+ return;
}
- //
+
// Prepare redirected constructor type
- //
ConstructorElement redirectedElement = redirectedConstructor.staticElement;
if (redirectedElement == null) {
- //
// If the element is null, we check for the
// REDIRECT_TO_MISSING_CONSTRUCTOR case
- //
TypeName constructorTypeName = redirectedConstructor.type;
DartType redirectedType = constructorTypeName.type;
if (redirectedType != null &&
redirectedType.element != null &&
!redirectedType.isDynamic) {
- //
// Prepare the constructor name
- //
String constructorStrName = constructorTypeName.name.name;
if (redirectedConstructor.name != null) {
constructorStrName += ".${redirectedConstructor.name.name}";
@@ -1742,15 +2223,13 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
: StaticWarningCode.REDIRECT_TO_MISSING_CONSTRUCTOR);
_errorReporter.reportErrorForNode(errorCode, redirectedConstructor,
[constructorStrName, redirectedType.displayName]);
- return true;
}
- return false;
+ return;
}
FunctionType redirectedType = redirectedElement.type;
DartType redirectedReturnType = redirectedType.returnType;
- //
+
// Report specific problem when return type is incompatible
- //
FunctionType constructorType = declaration.element.type;
DartType constructorReturnType = constructorType.returnType;
if (!_typeSystem.isAssignableTo(
@@ -1759,19 +2238,14 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
StaticWarningCode.REDIRECT_TO_INVALID_RETURN_TYPE,
redirectedConstructor,
[redirectedReturnType, constructorReturnType]);
- return true;
- }
- //
- // Check parameters
- //
- if (!_typeSystem.isSubtypeOf(redirectedType, constructorType)) {
+ return;
+ } else if (!_typeSystem.isSubtypeOf(redirectedType, constructorType)) {
+ // Check parameters.
_errorReporter.reportErrorForNode(
StaticWarningCode.REDIRECT_TO_INVALID_FUNCTION_TYPE,
redirectedConstructor,
[redirectedType, constructorType]);
- return true;
}
- return false;
}
/**
@@ -1789,43 +2263,44 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
* [StaticWarningCode.RETURN_WITHOUT_VALUE], and
* [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE].
*/
- bool _checkForAllReturnStatementErrorCodes(ReturnStatement statement) {
- FunctionType functionType =
- _enclosingFunction == null ? null : _enclosingFunction.type;
+ void _checkForAllReturnStatementErrorCodes(ReturnStatement statement) {
+ FunctionType functionType = _enclosingFunction?.type;
DartType expectedReturnType = functionType == null
? DynamicTypeImpl.instance
: functionType.returnType;
Expression returnExpression = statement.expression;
// RETURN_IN_GENERATIVE_CONSTRUCTOR
- bool isGenerativeConstructor = _enclosingFunction is ConstructorElement &&
- !(_enclosingFunction as ConstructorElement).isFactory;
- if (isGenerativeConstructor) {
+ bool isGenerativeConstructor(ExecutableElement element) =>
+ element is ConstructorElement && !element.isFactory;
+ if (isGenerativeConstructor(_enclosingFunction)) {
if (returnExpression == null) {
- return false;
+ return;
}
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTRUCTOR,
returnExpression);
- return true;
+ return;
}
// RETURN_WITHOUT_VALUE
if (returnExpression == null) {
if (_inGenerator ||
_typeSystem.isAssignableTo(
_computeReturnTypeForMethod(null), expectedReturnType)) {
- return false;
+ return;
}
_hasReturnWithoutValue = true;
_errorReporter.reportErrorForNode(
StaticWarningCode.RETURN_WITHOUT_VALUE, statement);
- return true;
+ return;
} else if (_inGenerator) {
// RETURN_IN_GENERATOR
_errorReporter.reportErrorForNode(
- CompileTimeErrorCode.RETURN_IN_GENERATOR, statement);
+ CompileTimeErrorCode.RETURN_IN_GENERATOR,
+ statement,
+ [_inAsync ? "async*" : "sync*"]);
}
- // RETURN_OF_INVALID_TYPE
- return _checkForReturnOfInvalidType(returnExpression, expectedReturnType);
+
+ _checkForReturnOfInvalidType(returnExpression, expectedReturnType);
}
/**
@@ -1837,10 +2312,10 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.AMBIGUOUS_EXPORT].
*/
- bool _checkForAmbiguousExport(ExportDirective directive,
+ void _checkForAmbiguousExport(ExportDirective directive,
ExportElement exportElement, LibraryElement exportedLibrary) {
if (exportedLibrary == null) {
- return false;
+ return;
}
// check exported names
Namespace namespace =
@@ -1856,12 +2331,42 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
prevElement.library.definingCompilationUnit.displayName,
element.library.definingCompilationUnit.displayName
]);
- return true;
+ return;
} else {
_exportedElements[name] = element;
}
}
- return false;
+ }
+
+ /**
+ * Check the given node to see whether it was ambiguous because the name was
+ * imported from two or more imports.
+ */
+ void _checkForAmbiguousImport(SimpleIdentifier node) {
+ Element element = node.staticElement;
+ if (element is MultiplyDefinedElementImpl) {
+ String name = element.displayName;
+ List<Element> conflictingMembers = element.conflictingElements;
+ int count = conflictingMembers.length;
+ List<String> libraryNames = new List<String>(count);
+ for (int i = 0; i < count; i++) {
+ libraryNames[i] = _getLibraryName(conflictingMembers[i]);
+ }
+ libraryNames.sort();
+ _errorReporter.reportErrorForNode(StaticWarningCode.AMBIGUOUS_IMPORT,
+ node, [name, StringUtilities.printListOfQuotedNames(libraryNames)]);
+ } else {
+ List<Element> sdkElements =
+ node.getProperty(LibraryImportScope.conflictingSdkElements);
+ if (sdkElements != null) {
+ _errorReporter.reportErrorForNode(
+ StaticWarningCode.CONFLICTING_DART_IMPORT, node, [
+ element.displayName,
+ _getLibraryName(sdkElements[0]),
+ _getLibraryName(element)
+ ]);
+ }
+ }
}
/**
@@ -1881,22 +2386,16 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
* [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE], and
* [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE].
*/
- bool _checkForArgumentTypeNotAssignable(
+ void _checkForArgumentTypeNotAssignable(
Expression expression,
DartType expectedStaticType,
DartType actualStaticType,
ErrorCode errorCode) {
- //
// Warning case: test static type information
- //
if (actualStaticType != null && expectedStaticType != null) {
- if (!_typeSystem.isAssignableTo(actualStaticType, expectedStaticType)) {
- _errorReporter.reportTypeErrorForNode(
- errorCode, expression, [actualStaticType, expectedStaticType]);
- return true;
- }
+ _checkForAssignableExpressionAtType(
+ expression, actualStaticType, expectedStaticType, errorCode);
}
- return false;
}
/**
@@ -1908,14 +2407,13 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE].
*/
- bool _checkForArgumentTypeNotAssignableForArgument(Expression argument) {
+ void _checkForArgumentTypeNotAssignableForArgument(Expression argument) {
if (argument == null) {
- return false;
+ return;
}
ParameterElement staticParameterElement = argument.staticParameterElement;
- DartType staticParameterType =
- staticParameterElement == null ? null : staticParameterElement.type;
- return _checkForArgumentTypeNotAssignableWithExpectedTypes(argument,
+ DartType staticParameterType = staticParameterElement?.type;
+ _checkForArgumentTypeNotAssignableWithExpectedTypes(argument,
staticParameterType, StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE);
}
@@ -1934,12 +2432,11 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
* [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE], and
* [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE].
*/
- bool _checkForArgumentTypeNotAssignableWithExpectedTypes(
- Expression expression,
- DartType expectedStaticType,
- ErrorCode errorCode) =>
- _checkForArgumentTypeNotAssignable(
- expression, expectedStaticType, getStaticType(expression), errorCode);
+ void _checkForArgumentTypeNotAssignableWithExpectedTypes(
+ Expression expression, DartType expectedStaticType, ErrorCode errorCode) {
+ _checkForArgumentTypeNotAssignable(
+ expression, expectedStaticType, getStaticType(expression), errorCode);
+ }
/**
* Verify that the arguments in the given [argumentList] can be assigned to
@@ -1950,17 +2447,14 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE].
*/
- bool _checkForArgumentTypesNotAssignableInList(ArgumentList argumentList) {
+ void _checkForArgumentTypesNotAssignableInList(ArgumentList argumentList) {
if (argumentList == null) {
- return false;
+ return;
}
- bool problemReported = false;
+
for (Expression argument in argumentList.arguments) {
- if (_checkForArgumentTypeNotAssignableForArgument(argument)) {
- problemReported = true;
- }
+ _checkForArgumentTypeNotAssignableForArgument(argument);
}
- return problemReported;
}
/**
@@ -1970,19 +2464,41 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
* [errorCode] is the error code to be reported. The [arguments] are the
* arguments to pass in when creating the error.
*/
- bool _checkForAssignability(Expression expression, InterfaceType type,
+ void _checkForAssignability(Expression expression, InterfaceType type,
ErrorCode errorCode, List<Object> arguments) {
if (expression == null) {
- return false;
+ return;
}
DartType expressionType = expression.staticType;
if (expressionType == null) {
- return false;
+ return;
}
- if (_typeSystem.isAssignableTo(expressionType, type)) {
- return false;
+ if (_expressionIsAssignableAtType(expression, expressionType, type)) {
+ return;
}
_errorReporter.reportErrorForNode(errorCode, expression, arguments);
+ }
+
+ bool _checkForAssignableExpression(
+ Expression expression, DartType expectedStaticType, ErrorCode errorCode) {
+ DartType actualStaticType = getStaticType(expression);
+ return actualStaticType != null &&
+ _checkForAssignableExpressionAtType(
+ expression, actualStaticType, expectedStaticType, errorCode);
+ }
+
+ bool _checkForAssignableExpressionAtType(
+ Expression expression,
+ DartType actualStaticType,
+ DartType expectedStaticType,
+ ErrorCode errorCode) {
+ // TODO(leafp): Move the Downcast functionality here.
+ if (!_expressionIsAssignableAtType(
+ expression, actualStaticType, expectedStaticType)) {
+ _errorReporter.reportTypeErrorForNode(
+ errorCode, expression, [actualStaticType, expectedStaticType]);
+ return false;
+ }
return true;
}
@@ -1993,7 +2509,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
* [StaticWarningCode.ASSIGNMENT_TO_FINAL], and
* [StaticWarningCode.ASSIGNMENT_TO_METHOD].
*/
- bool _checkForAssignmentToFinal(Expression expression) {
+ void _checkForAssignmentToFinal(Expression expression) {
// prepare element
Element element = null;
AstNode highlightedNode = expression;
@@ -2003,22 +2519,20 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
highlightedNode = expression.identifier;
}
} else if (expression is PropertyAccess) {
- PropertyAccess propertyAccess = expression;
- element = propertyAccess.propertyName.staticElement;
- highlightedNode = propertyAccess.propertyName;
+ element = expression.propertyName.staticElement;
+ highlightedNode = expression.propertyName;
}
// check if element is assignable
- if (element is PropertyAccessorElement) {
- PropertyAccessorElement accessor = element as PropertyAccessorElement;
- element = accessor.variable;
+ Element toVariable(Element element) {
+ return element is PropertyAccessorElement ? element.variable : element;
}
+
+ element = toVariable(element);
if (element is VariableElement) {
if (element.isConst) {
_errorReporter.reportErrorForNode(
StaticWarningCode.ASSIGNMENT_TO_CONST, expression);
- return true;
- }
- if (element.isFinal) {
+ } else if (element.isFinal) {
if (element is FieldElementImpl &&
element.setter == null &&
element.isSynthetic) {
@@ -2026,32 +2540,23 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
StaticWarningCode.ASSIGNMENT_TO_FINAL_NO_SETTER,
highlightedNode,
[element.name, element.enclosingElement.displayName]);
- return true;
+ return;
}
_errorReporter.reportErrorForNode(StaticWarningCode.ASSIGNMENT_TO_FINAL,
highlightedNode, [element.name]);
- return true;
}
- return false;
- }
- if (element is FunctionElement) {
+ } else if (element is FunctionElement) {
_errorReporter.reportErrorForNode(
StaticWarningCode.ASSIGNMENT_TO_FUNCTION, expression);
- return true;
- }
- if (element is MethodElement) {
+ } else if (element is MethodElement) {
_errorReporter.reportErrorForNode(
StaticWarningCode.ASSIGNMENT_TO_METHOD, expression);
- return true;
- }
- if (element is ClassElement ||
+ } else if (element is ClassElement ||
element is FunctionTypeAliasElement ||
element is TypeParameterElement) {
_errorReporter.reportErrorForNode(
StaticWarningCode.ASSIGNMENT_TO_TYPE, expression);
- return true;
}
- return false;
}
/**
@@ -2062,15 +2567,13 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
* [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_PARAMETER_NAME], and
* [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME].
*/
- bool _checkForBuiltInIdentifierAsName(
+ void _checkForBuiltInIdentifierAsName(
SimpleIdentifier identifier, ErrorCode errorCode) {
- sc.Token token = identifier.token;
- if (token.type == sc.TokenType.KEYWORD) {
- _errorReporter.reportErrorForNode(
- errorCode, identifier, [identifier.name]);
- return true;
+ Token token = identifier.token;
+ if (token.type == TokenType.KEYWORD) {
+ _errorReporter
+ .reportErrorForNode(errorCode, identifier, [identifier.name]);
}
- return false;
}
/**
@@ -2079,17 +2582,16 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* see [StaticWarningCode.CASE_BLOCK_NOT_TERMINATED].
*/
- bool _checkForCaseBlockNotTerminated(SwitchCase switchCase) {
+ void _checkForCaseBlockNotTerminated(SwitchCase switchCase) {
NodeList<Statement> statements = switchCase.statements;
if (statements.isEmpty) {
// fall-through without statements at all
AstNode parent = switchCase.parent;
if (parent is SwitchStatement) {
- SwitchStatement switchStatement = parent;
- NodeList<SwitchMember> members = switchStatement.members;
+ NodeList<SwitchMember> members = parent.members;
int index = members.indexOf(switchCase);
if (index != -1 && index < members.length - 1) {
- return false;
+ return;
}
}
// no other switch member after this one
@@ -2099,20 +2601,19 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
if (statement is BreakStatement ||
statement is ContinueStatement ||
statement is ReturnStatement) {
- return false;
+ return;
}
// terminated with 'throw' expression
if (statement is ExpressionStatement) {
Expression expression = statement.expression;
if (expression is ThrowExpression) {
- return false;
+ return;
}
}
}
- // report error
+
_errorReporter.reportErrorForToken(
StaticWarningCode.CASE_BLOCK_NOT_TERMINATED, switchCase.keyword);
- return true;
}
/**
@@ -2121,17 +2622,15 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [StaticWarningCode.CASE_BLOCK_NOT_TERMINATED].
*/
- bool _checkForCaseBlocksNotTerminated(SwitchStatement statement) {
- bool foundError = false;
+ void _checkForCaseBlocksNotTerminated(SwitchStatement statement) {
NodeList<SwitchMember> members = statement.members;
int lastMember = members.length - 1;
for (int i = 0; i < lastMember; i++) {
SwitchMember member = members[i];
- if (member is SwitchCase && _checkForCaseBlockNotTerminated(member)) {
- foundError = true;
+ if (member is SwitchCase) {
+ _checkForCaseBlockNotTerminated(member);
}
}
- return foundError;
}
/**
@@ -2140,7 +2639,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [StaticWarningCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER].
*/
- bool _checkForConcreteClassWithAbstractMember(MethodDeclaration method) {
+ void _checkForConcreteClassWithAbstractMember(MethodDeclaration method) {
if (method.isAbstract &&
_enclosingClass != null &&
!_enclosingClass.isAbstract) {
@@ -2157,15 +2656,13 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
overriddenMember = _enclosingClass.lookUpInheritedConcreteMethod(
memberName, _currentLibrary);
}
- if (overriddenMember == null) {
+ if (overriddenMember == null && !_enclosingClass.hasNoSuchMethod) {
_errorReporter.reportErrorForNode(
StaticWarningCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER,
nameNode,
[memberName, _enclosingClass.displayName]);
- return true;
}
}
- return false;
}
/**
@@ -2178,7 +2675,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
* [CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_NAME_AND_FIELD], and
* [CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_NAME_AND_METHOD].
*/
- bool _checkForConflictingConstructorNameAndMember(
+ void _checkForConflictingConstructorNameAndMember(
ConstructorDeclaration constructor,
ConstructorElement constructorElement) {
SimpleIdentifier constructorName = constructor.name;
@@ -2200,33 +2697,27 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
constructor,
[name]);
}
- return true;
+ return;
}
}
// conflict with class member
if (constructorName != null &&
constructorElement != null &&
!constructorName.isSynthetic) {
- // fields
- FieldElement field = classElement.getField(name);
- if (field != null) {
+ if (classElement.getField(name) != null) {
+ // fields
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_NAME_AND_FIELD,
constructor,
[name]);
- return true;
- }
- // methods
- MethodElement method = classElement.getMethod(name);
- if (method != null) {
+ } else if (classElement.getMethod(name) != null) {
+ // methods
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_NAME_AND_METHOD,
constructor,
[name]);
- return true;
}
}
- return false;
}
/**
@@ -2236,11 +2727,11 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
* See [CompileTimeErrorCode.CONFLICTING_GETTER_AND_METHOD], and
* [CompileTimeErrorCode.CONFLICTING_METHOD_AND_GETTER].
*/
- bool _checkForConflictingGetterAndMethod() {
+ void _checkForConflictingGetterAndMethod() {
if (_enclosingClass == null) {
- return false;
+ return;
}
- bool hasProblem = false;
+
// method declared in the enclosing class vs. inherited getter
for (MethodElement method in _enclosingClass.methods) {
String name = method.name;
@@ -2250,8 +2741,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
if (inherited is! PropertyAccessorElement) {
continue;
}
- // report problem
- hasProblem = true;
+
_errorReporter.reportErrorForElement(
CompileTimeErrorCode.CONFLICTING_GETTER_AND_METHOD, method, [
_enclosingClass.displayName,
@@ -2271,8 +2761,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
if (inherited is! MethodElement) {
continue;
}
- // report problem
- hasProblem = true;
+
_errorReporter.reportErrorForElement(
CompileTimeErrorCode.CONFLICTING_METHOD_AND_GETTER, accessor, [
_enclosingClass.displayName,
@@ -2280,8 +2769,6 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
name
]);
}
- // done
- return hasProblem;
}
/**
@@ -2292,13 +2779,12 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
* See [StaticWarningCode.CONFLICTING_INSTANCE_GETTER_AND_SUPERCLASS_MEMBER], and
* [StaticWarningCode.CONFLICTING_INSTANCE_SETTER_AND_SUPERCLASS_MEMBER].
*/
- bool _checkForConflictingInstanceGetterAndSuperclassMember() {
+ void _checkForConflictingInstanceGetterAndSuperclassMember() {
if (_enclosingClass == null) {
- return false;
+ return;
}
InterfaceType enclosingType = _enclosingClass.type;
// check every accessor
- bool hasProblem = false;
for (PropertyAccessorElement accessor in _enclosingClass.accessors) {
// we analyze instance accessors here
if (accessor.isStatic) {
@@ -2335,8 +2821,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
ClassElement superElementClass =
superElement.enclosingElement as ClassElement;
InterfaceType superElementType = superElementClass.type;
- // report problem
- hasProblem = true;
+
if (getter) {
_errorReporter.reportErrorForElement(
StaticWarningCode.CONFLICTING_INSTANCE_GETTER_AND_SUPERCLASS_MEMBER,
@@ -2349,8 +2834,6 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
[superElementType.displayName]);
}
}
- // done
- return hasProblem;
}
/**
@@ -2362,34 +2845,32 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [StaticWarningCode.CONFLICTING_INSTANCE_METHOD_SETTER].
*/
- bool _checkForConflictingInstanceMethodSetter(ClassDeclaration declaration) {
+ void _checkForConflictingInstanceMethodSetter(ClassDeclaration declaration) {
// Reference all of the class members in this class.
NodeList<ClassMember> classMembers = declaration.members;
if (classMembers.isEmpty) {
- return false;
+ return;
}
// Create a HashMap to track conflicting members, and then loop through
// members in the class to construct the HashMap, at the same time,
// look for violations. Don't add members if they are part of a conflict,
// this prevents multiple warnings for one issue.
- bool foundError = false;
HashMap<String, ClassMember> memberHashMap =
new HashMap<String, ClassMember>();
- for (ClassMember classMember in classMembers) {
- if (classMember is MethodDeclaration) {
- MethodDeclaration method = classMember;
- if (method.isStatic) {
+ for (ClassMember member in classMembers) {
+ if (member is MethodDeclaration) {
+ if (member.isStatic) {
continue;
}
// prepare name
- SimpleIdentifier name = method.name;
+ SimpleIdentifier name = member.name;
if (name == null) {
continue;
}
bool addThisMemberToTheMap = true;
- bool isGetter = method.isGetter;
- bool isSetter = method.isSetter;
- bool isOperator = method.isOperator;
+ bool isGetter = member.isGetter;
+ bool isSetter = member.isSetter;
+ bool isOperator = member.isOperator;
bool isMethod = !isGetter && !isSetter && !isOperator;
// Do lookups in the enclosing class (and the inherited member) if the
// member is a method or a setter for
@@ -2410,14 +2891,12 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
}
}
if (enclosingElementOfSetter != null) {
- // report problem
_errorReporter.reportErrorForNode(
StaticWarningCode.CONFLICTING_INSTANCE_METHOD_SETTER, name, [
_enclosingClass.displayName,
name.name,
enclosingElementOfSetter.displayName
]);
- foundError = true;
addThisMemberToTheMap = false;
}
} else if (isSetter) {
@@ -2426,26 +2905,23 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
if (conflictingMethod != null &&
conflictingMethod is MethodDeclaration &&
!conflictingMethod.isGetter) {
- // report problem
_errorReporter.reportErrorForNode(
StaticWarningCode.CONFLICTING_INSTANCE_METHOD_SETTER2,
name,
[_enclosingClass.displayName, name.name]);
- foundError = true;
addThisMemberToTheMap = false;
}
}
// Finally, add this member into the HashMap.
if (addThisMemberToTheMap) {
- if (method.isSetter) {
- memberHashMap["${name.name}="] = method;
+ if (member.isSetter) {
+ memberHashMap["${name.name}="] = member;
} else {
- memberHashMap[name.name] = method;
+ memberHashMap[name.name] = member;
}
}
}
}
- return foundError;
}
/**
@@ -2454,41 +2930,40 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [StaticWarningCode.CONFLICTING_STATIC_GETTER_AND_INSTANCE_SETTER].
*/
- bool _checkForConflictingStaticGetterAndInstanceSetter(
+ void _checkForConflictingStaticGetterAndInstanceSetter(
MethodDeclaration method) {
if (!method.isStatic) {
- return false;
+ return;
}
// prepare name
SimpleIdentifier nameNode = method.name;
if (nameNode == null) {
- return false;
+ return;
}
String name = nameNode.name;
// prepare enclosing type
if (_enclosingClass == null) {
- return false;
+ return;
}
InterfaceType enclosingType = _enclosingClass.type;
// try to find setter
ExecutableElement setter =
enclosingType.lookUpSetter(name, _currentLibrary);
if (setter == null) {
- return false;
+ return;
}
// OK, also static
if (setter.isStatic) {
- return false;
+ return;
}
// prepare "setter" type to report its name
ClassElement setterClass = setter.enclosingElement as ClassElement;
InterfaceType setterType = setterClass.type;
- // report problem
+
_errorReporter.reportErrorForNode(
StaticWarningCode.CONFLICTING_STATIC_GETTER_AND_INSTANCE_SETTER,
nameNode,
[setterType.displayName]);
- return true;
}
/**
@@ -2497,20 +2972,20 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [StaticWarningCode.CONFLICTING_STATIC_SETTER_AND_INSTANCE_MEMBER].
*/
- bool _checkForConflictingStaticSetterAndInstanceMember(
+ void _checkForConflictingStaticSetterAndInstanceMember(
MethodDeclaration method) {
if (!method.isStatic) {
- return false;
+ return;
}
// prepare name
SimpleIdentifier nameNode = method.name;
if (nameNode == null) {
- return false;
+ return;
}
String name = nameNode.name;
// prepare enclosing type
if (_enclosingClass == null) {
- return false;
+ return;
}
InterfaceType enclosingType = _enclosingClass.type;
// try to find member
@@ -2523,21 +2998,20 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
member = enclosingType.lookUpSetter(name, _currentLibrary);
}
if (member == null) {
- return false;
+ return;
}
// OK, also static
if (member.isStatic) {
- return false;
+ return;
}
// prepare "member" type to report its name
ClassElement memberClass = member.enclosingElement as ClassElement;
InterfaceType memberType = memberClass.type;
- // report problem
+
_errorReporter.reportErrorForNode(
StaticWarningCode.CONFLICTING_STATIC_SETTER_AND_INSTANCE_MEMBER,
nameNode,
[memberType.displayName]);
- return true;
}
/**
@@ -2547,9 +3021,8 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
* See [CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_CLASS], and
* [CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER].
*/
- bool _checkForConflictingTypeVariableErrorCodes(
+ void _checkForConflictingTypeVariableErrorCodes(
ClassDeclaration declaration) {
- bool problemReported = false;
for (TypeParameterElement typeParameter in _enclosingClass.typeParameters) {
String name = typeParameter.name;
// name is same as the name of the enclosing class
@@ -2558,7 +3031,6 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_CLASS,
typeParameter,
[name]);
- problemReported = true;
}
// check members
if (_enclosingClass.getMethod(name) != null ||
@@ -2568,10 +3040,8 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER,
typeParameter,
[name]);
- problemReported = true;
}
}
- return problemReported;
}
/**
@@ -2580,59 +3050,55 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER].
*/
- bool _checkForConstConstructorWithNonConstSuper(
+ void _checkForConstConstructorWithNonConstSuper(
ConstructorDeclaration constructor) {
if (!_isEnclosingConstructorConst) {
- return false;
+ return;
}
// OK, const factory, checked elsewhere
if (constructor.factoryKeyword != null) {
- return false;
+ return;
}
// check for mixins
if (_enclosingClass.mixins.length != 0) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN,
constructor.returnType);
- return true;
+ return;
}
// try to find and check super constructor invocation
for (ConstructorInitializer initializer in constructor.initializers) {
if (initializer is SuperConstructorInvocation) {
- SuperConstructorInvocation superInvocation = initializer;
- ConstructorElement element = superInvocation.staticElement;
+ ConstructorElement element = initializer.staticElement;
if (element == null || element.isConst) {
- return false;
+ return;
}
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER,
- superInvocation,
+ initializer,
[element.enclosingElement.displayName]);
- return true;
+ return;
}
}
// no explicit super constructor invocation, check default constructor
InterfaceType supertype = _enclosingClass.supertype;
if (supertype == null) {
- return false;
+ return;
}
if (supertype.isObject) {
- return false;
+ return;
}
ConstructorElement unnamedConstructor =
supertype.element.unnamedConstructor;
- if (unnamedConstructor == null) {
- return false;
- }
- if (unnamedConstructor.isConst) {
- return false;
+ if (unnamedConstructor == null || unnamedConstructor.isConst) {
+ return;
}
+
// default constructor is not 'const', report problem
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER,
constructor.returnType,
[supertype.displayName]);
- return true;
}
/**
@@ -2642,22 +3108,21 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD].
*/
- bool _checkForConstConstructorWithNonFinalField(
+ void _checkForConstConstructorWithNonFinalField(
ConstructorDeclaration constructor,
ConstructorElement constructorElement) {
if (!_isEnclosingConstructorConst) {
- return false;
+ return;
}
// check if there is non-final field
ClassElement classElement = constructorElement.enclosingElement;
if (!classElement.hasNonFinalField) {
- return false;
+ return;
}
- // report problem
+
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD,
constructor);
- return true;
}
/**
@@ -2668,16 +3133,14 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.CONST_DEFERRED_CLASS].
*/
- bool _checkForConstDeferredClass(InstanceCreationExpression expression,
+ void _checkForConstDeferredClass(InstanceCreationExpression expression,
ConstructorName constructorName, TypeName typeName) {
if (typeName.isDeferred) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.CONST_DEFERRED_CLASS,
constructorName,
[typeName.name.name]);
- return true;
}
- return false;
}
/**
@@ -2686,13 +3149,11 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.CONST_CONSTRUCTOR_THROWS_EXCEPTION].
*/
- bool _checkForConstEvalThrowsException(ThrowExpression expression) {
+ void _checkForConstEvalThrowsException(ThrowExpression expression) {
if (_isEnclosingConstructorConst) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.CONST_CONSTRUCTOR_THROWS_EXCEPTION, expression);
- return true;
}
- return false;
}
/**
@@ -2700,13 +3161,11 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.CONST_FORMAL_PARAMETER].
*/
- bool _checkForConstFormalParameter(NormalFormalParameter parameter) {
+ void _checkForConstFormalParameter(NormalFormalParameter parameter) {
if (parameter.isConst) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.CONST_FORMAL_PARAMETER, parameter);
- return true;
}
- return false;
}
/**
@@ -2719,25 +3178,22 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
* See [StaticWarningCode.CONST_WITH_ABSTRACT_CLASS], and
* [StaticWarningCode.NEW_WITH_ABSTRACT_CLASS].
*/
- bool _checkForConstOrNewWithAbstractClass(
+ void _checkForConstOrNewWithAbstractClass(
InstanceCreationExpression expression,
TypeName typeName,
InterfaceType type) {
if (type.element.isAbstract) {
ConstructorElement element = expression.staticElement;
if (element != null && !element.isFactory) {
- if ((expression.keyword as sc.KeywordToken).keyword ==
- sc.Keyword.CONST) {
+ if (expression.keyword.keyword == Keyword.CONST) {
_errorReporter.reportErrorForNode(
StaticWarningCode.CONST_WITH_ABSTRACT_CLASS, typeName);
} else {
_errorReporter.reportErrorForNode(
StaticWarningCode.NEW_WITH_ABSTRACT_CLASS, typeName);
}
- return true;
}
}
- return false;
}
/**
@@ -2749,14 +3205,12 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.INSTANTIATE_ENUM].
*/
- bool _checkForConstOrNewWithEnum(InstanceCreationExpression expression,
+ void _checkForConstOrNewWithEnum(InstanceCreationExpression expression,
TypeName typeName, InterfaceType type) {
if (type.element.isEnum) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.INSTANTIATE_ENUM, typeName);
- return true;
}
- return false;
}
/**
@@ -2768,14 +3222,12 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.CONST_WITH_NON_CONST].
*/
- bool _checkForConstWithNonConst(InstanceCreationExpression expression) {
+ void _checkForConstWithNonConst(InstanceCreationExpression expression) {
ConstructorElement constructorElement = expression.staticElement;
if (constructorElement != null && !constructorElement.isConst) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.CONST_WITH_NON_CONST, expression);
- return true;
}
- return false;
}
/**
@@ -2783,14 +3235,14 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS].
*/
- bool _checkForConstWithTypeParameters(TypeName typeName) {
+ void _checkForConstWithTypeParameters(TypeName typeName) {
// something wrong with AST
if (typeName == null) {
- return false;
+ return;
}
Identifier name = typeName.name;
if (name == null) {
- return false;
+ return;
}
// should not be a type parameter
if (name.staticElement is TypeParameterElement) {
@@ -2800,16 +3252,10 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
// check type arguments
TypeArgumentList typeArguments = typeName.typeArguments;
if (typeArguments != null) {
- bool hasError = false;
for (TypeName argument in typeArguments.arguments) {
- if (_checkForConstWithTypeParameters(argument)) {
- hasError = true;
- }
+ _checkForConstWithTypeParameters(argument);
}
- return hasError;
}
- // OK
- return false;
}
/**
@@ -2824,20 +3270,20 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
* See [CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR], and
* [CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT].
*/
- bool _checkForConstWithUndefinedConstructor(
+ void _checkForConstWithUndefinedConstructor(
InstanceCreationExpression expression,
ConstructorName constructorName,
TypeName typeName) {
// OK if resolved
if (expression.staticElement != null) {
- return false;
+ return;
}
DartType type = typeName.type;
if (type is InterfaceType) {
ClassElement element = type.element;
if (element != null && element.isEnum) {
// We have already reported the error.
- return false;
+ return;
}
}
Identifier className = typeName.name;
@@ -2854,7 +3300,6 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
constructorName,
[className]);
}
- return true;
}
/**
@@ -2863,21 +3308,17 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS].
*/
- bool _checkForDefaultValueInFunctionTypeAlias(FunctionTypeAlias alias) {
- bool result = false;
+ void _checkForDefaultValueInFunctionTypeAlias(FunctionTypeAlias alias) {
FormalParameterList formalParameterList = alias.parameters;
NodeList<FormalParameter> parameters = formalParameterList.parameters;
- for (FormalParameter formalParameter in parameters) {
- if (formalParameter is DefaultFormalParameter) {
- DefaultFormalParameter defaultFormalParameter = formalParameter;
- if (defaultFormalParameter.defaultValue != null) {
+ for (FormalParameter parameter in parameters) {
+ if (parameter is DefaultFormalParameter) {
+ if (parameter.defaultValue != null) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS, alias);
- result = true;
}
}
}
- return result;
}
/**
@@ -2886,21 +3327,20 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER].
*/
- bool _checkForDefaultValueInFunctionTypedParameter(
+ void _checkForDefaultValueInFunctionTypedParameter(
DefaultFormalParameter parameter) {
// OK, not in a function typed parameter.
if (!_isInFunctionTypedFormalParameter) {
- return false;
+ return;
}
// OK, no default value.
if (parameter.defaultValue == null) {
- return false;
+ return;
}
- // Report problem.
+
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER,
parameter);
- return true;
}
/**
@@ -2909,8 +3349,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.SHARED_DEFERRED_PREFIX].
*/
- bool _checkForDeferredPrefixCollisions(CompilationUnit unit) {
- bool foundError = false;
+ void _checkForDeferredPrefixCollisions(CompilationUnit unit) {
NodeList<Directive> directives = unit.directives;
int count = directives.length;
if (count > 0) {
@@ -2919,30 +3358,24 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
for (int i = 0; i < count; i++) {
Directive directive = directives[i];
if (directive is ImportDirective) {
- ImportDirective importDirective = directive;
- SimpleIdentifier prefix = importDirective.prefix;
+ SimpleIdentifier prefix = directive.prefix;
if (prefix != null) {
Element element = prefix.staticElement;
if (element is PrefixElement) {
- PrefixElement prefixElement = element;
- List<ImportDirective> elements =
- prefixToDirectivesMap[prefixElement];
+ List<ImportDirective> elements = prefixToDirectivesMap[element];
if (elements == null) {
elements = new List<ImportDirective>();
- prefixToDirectivesMap[prefixElement] = elements;
+ prefixToDirectivesMap[element] = elements;
}
- elements.add(importDirective);
+ elements.add(directive);
}
}
}
}
for (List<ImportDirective> imports in prefixToDirectivesMap.values) {
- if (_hasDeferredPrefixCollision(imports)) {
- foundError = true;
- }
+ _checkDeferredPrefixCollision(imports);
}
}
- return foundError;
}
/**
@@ -2951,22 +3384,21 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.DUPLICATE_DEFINITION_INHERITANCE].
*/
- bool _checkForDuplicateDefinitionInheritance() {
+ void _checkForDuplicateDefinitionInheritance() {
if (_enclosingClass == null) {
- return false;
+ return;
}
- bool hasProblem = false;
+
for (ExecutableElement member in _enclosingClass.methods) {
- if (member.isStatic && _checkForDuplicateDefinitionOfMember(member)) {
- hasProblem = true;
+ if (member.isStatic) {
+ _checkForDuplicateDefinitionOfMember(member);
}
}
for (ExecutableElement member in _enclosingClass.accessors) {
- if (member.isStatic && _checkForDuplicateDefinitionOfMember(member)) {
- hasProblem = true;
+ if (member.isStatic) {
+ _checkForDuplicateDefinitionOfMember(member);
}
}
- return hasProblem;
}
/**
@@ -2975,21 +3407,21 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.DUPLICATE_DEFINITION_INHERITANCE].
*/
- bool _checkForDuplicateDefinitionOfMember(ExecutableElement staticMember) {
+ void _checkForDuplicateDefinitionOfMember(ExecutableElement staticMember) {
// prepare name
String name = staticMember.name;
if (name == null) {
- return false;
+ return;
}
// try to find member
ExecutableElement inheritedMember =
_inheritanceManager.lookupInheritance(_enclosingClass, name);
if (inheritedMember == null) {
- return false;
+ return;
}
// OK, also static
if (inheritedMember.isStatic) {
- return false;
+ return;
}
// determine the display name, use the extended display name if the
// enclosing class of the inherited member is in a different source
@@ -3000,12 +3432,11 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
} else {
displayName = enclosingElement.getExtendedDisplayName(null);
}
- // report problem
+
_errorReporter.reportErrorForElement(
CompileTimeErrorCode.DUPLICATE_DEFINITION_INHERITANCE,
staticMember,
[name, displayName]);
- return true;
}
/**
@@ -3014,19 +3445,16 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [StaticTypeWarningCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS].
*/
- bool _checkForExpectedOneListTypeArgument(
+ void _checkForExpectedOneListTypeArgument(
ListLiteral literal, TypeArgumentList typeArguments) {
// check number of type arguments
int num = typeArguments.arguments.length;
- if (num == 1) {
- return false;
+ if (num != 1) {
+ _errorReporter.reportErrorForNode(
+ StaticTypeWarningCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS,
+ typeArguments,
+ [num]);
}
- // report problem
- _errorReporter.reportErrorForNode(
- StaticTypeWarningCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS,
- typeArguments,
- [num]);
- return true;
}
/**
@@ -3038,10 +3466,10 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.EXPORT_DUPLICATED_LIBRARY_NAME].
*/
- bool _checkForExportDuplicateLibraryName(ExportDirective directive,
+ void _checkForExportDuplicateLibraryName(ExportDirective directive,
ExportElement exportElement, LibraryElement exportedLibrary) {
if (exportedLibrary == null) {
- return false;
+ return;
}
String name = exportedLibrary.name;
// check if there is other exported library with the same name
@@ -3056,13 +3484,11 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
name
]);
}
- return true;
+ return;
}
} else {
_nameToExportElement[name] = exportedLibrary;
}
- // OK
- return false;
}
/**
@@ -3073,27 +3499,26 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY].
*/
- bool _checkForExportInternalLibrary(
+ void _checkForExportInternalLibrary(
ExportDirective directive, ExportElement exportElement) {
if (_isInSystemLibrary) {
- return false;
+ return;
}
// should be private
DartSdk sdk = _currentLibrary.context.sourceFactory.dartSdk;
String uri = exportElement.uri;
SdkLibrary sdkLibrary = sdk.getSdkLibrary(uri);
if (sdkLibrary == null) {
- return false;
+ return;
}
if (!sdkLibrary.isInternal) {
- return false;
+ return;
}
- // report problem
+
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY,
directive,
[directive.uri]);
- return true;
}
/**
@@ -3101,11 +3526,11 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.EXTENDS_DEFERRED_CLASS].
*/
- bool _checkForExtendsDeferredClass(ExtendsClause clause) {
+ void _checkForExtendsDeferredClass(ExtendsClause clause) {
if (clause == null) {
- return false;
+ return;
}
- return _checkForExtendsOrImplementsDeferredClass(
+ _checkForExtendsOrImplementsDeferredClass(
clause.superclass, CompileTimeErrorCode.EXTENDS_DEFERRED_CLASS);
}
@@ -3114,11 +3539,11 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS].
*/
- bool _checkForExtendsDeferredClassInTypeAlias(ClassTypeAlias alias) {
+ void _checkForExtendsDeferredClassInTypeAlias(ClassTypeAlias alias) {
if (alias == null) {
- return false;
+ return;
}
- return _checkForExtendsOrImplementsDeferredClass(
+ _checkForExtendsOrImplementsDeferredClass(
alias.superclass, CompileTimeErrorCode.EXTENDS_DEFERRED_CLASS);
}
@@ -3168,8 +3593,8 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
return false;
}
if (typeName.isDeferred) {
- _errorReporter.reportErrorForNode(
- errorCode, typeName, [typeName.name.name]);
+ _errorReporter
+ .reportErrorForNode(errorCode, typeName, [typeName.name.name]);
return true;
}
return false;
@@ -3231,40 +3656,36 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
/**
* Verify that the given constructor field [initializer] has compatible field
- * and initializer expression types. The [staticElement] is the static element
+ * and initializer expression types. The [fieldElement] is the static element
* from the name in the [ConstructorFieldInitializer].
*
* See [CompileTimeErrorCode.CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE], and
* [StaticWarningCode.FIELD_INITIALIZER_NOT_ASSIGNABLE].
*/
- bool _checkForFieldInitializerNotAssignable(
- ConstructorFieldInitializer initializer, Element staticElement) {
- // prepare field element
- if (staticElement is! FieldElement) {
- return false;
- }
- FieldElement fieldElement = staticElement as FieldElement;
+ void _checkForFieldInitializerNotAssignable(
+ ConstructorFieldInitializer initializer, FieldElement fieldElement) {
// prepare field type
DartType fieldType = fieldElement.type;
// prepare expression type
Expression expression = initializer.expression;
if (expression == null) {
- return false;
+ return;
}
// test the static type of the expression
DartType staticType = getStaticType(expression);
if (staticType == null) {
- return false;
+ return;
}
- if (_typeSystem.isAssignableTo(staticType, fieldType)) {
- return false;
+ if (_expressionIsAssignableAtType(expression, staticType, fieldType)) {
+ return;
}
// report problem
if (_isEnclosingConstructorConst) {
// TODO(paulberry): this error should be based on the actual type of the
// constant, not the static type. See dartbug.com/21119.
_errorReporter.reportTypeErrorForNode(
- CheckedModeCompileTimeErrorCode.CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE,
+ CheckedModeCompileTimeErrorCode
+ .CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE,
expression,
[staticType, fieldType]);
}
@@ -3272,7 +3693,6 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
StaticWarningCode.FIELD_INITIALIZER_NOT_ASSIGNABLE,
expression,
[staticType, fieldType]);
- return true;
// TODO(brianwilkerson) Define a hint corresponding to these errors and
// report it if appropriate.
// // test the propagated type of the expression
@@ -3303,34 +3723,37 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR].
*/
- bool _checkForFieldInitializingFormalRedirectingConstructor(
+ void _checkForFieldInitializingFormalRedirectingConstructor(
FieldFormalParameter parameter) {
- ConstructorDeclaration constructor =
- parameter.getAncestor((node) => node is ConstructorDeclaration);
- if (constructor == null) {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR,
- parameter);
- return true;
- }
- // constructor cannot be a factory
- if (constructor.factoryKeyword != null) {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.FIELD_INITIALIZER_FACTORY_CONSTRUCTOR,
- parameter);
- return true;
- }
- // constructor cannot have a redirection
- for (ConstructorInitializer initializer in constructor.initializers) {
- if (initializer is RedirectingConstructorInvocation) {
+ // prepare the node that should be a ConstructorDeclaration
+ AstNode formalParameterList = parameter.parent;
+ if (formalParameterList is! FormalParameterList) {
+ formalParameterList = formalParameterList?.parent;
+ }
+ AstNode constructor = formalParameterList?.parent;
+ // now check whether the node is actually a ConstructorDeclaration
+ if (constructor is ConstructorDeclaration) {
+ // constructor cannot be a factory
+ if (constructor.factoryKeyword != null) {
_errorReporter.reportErrorForNode(
- CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR,
+ CompileTimeErrorCode.FIELD_INITIALIZER_FACTORY_CONSTRUCTOR,
parameter);
- return true;
+ return;
+ }
+ // constructor cannot have a redirection
+ for (ConstructorInitializer initializer in constructor.initializers) {
+ if (initializer is RedirectingConstructorInvocation) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR,
+ parameter);
+ return;
+ }
}
+ } else {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR,
+ parameter);
}
- // OK
- return false;
}
/**
@@ -3340,31 +3763,27 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
* See [CompileTimeErrorCode.CONST_NOT_INITIALIZED], and
* [StaticWarningCode.FINAL_NOT_INITIALIZED].
*/
- bool _checkForFinalNotInitialized(VariableDeclarationList list) {
- if (_isInNativeClass) {
- return false;
+ void _checkForFinalNotInitialized(VariableDeclarationList list) {
+ if (_isInNativeClass || list.isSynthetic) {
+ return;
}
- bool foundError = false;
- if (!list.isSynthetic) {
- NodeList<VariableDeclaration> variables = list.variables;
- for (VariableDeclaration variable in variables) {
- if (variable.initializer == null) {
- if (list.isConst) {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.CONST_NOT_INITIALIZED,
- variable.name,
- [variable.name.name]);
- } else if (list.isFinal) {
- _errorReporter.reportErrorForNode(
- StaticWarningCode.FINAL_NOT_INITIALIZED,
- variable.name,
- [variable.name.name]);
- }
- foundError = true;
+
+ NodeList<VariableDeclaration> variables = list.variables;
+ for (VariableDeclaration variable in variables) {
+ if (variable.initializer == null) {
+ if (list.isConst) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.CONST_NOT_INITIALIZED,
+ variable.name,
+ [variable.name.name]);
+ } else if (list.isFinal) {
+ _errorReporter.reportErrorForNode(
+ StaticWarningCode.FINAL_NOT_INITIALIZED,
+ variable.name,
+ [variable.name.name]);
}
}
}
- return foundError;
}
/**
@@ -3376,21 +3795,18 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
* See [CompileTimeErrorCode.CONST_NOT_INITIALIZED], and
* [StaticWarningCode.FINAL_NOT_INITIALIZED].
*/
- bool _checkForFinalNotInitializedInClass(ClassDeclaration declaration) {
+ void _checkForFinalNotInitializedInClass(ClassDeclaration declaration) {
NodeList<ClassMember> classMembers = declaration.members;
for (ClassMember classMember in classMembers) {
if (classMember is ConstructorDeclaration) {
- return false;
+ return;
}
}
- bool foundError = false;
for (ClassMember classMember in classMembers) {
- if (classMember is FieldDeclaration &&
- _checkForFinalNotInitialized(classMember.fields)) {
- foundError = true;
+ if (classMember is FieldDeclaration) {
+ _checkForFinalNotInitialized(classMember.fields);
}
}
- return foundError;
}
/**
@@ -3406,26 +3822,60 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
}
if (_enclosingFunction.isAsynchronous) {
if (_enclosingFunction.isGenerator) {
- if (!_typeSystem.isAssignableTo(
- _enclosingFunction.returnType, _typeProvider.streamDynamicType)) {
- _errorReporter.reportErrorForNode(
- StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE,
- returnType);
- }
+ _checkForIllegalReturnTypeCode(
+ returnType,
+ _typeProvider.streamDynamicType,
+ StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE);
} else {
- if (!_typeSystem.isAssignableTo(
- _enclosingFunction.returnType, _typeProvider.futureDynamicType)) {
- _errorReporter.reportErrorForNode(
- StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE, returnType);
- }
+ _checkForIllegalReturnTypeCode(
+ returnType,
+ _typeProvider.futureDynamicType,
+ StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE);
}
} else if (_enclosingFunction.isGenerator) {
- if (!_typeSystem.isAssignableTo(
- _enclosingFunction.returnType, _typeProvider.iterableDynamicType)) {
- _errorReporter.reportErrorForNode(
- StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE,
- returnType);
+ _checkForIllegalReturnTypeCode(
+ returnType,
+ _typeProvider.iterableDynamicType,
+ StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE);
+ }
+ }
+
+ /**
+ * If the current function is async, async*, or sync*, verify that its
+ * declared return type is assignable to Future, Stream, or Iterable,
+ * respectively. This is called by [_checkForIllegalReturnType] to check if
+ * the declared [returnTypeName] is assignable to the required [expectedType]
+ * and if not report [errorCode].
+ */
+ void _checkForIllegalReturnTypeCode(TypeName returnTypeName,
+ DartType expectedType, StaticTypeWarningCode errorCode) {
+ DartType returnType = _enclosingFunction.returnType;
+ if (_options.strongMode) {
+ //
+ // When checking an async/sync*/async* method, we know the exact type
+ // that will be returned (e.g. Future, Iterable, or Stream).
+ //
+ // For example an `async` function body will return a `Future<T>` for
+ // some `T` (possibly `dynamic`).
+ //
+ // We allow the declared return type to be a supertype of that
+ // (e.g. `dynamic`, `Object`), or Future<S> for some S.
+ // (We assume the T <: S relation is checked elsewhere.)
+ //
+ // We do not allow user-defined subtypes of Future, because an `async`
+ // method will never return those.
+ //
+ // To check for this, we ensure that `Future<bottom> <: returnType`.
+ //
+ // Similar logic applies for sync* and async*.
+ //
+ InterfaceType genericType = (expectedType.element as ClassElement).type;
+ DartType lowerBound = genericType.instantiate([BottomTypeImpl.instance]);
+ if (!_typeSystem.isSubtypeOf(lowerBound, returnType)) {
+ _errorReporter.reportErrorForNode(errorCode, returnTypeName);
}
+ } else if (!_typeSystem.isAssignableTo(returnType, expectedType)) {
+ _errorReporter.reportErrorForNode(errorCode, returnTypeName);
}
}
@@ -3435,18 +3885,14 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS].
*/
- bool _checkForImplementsDeferredClass(ImplementsClause clause) {
+ void _checkForImplementsDeferredClass(ImplementsClause clause) {
if (clause == null) {
- return false;
+ return;
}
- bool foundError = false;
for (TypeName type in clause.interfaces) {
- if (_checkForExtendsOrImplementsDeferredClass(
- type, CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS)) {
- foundError = true;
- }
+ _checkForExtendsOrImplementsDeferredClass(
+ type, CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS);
}
- return foundError;
}
/**
@@ -3469,6 +3915,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.
@@ -3477,58 +4030,55 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
* [CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_STATIC].
* TODO(scheglov) rename thid method
*/
- bool _checkForImplicitThisReferenceInInitializer(
+ void _checkForImplicitThisReferenceInInitializer(
SimpleIdentifier identifier) {
if (!_isInConstructorInitializer &&
!_isInStaticMethod &&
!_isInFactory &&
!_isInInstanceVariableInitializer &&
!_isInStaticVariableDeclaration) {
- return false;
+ return;
}
// prepare element
Element element = identifier.staticElement;
if (!(element is MethodElement || element is PropertyAccessorElement)) {
- return false;
+ return;
}
// static element
ExecutableElement executableElement = element as ExecutableElement;
if (executableElement.isStatic) {
- return false;
+ return;
}
// not a class member
Element enclosingElement = element.enclosingElement;
if (enclosingElement is! ClassElement) {
- return false;
+ return;
}
// comment
AstNode parent = identifier.parent;
if (parent is CommentReference) {
- return false;
+ return;
}
// qualified method invocation
if (parent is MethodInvocation) {
- MethodInvocation invocation = parent;
- if (identical(invocation.methodName, identifier) &&
- invocation.realTarget != null) {
- return false;
+ if (identical(parent.methodName, identifier) &&
+ parent.realTarget != null) {
+ return;
}
}
// qualified property access
if (parent is PropertyAccess) {
- PropertyAccess access = parent;
- if (identical(access.propertyName, identifier) &&
- access.realTarget != null) {
- return false;
+ if (identical(parent.propertyName, identifier) &&
+ parent.realTarget != null) {
+ return;
}
}
if (parent is PrefixedIdentifier) {
- PrefixedIdentifier prefixed = parent;
- if (identical(prefixed.identifier, identifier)) {
- return false;
+ if (identical(parent.identifier, identifier)) {
+ return;
}
}
- // report problem
+
if (_isInStaticMethod) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_STATIC, identifier);
@@ -3540,7 +4090,6 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER,
identifier);
}
- return true;
}
/**
@@ -3551,33 +4100,28 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.IMPORT_DUPLICATED_LIBRARY_NAME].
*/
- bool _checkForImportDuplicateLibraryName(
+ void _checkForImportDuplicateLibraryName(
ImportDirective directive, ImportElement importElement) {
// prepare imported library
LibraryElement nodeLibrary = importElement.importedLibrary;
if (nodeLibrary == null) {
- return false;
+ return;
}
String name = nodeLibrary.name;
// check if there is another imported library with the same name
LibraryElement prevLibrary = _nameToImportElement[name];
if (prevLibrary != null) {
- if (prevLibrary != nodeLibrary) {
- if (!name.isEmpty) {
- _errorReporter.reportErrorForNode(
- StaticWarningCode.IMPORT_DUPLICATED_LIBRARY_NAMED, directive, [
- prevLibrary.definingCompilationUnit.displayName,
- nodeLibrary.definingCompilationUnit.displayName,
- name
- ]);
- }
- return true;
+ if (prevLibrary != nodeLibrary && !name.isEmpty) {
+ _errorReporter.reportErrorForNode(
+ StaticWarningCode.IMPORT_DUPLICATED_LIBRARY_NAMED, directive, [
+ prevLibrary.definingCompilationUnit.displayName,
+ nodeLibrary.definingCompilationUnit.displayName,
+ name
+ ]);
}
} else {
_nameToImportElement[name] = nodeLibrary;
}
- // OK
- return false;
}
/**
@@ -3588,27 +4132,23 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.IMPORT_INTERNAL_LIBRARY].
*/
- bool _checkForImportInternalLibrary(
+ void _checkForImportInternalLibrary(
ImportDirective directive, ImportElement importElement) {
if (_isInSystemLibrary) {
- return false;
+ return;
}
// should be private
DartSdk sdk = _currentLibrary.context.sourceFactory.dartSdk;
String uri = importElement.uri;
SdkLibrary sdkLibrary = sdk.getSdkLibrary(uri);
- if (sdkLibrary == null) {
- return false;
- }
- if (!sdkLibrary.isInternal) {
- return false;
+ if (sdkLibrary == null || !sdkLibrary.isInternal) {
+ return;
}
- // report problem
+
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.IMPORT_INTERNAL_LIBRARY,
directive,
[directive.uri]);
- return true;
}
/**
@@ -3617,20 +4157,73 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE].
*/
- bool _checkForInconsistentMethodInheritance() {
+ void _checkForInconsistentMethodInheritance() {
// Ensure that the inheritance manager has a chance to generate all errors
// we may care about, note that we ensure that the interfaces data since
// there are no errors.
- _inheritanceManager.getMapOfMembersInheritedFromInterfaces(_enclosingClass);
- HashSet<AnalysisError> errors =
- _inheritanceManager.getErrors(_enclosingClass);
+ _inheritanceManager.getMembersInheritedFromInterfaces(_enclosingClass);
+ Set<AnalysisError> errors = _inheritanceManager.getErrors(_enclosingClass);
if (errors == null || errors.isEmpty) {
- return false;
+ return;
}
for (AnalysisError error in errors) {
_errorReporter.reportError(error);
}
- return true;
+ return;
+ }
+
+ /**
+ * Check for a type mis-match between the iterable expression and the
+ * assigned variable in a for-in statement.
+ */
+ void _checkForInIterable(ForEachStatement node) {
+ // Ignore malformed for statements.
+ if (node.identifier == null && node.loopVariable == null) {
+ return;
+ }
+
+ DartType iterableType = getStaticType(node.iterable);
+ if (iterableType.isDynamic) {
+ return;
+ }
+
+ // The type of the loop variable.
+ SimpleIdentifier variable = node.identifier ?? node.loopVariable.identifier;
+ DartType variableType = getStaticType(variable);
+
+ DartType loopType = node.awaitKeyword != null
+ ? _typeProvider.streamType
+ : _typeProvider.iterableType;
+
+ // Use an explicit string instead of [loopType] to remove the "<E>".
+ String loopTypeName = node.awaitKeyword != null ? "Stream" : "Iterable";
+
+ // The object being iterated has to implement Iterable<T> for some T that
+ // is assignable to the variable's type.
+ // TODO(rnystrom): Move this into mostSpecificTypeArgument()?
+ iterableType = iterableType.resolveToBound(_typeProvider.objectType);
+ DartType bestIterableType =
+ _typeSystem.mostSpecificTypeArgument(iterableType, loopType);
+
+ // Allow it to be a supertype of Iterable<T> (basically just Object) and do
+ // an implicit downcast to Iterable<dynamic>.
+ if (bestIterableType == null) {
+ if (_typeSystem.isSubtypeOf(loopType, iterableType)) {
+ bestIterableType = DynamicTypeImpl.instance;
+ }
+ }
+
+ if (bestIterableType == null) {
+ _errorReporter.reportTypeErrorForNode(
+ StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE,
+ node.iterable,
+ [iterableType, loopTypeName]);
+ } else if (!_typeSystem.isAssignableTo(bestIterableType, variableType)) {
+ _errorReporter.reportTypeErrorForNode(
+ StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE,
+ node.iterable,
+ [iterableType, loopTypeName, variableType]);
+ }
}
/**
@@ -3639,36 +4232,32 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER].
*/
- bool _checkForInstanceAccessToStaticMember(
+ void _checkForInstanceAccessToStaticMember(
ClassElement typeReference, SimpleIdentifier name) {
// OK, in comment
if (_isInComment) {
- return false;
+ return;
}
// OK, target is a type
if (typeReference != null) {
- return false;
+ return;
}
// prepare member Element
Element element = name.staticElement;
- if (element is! ExecutableElement) {
- return false;
- }
- ExecutableElement executableElement = element as ExecutableElement;
- // OK, top-level element
- if (executableElement.enclosingElement is! ClassElement) {
- return false;
- }
- // OK, instance member
- if (!executableElement.isStatic) {
- return false;
+ if (element is ExecutableElement) {
+ // OK, top-level element
+ if (element.enclosingElement is! ClassElement) {
+ return;
+ }
+ // OK, instance member
+ if (!element.isStatic) {
+ return;
+ }
+ _errorReporter.reportErrorForNode(
+ StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER,
+ name,
+ [name.name]);
}
- // report problem
- _errorReporter.reportErrorForNode(
- StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER,
- name,
- [name.name]);
- return true;
}
/**
@@ -3686,8 +4275,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
!executableElement.isOperator) {
HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>();
InterfaceType superclassType = _enclosingClass.supertype;
- ClassElement superclassElement =
- superclassType == null ? null : superclassType.element;
+ ClassElement superclassElement = superclassType?.element;
bool executableElementPrivate =
Identifier.isPrivateName(executableElementName);
while (superclassElement != null &&
@@ -3706,7 +4294,8 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
// instance vs. static
if (fieldElt.isStatic) {
_errorReporter.reportErrorForNode(
- StaticWarningCode.INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC,
+ StaticWarningCode
+ .INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC,
errorNameTarget,
[executableElementName, fieldElt.enclosingElement.displayName]);
return true;
@@ -3714,7 +4303,9 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
}
// Check methods.
List<MethodElement> methodElements = superclassElement.methods;
- for (MethodElement methodElement in methodElements) {
+ int length = methodElements.length;
+ for (int i = 0; i < length; i++) {
+ MethodElement methodElement = methodElements[i];
// We need the same name.
if (methodElement.name != executableElementName) {
continue;
@@ -3727,17 +4318,18 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
// instance vs. static
if (methodElement.isStatic) {
_errorReporter.reportErrorForNode(
- StaticWarningCode.INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC,
- errorNameTarget, [
- executableElementName,
- methodElement.enclosingElement.displayName
- ]);
+ StaticWarningCode
+ .INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC,
+ errorNameTarget,
+ [
+ executableElementName,
+ methodElement.enclosingElement.displayName
+ ]);
return true;
}
}
superclassType = superclassElement.supertype;
- superclassElement =
- superclassType == null ? null : superclassType.element;
+ superclassElement = superclassType?.element;
}
}
return false;
@@ -3750,15 +4342,14 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE].
*/
- bool _checkForIntNotAssignable(Expression argument) {
+ void _checkForIntNotAssignable(Expression argument) {
if (argument == null) {
- return false;
+ return;
}
ParameterElement staticParameterElement = argument.staticParameterElement;
- DartType staticParameterType =
- staticParameterElement == null ? null : staticParameterElement.type;
- return _checkForArgumentTypeNotAssignable(argument, staticParameterType,
- _intType, StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE);
+ DartType staticParameterType = staticParameterElement?.type;
+ _checkForArgumentTypeNotAssignable(argument, staticParameterType, _intType,
+ StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE);
}
/**
@@ -3766,17 +4357,13 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.INVALID_ANNOTATION_FROM_DEFERRED_LIBRARY].
*/
- bool _checkForInvalidAnnotationFromDeferredLibrary(Annotation annotation) {
+ void _checkForInvalidAnnotationFromDeferredLibrary(Annotation annotation) {
Identifier nameIdentifier = annotation.name;
- if (nameIdentifier is PrefixedIdentifier) {
- if (nameIdentifier.isDeferred) {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.INVALID_ANNOTATION_FROM_DEFERRED_LIBRARY,
- annotation.name);
- return true;
- }
+ if (nameIdentifier is PrefixedIdentifier && nameIdentifier.isDeferred) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.INVALID_ANNOTATION_FROM_DEFERRED_LIBRARY,
+ annotation.name);
}
- return false;
}
/**
@@ -3785,23 +4372,16 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [StaticTypeWarningCode.INVALID_ASSIGNMENT].
*/
- bool _checkForInvalidAssignment(Expression lhs, Expression rhs) {
+ void _checkForInvalidAssignment(Expression lhs, Expression rhs) {
if (lhs == null || rhs == null) {
- return false;
+ return;
}
VariableElement leftVariableElement = getVariableElement(lhs);
DartType leftType = (leftVariableElement == null)
? getStaticType(lhs)
: leftVariableElement.type;
- DartType staticRightType = getStaticType(rhs);
- if (!_typeSystem.isAssignableTo(staticRightType, leftType)) {
- _errorReporter.reportTypeErrorForNode(
- StaticTypeWarningCode.INVALID_ASSIGNMENT,
- rhs,
- [staticRightType, leftType]);
- return true;
- }
- return false;
+ _checkForAssignableExpression(
+ rhs, leftType, StaticTypeWarningCode.INVALID_ASSIGNMENT);
}
/**
@@ -3811,29 +4391,17 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [StaticTypeWarningCode.INVALID_ASSIGNMENT].
*/
- bool _checkForInvalidCompoundAssignment(
+ void _checkForInvalidCompoundAssignment(
AssignmentExpression assignment, Expression lhs, Expression rhs) {
if (lhs == null) {
- return false;
- }
- VariableElement leftVariableElement = getVariableElement(lhs);
- DartType leftType = (leftVariableElement == null)
- ? getStaticType(lhs)
- : leftVariableElement.type;
- MethodElement invokedMethod = assignment.staticElement;
- if (invokedMethod == null) {
- return false;
- }
- DartType rightType = invokedMethod.type.returnType;
- if (leftType == null || rightType == null) {
- return false;
+ return;
}
+ DartType leftType = getStaticType(lhs);
+ DartType rightType = getStaticType(assignment);
if (!_typeSystem.isAssignableTo(rightType, leftType)) {
_errorReporter.reportTypeErrorForNode(
StaticTypeWarningCode.INVALID_ASSIGNMENT, rhs, [rightType, leftType]);
- return true;
}
- return false;
}
/**
@@ -3845,13 +4413,12 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
void _checkForInvalidField(ConstructorFieldInitializer initializer,
SimpleIdentifier fieldName, Element staticElement) {
if (staticElement is FieldElement) {
- FieldElement fieldElement = staticElement;
- if (fieldElement.isSynthetic) {
+ if (staticElement.isSynthetic) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.INITIALIZER_FOR_NON_EXISTENT_FIELD,
initializer,
[fieldName]);
- } else if (fieldElement.isStatic) {
+ } else if (staticElement.isStatic) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.INITIALIZER_FOR_STATIC_FIELD,
initializer,
@@ -3870,14 +4437,12 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
* Check to see whether the given function [body] has a modifier associated
* with it, and report it as an error if it does.
*/
- bool _checkForInvalidModifierOnBody(
+ void _checkForInvalidModifierOnBody(
FunctionBody body, CompileTimeErrorCode errorCode) {
- sc.Token keyword = body.keyword;
+ Token keyword = body.keyword;
if (keyword != null) {
_errorReporter.reportErrorForToken(errorCode, keyword, [keyword.lexeme]);
- return true;
}
- return false;
}
/**
@@ -3885,13 +4450,11 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS].
*/
- bool _checkForInvalidReferenceToThis(ThisExpression expression) {
+ void _checkForInvalidReferenceToThis(ThisExpression expression) {
if (!_isThisInValidContext(expression)) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS, expression);
- return true;
}
- return false;
}
/**
@@ -3900,76 +4463,71 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
* [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_LIST] or
* [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP].
*/
- bool _checkForInvalidTypeArgumentInConstTypedLiteral(
+ void _checkForInvalidTypeArgumentInConstTypedLiteral(
NodeList<TypeName> arguments, ErrorCode errorCode) {
- bool foundError = false;
for (TypeName typeName in arguments) {
if (typeName.type is TypeParameterType) {
_errorReporter.reportErrorForNode(errorCode, typeName, [typeName.name]);
- foundError = true;
}
}
- return foundError;
}
/**
- * Verify that the elements given list [literal] are subtypes of the specified
- * element type. The [typeArguments] are the type arguments.
+ * Verify that the elements given list [literal] are subtypes of the list's
+ * static type.
*
* See [CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE], and
* [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE].
*/
- bool _checkForListElementTypeNotAssignable(
- ListLiteral literal, TypeArgumentList typeArguments) {
- NodeList<TypeName> typeNames = typeArguments.arguments;
- if (typeNames.length < 1) {
- return false;
- }
- DartType listElementType = typeNames[0].type;
+ void _checkForListElementTypeNotAssignable(ListLiteral literal) {
+ // Determine the list's element type. We base this on the static type and
+ // not the literal's type arguments because in strong mode, the type
+ // arguments may be inferred.
+ DartType listType = literal.staticType;
+ assert(listType is InterfaceTypeImpl);
+
+ List<DartType> typeArguments =
+ (listType as InterfaceTypeImpl).typeArguments;
+ assert(typeArguments.length == 1);
+
+ DartType listElementType = typeArguments[0];
+
// Check every list element.
- bool hasProblems = false;
for (Expression element in literal.elements) {
if (literal.constKeyword != null) {
// TODO(paulberry): this error should be based on the actual type of the
// list element, not the static type. See dartbug.com/21119.
- if (_checkForArgumentTypeNotAssignableWithExpectedTypes(
+ _checkForArgumentTypeNotAssignableWithExpectedTypes(
element,
listElementType,
- CheckedModeCompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE)) {
- hasProblems = true;
- }
- }
- if (_checkForArgumentTypeNotAssignableWithExpectedTypes(
- element,
- listElementType,
- StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE)) {
- hasProblems = true;
+ CheckedModeCompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE);
}
+ _checkForArgumentTypeNotAssignableWithExpectedTypes(element,
+ listElementType, StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE);
}
- return hasProblems;
}
/**
* Verify that the key/value of entries of the given map [literal] are
- * subtypes of the key/value types specified in the type arguments. The
- * [typeArguments] are the type arguments.
+ * subtypes of the map's static type.
*
* See [CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE],
* [CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE],
* [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE], and
* [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE].
*/
- bool _checkForMapTypeNotAssignable(
- MapLiteral literal, TypeArgumentList typeArguments) {
- // Prepare maps key/value types.
- NodeList<TypeName> typeNames = typeArguments.arguments;
- if (typeNames.length < 2) {
- return false;
- }
- DartType keyType = typeNames[0].type;
- DartType valueType = typeNames[1].type;
- // Check every map entry.
- bool hasProblems = false;
+ void _checkForMapTypeNotAssignable(MapLiteral literal) {
+ // Determine the map's key and value types. We base this on the static type
+ // and not the literal's type arguments because in strong mode, the type
+ // arguments may be inferred.
+ DartType mapType = literal.staticType;
+ assert(mapType is InterfaceTypeImpl);
+
+ List<DartType> typeArguments = (mapType as InterfaceTypeImpl).typeArguments;
+ assert(typeArguments.length == 2);
+ DartType keyType = typeArguments[0];
+ DartType valueType = typeArguments[1];
+
NodeList<MapLiteralEntry> entries = literal.entries;
for (MapLiteralEntry entry in entries) {
Expression key = entry.key;
@@ -3977,27 +4535,16 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
if (literal.constKeyword != null) {
// TODO(paulberry): this error should be based on the actual type of the
// list element, not the static type. See dartbug.com/21119.
- if (_checkForArgumentTypeNotAssignableWithExpectedTypes(key, keyType,
- CheckedModeCompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE)) {
- hasProblems = true;
- }
- if (_checkForArgumentTypeNotAssignableWithExpectedTypes(
- value,
- valueType,
- CheckedModeCompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE)) {
- hasProblems = true;
- }
- }
- if (_checkForArgumentTypeNotAssignableWithExpectedTypes(
- key, keyType, StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE)) {
- hasProblems = true;
- }
- if (_checkForArgumentTypeNotAssignableWithExpectedTypes(
- value, valueType, StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE)) {
- hasProblems = true;
+ _checkForArgumentTypeNotAssignableWithExpectedTypes(key, keyType,
+ CheckedModeCompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE);
+ _checkForArgumentTypeNotAssignableWithExpectedTypes(value, valueType,
+ CheckedModeCompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE);
}
+ _checkForArgumentTypeNotAssignableWithExpectedTypes(
+ key, keyType, StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE);
+ _checkForArgumentTypeNotAssignableWithExpectedTypes(
+ value, valueType, StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE);
}
- return hasProblems;
}
/**
@@ -4006,26 +4553,23 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME].
*/
- bool _checkForMemberWithClassName() {
+ void _checkForMemberWithClassName() {
if (_enclosingClass == null) {
- return false;
+ return;
}
String className = _enclosingClass.name;
if (className == null) {
- return false;
+ return;
}
- bool problemReported = false;
+
// check accessors
for (PropertyAccessorElement accessor in _enclosingClass.accessors) {
if (className == accessor.name) {
_errorReporter.reportErrorForElement(
CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME, accessor);
- problemReported = true;
}
}
// don't check methods, they would be constructors
- // done
- return problemReported;
}
/**
@@ -4035,90 +4579,87 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
* See [StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES], and
* [StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES_FROM_SUPERTYPE].
*/
- bool _checkForMismatchedAccessorTypes(
+ void _checkForMismatchedAccessorTypes(
Declaration accessorDeclaration, String accessorTextName) {
ExecutableElement accessorElement =
accessorDeclaration.element as ExecutableElement;
- if (accessorElement is! PropertyAccessorElement) {
- return false;
- }
- PropertyAccessorElement propertyAccessorElement =
- accessorElement as PropertyAccessorElement;
- PropertyAccessorElement counterpartAccessor = null;
- ClassElement enclosingClassForCounterpart = null;
- if (propertyAccessorElement.isGetter) {
- counterpartAccessor = propertyAccessorElement.correspondingSetter;
- } else {
- counterpartAccessor = propertyAccessorElement.correspondingGetter;
- // If the setter and getter are in the same enclosing element, return,
- // this prevents having MISMATCHED_GETTER_AND_SETTER_TYPES reported twice.
- if (counterpartAccessor != null &&
- identical(counterpartAccessor.enclosingElement,
- propertyAccessorElement.enclosingElement)) {
- return false;
- }
- }
- if (counterpartAccessor == null) {
- // If the accessor is declared in a class, check the superclasses.
- if (_enclosingClass != null) {
- // Figure out the correct identifier to lookup in the inheritance graph,
- // if 'x', then 'x=', or if 'x=', then 'x'.
- String lookupIdentifier = propertyAccessorElement.name;
- if (StringUtilities.endsWithChar(lookupIdentifier, 0x3D)) {
- lookupIdentifier =
- lookupIdentifier.substring(0, lookupIdentifier.length - 1);
- } else {
- lookupIdentifier += "=";
- }
- // lookup with the identifier.
- ExecutableElement elementFromInheritance = _inheritanceManager
- .lookupInheritance(_enclosingClass, lookupIdentifier);
- // Verify that we found something, and that it is an accessor
- if (elementFromInheritance != null &&
- elementFromInheritance is PropertyAccessorElement) {
- enclosingClassForCounterpart =
- elementFromInheritance.enclosingElement as ClassElement;
- counterpartAccessor = elementFromInheritance;
+ if (accessorElement is PropertyAccessorElement) {
+ PropertyAccessorElement counterpartAccessor = null;
+ ClassElement enclosingClassForCounterpart = null;
+ if (accessorElement.isGetter) {
+ counterpartAccessor = accessorElement.correspondingSetter;
+ } else {
+ counterpartAccessor = accessorElement.correspondingGetter;
+ // If the setter and getter are in the same enclosing element, return,
+ // this prevents having MISMATCHED_GETTER_AND_SETTER_TYPES reported twice.
+ if (counterpartAccessor != null &&
+ identical(counterpartAccessor.enclosingElement,
+ accessorElement.enclosingElement)) {
+ return;
}
}
if (counterpartAccessor == null) {
- return false;
+ // If the accessor is declared in a class, check the superclasses.
+ if (_enclosingClass != null) {
+ // Figure out the correct identifier to lookup in the inheritance graph,
+ // if 'x', then 'x=', or if 'x=', then 'x'.
+ String lookupIdentifier = accessorElement.name;
+ if (StringUtilities.endsWithChar(lookupIdentifier, 0x3D)) {
+ lookupIdentifier =
+ lookupIdentifier.substring(0, lookupIdentifier.length - 1);
+ } else {
+ lookupIdentifier += "=";
+ }
+ // lookup with the identifier.
+ ExecutableElement elementFromInheritance = _inheritanceManager
+ .lookupInheritance(_enclosingClass, lookupIdentifier);
+ // Verify that we found something, and that it is an accessor
+ if (elementFromInheritance != null &&
+ elementFromInheritance is PropertyAccessorElement) {
+ enclosingClassForCounterpart =
+ elementFromInheritance.enclosingElement as ClassElement;
+ counterpartAccessor = elementFromInheritance;
+ }
+ }
+ if (counterpartAccessor == null) {
+ return;
+ }
}
- }
- // Default of null == no accessor or no type (dynamic)
- DartType getterType = null;
- DartType setterType = null;
- // Get an existing counterpart accessor if any.
- if (propertyAccessorElement.isGetter) {
- getterType = _getGetterType(propertyAccessorElement);
- setterType = _getSetterType(counterpartAccessor);
- } else if (propertyAccessorElement.isSetter) {
- setterType = _getSetterType(propertyAccessorElement);
- getterType = _getGetterType(counterpartAccessor);
- }
- // If either types are not assignable to each other, report an error
- // (if the getter is null, it is dynamic which is assignable to everything).
- if (setterType != null &&
- getterType != null &&
- !_typeSystem.isAssignableTo(getterType, setterType)) {
- if (enclosingClassForCounterpart == null) {
- _errorReporter.reportTypeErrorForNode(
- StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES,
- accessorDeclaration,
- [accessorTextName, setterType, getterType]);
- return true;
- } else {
- _errorReporter.reportTypeErrorForNode(
- StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES_FROM_SUPERTYPE,
- accessorDeclaration, [
- accessorTextName,
- setterType,
- getterType,
- enclosingClassForCounterpart.displayName
- ]);
+ // Default of null == no accessor or no type (dynamic)
+ DartType getterType = null;
+ DartType setterType = null;
+ // Get an existing counterpart accessor if any.
+ if (accessorElement.isGetter) {
+ getterType = _getGetterType(accessorElement);
+ setterType = _getSetterType(counterpartAccessor);
+ } else if (accessorElement.isSetter) {
+ setterType = _getSetterType(accessorElement);
+ getterType = _getGetterType(counterpartAccessor);
+ }
+ // If either types are not assignable to each other, report an error
+ // (if the getter is null, it is dynamic which is assignable to everything).
+ if (setterType != null &&
+ getterType != null &&
+ !_typeSystem.isAssignableTo(getterType, setterType)) {
+ if (enclosingClassForCounterpart == null) {
+ _errorReporter.reportTypeErrorForNode(
+ StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES,
+ accessorDeclaration,
+ [accessorTextName, setterType, getterType]);
+ } else {
+ _errorReporter.reportTypeErrorForNode(
+ StaticWarningCode
+ .MISMATCHED_GETTER_AND_SETTER_TYPES_FROM_SUPERTYPE,
+ accessorDeclaration,
+ [
+ accessorTextName,
+ setterType,
+ getterType,
+ enclosingClassForCounterpart.displayName
+ ]);
+ }
}
}
- return false;
}
/**
@@ -4126,57 +4667,63 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
* an enum type either have a default case or include all of the enum
* constants.
*/
- bool _checkForMissingEnumConstantInSwitch(SwitchStatement statement) {
+ void _checkForMissingEnumConstantInSwitch(SwitchStatement statement) {
// TODO(brianwilkerson) This needs to be checked after constant values have
// been computed.
Expression expression = statement.expression;
DartType expressionType = getStaticType(expression);
if (expressionType == null) {
- return false;
+ return;
}
Element expressionElement = expressionType.element;
- if (expressionElement is! ClassElement) {
- return false;
- }
- ClassElement classElement = expressionElement as ClassElement;
- if (!classElement.isEnum) {
- return false;
- }
- List<String> constantNames = new List<String>();
- List<FieldElement> fields = classElement.fields;
- int fieldCount = fields.length;
- for (int i = 0; i < fieldCount; i++) {
- FieldElement field = fields[i];
- if (field.isStatic && !field.isSynthetic) {
- constantNames.add(field.name);
+ if (expressionElement is ClassElement) {
+ if (!expressionElement.isEnum) {
+ return;
+ }
+ List<String> constantNames = <String>[];
+ List<FieldElement> fields = expressionElement.fields;
+ int fieldCount = fields.length;
+ for (int i = 0; i < fieldCount; i++) {
+ FieldElement field = fields[i];
+ if (field.isStatic && !field.isSynthetic) {
+ constantNames.add(field.name);
+ }
}
- }
- NodeList<SwitchMember> members = statement.members;
- int memberCount = members.length;
- for (int i = 0; i < memberCount; i++) {
- SwitchMember member = members[i];
- if (member is SwitchDefault) {
- return false;
+ NodeList<SwitchMember> members = statement.members;
+ int memberCount = members.length;
+ for (int i = 0; i < memberCount; i++) {
+ SwitchMember member = members[i];
+ if (member is SwitchDefault) {
+ return;
+ }
+ String constantName =
+ _getConstantName((member as SwitchCase).expression);
+ if (constantName != null) {
+ constantNames.remove(constantName);
+ }
}
- String constantName = _getConstantName((member as SwitchCase).expression);
- if (constantName != null) {
- constantNames.remove(constantName);
+ if (constantNames.isEmpty) {
+ return;
+ }
+ for (int i = 0; i < constantNames.length; i++) {
+ int offset = statement.offset;
+ int end = statement.rightParenthesis.end;
+ _errorReporter.reportErrorForOffset(
+ StaticWarningCode.MISSING_ENUM_CONSTANT_IN_SWITCH,
+ offset,
+ end - offset,
+ [constantNames[i]]);
}
}
- int nameCount = constantNames.length;
- if (nameCount == 0) {
- return false;
- }
- for (int i = 0; i < nameCount; i++) {
- int offset = statement.offset;
- int end = statement.rightParenthesis.end;
- _errorReporter.reportErrorForOffset(
- CompileTimeErrorCode.MISSING_ENUM_CONSTANT_IN_SWITCH,
- offset,
- end - offset,
- [constantNames[i]]);
+ }
+
+ void _checkForMissingJSLibAnnotation(Annotation node) {
+ if (node.elementAnnotation?.isJS ?? false) {
+ if (_currentLibrary.isJS != true) {
+ _errorReporter.reportErrorForNode(
+ HintCode.MISSING_JS_LIB_ANNOTATION, node);
+ }
}
- return true;
}
/**
@@ -4185,24 +4732,20 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [StaticWarningCode.MIXED_RETURN_TYPES].
*/
- bool _checkForMixedReturns(BlockFunctionBody body) {
+ void _checkForMixedReturns(BlockFunctionBody body) {
if (_hasReturnWithoutValue) {
- return false;
+ return;
}
- int withCount = _returnsWith.length;
- int withoutCount = _returnsWithout.length;
- if (withCount > 0 && withoutCount > 0) {
- for (int i = 0; i < withCount; i++) {
- _errorReporter.reportErrorForToken(StaticWarningCode.MIXED_RETURN_TYPES,
- _returnsWith[i].returnKeyword);
+ if (_returnsWith.isNotEmpty && _returnsWithout.isNotEmpty) {
+ for (ReturnStatement returnWith in _returnsWith) {
+ _errorReporter.reportErrorForToken(
+ StaticWarningCode.MIXED_RETURN_TYPES, returnWith.returnKeyword);
}
- for (int i = 0; i < withoutCount; i++) {
- _errorReporter.reportErrorForToken(StaticWarningCode.MIXED_RETURN_TYPES,
- _returnsWithout[i].returnKeyword);
+ for (ReturnStatement returnWithout in _returnsWithout) {
+ _errorReporter.reportErrorForToken(
+ StaticWarningCode.MIXED_RETURN_TYPES, returnWithout.returnKeyword);
}
- return true;
}
- return false;
}
/**
@@ -4231,10 +4774,10 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
* appropriate.
*/
void _checkForMixinHasNoConstructors(AstNode node) {
- if ((_enclosingClass as ClassElementImpl).doesMixinLackConstructors) {
+ if (_enclosingClass.doesMixinLackConstructors) {
ErrorCode errorCode = CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS;
- _errorReporter.reportErrorForNode(
- errorCode, node, [_enclosingClass.supertype]);
+ _errorReporter
+ .reportErrorForNode(errorCode, node, [_enclosingClass.supertype]);
}
}
@@ -4284,18 +4827,29 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.MULTIPLE_SUPER_INITIALIZERS].
*/
- bool _checkForMultipleSuperInitializers(ConstructorDeclaration constructor) {
- int numSuperInitializers = 0;
+ void _checkForMultipleSuperInitializers(ConstructorDeclaration constructor) {
+ bool hasSuperInitializer = false;
for (ConstructorInitializer initializer in constructor.initializers) {
if (initializer is SuperConstructorInvocation) {
- numSuperInitializers++;
- if (numSuperInitializers > 1) {
+ if (hasSuperInitializer) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.MULTIPLE_SUPER_INITIALIZERS, initializer);
}
+ hasSuperInitializer = true;
+ }
+ }
+ }
+
+ void _checkForMustCallSuper(MethodDeclaration node) {
+ MethodElement element = _findOverriddenMemberThatMustCallSuper(node);
+ if (element != null) {
+ _InvocationCollector collector = new _InvocationCollector();
+ node.accept(collector);
+ if (!collector.superCalls.contains(element.name)) {
+ _errorReporter.reportErrorForNode(HintCode.MUST_CALL_SUPER, node.name,
+ [element.enclosingElement.name]);
}
}
- return numSuperInitializers > 0;
}
/**
@@ -4303,13 +4857,11 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [ParserErrorCode.NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE].
*/
- bool _checkForNativeFunctionBodyInNonSDKCode(NativeFunctionBody body) {
+ void _checkForNativeFunctionBodyInNonSdkCode(NativeFunctionBody body) {
if (!_isInSystemLibrary && !_hasExtUri) {
_errorReporter.reportErrorForNode(
ParserErrorCode.NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE, body);
- return true;
}
- return false;
}
/**
@@ -4322,20 +4874,20 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [StaticWarningCode.NEW_WITH_UNDEFINED_CONSTRUCTOR].
*/
- bool _checkForNewWithUndefinedConstructor(
+ void _checkForNewWithUndefinedConstructor(
InstanceCreationExpression expression,
ConstructorName constructorName,
TypeName typeName) {
// OK if resolved
if (expression.staticElement != null) {
- return false;
+ return;
}
DartType type = typeName.type;
if (type is InterfaceType) {
ClassElement element = type.element;
if (element != null && element.isEnum) {
// We have already reported the error.
- return false;
+ return;
}
}
// prepare class name
@@ -4353,7 +4905,6 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
constructorName,
[className]);
}
- return true;
}
/**
@@ -4363,22 +4914,21 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT].
*/
- bool _checkForNoDefaultSuperConstructorImplicit(
+ void _checkForNoDefaultSuperConstructorImplicit(
ClassDeclaration declaration) {
// do nothing if mixin errors have already been reported for this class.
- ClassElementImpl enclosingClass = _enclosingClass;
- if (enclosingClass.doesMixinLackConstructors) {
- return false;
+ if (_enclosingClass.doesMixinLackConstructors) {
+ return;
}
// do nothing if there is explicit constructor
List<ConstructorElement> constructors = _enclosingClass.constructors;
if (!constructors[0].isSynthetic) {
- return false;
+ return;
}
// prepare super
InterfaceType superType = _enclosingClass.supertype;
if (superType == null) {
- return false;
+ return;
}
ClassElement superElement = superType.element;
// try to find default generative super constructor
@@ -4390,20 +4940,19 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR,
declaration.name,
[superUnnamedConstructor]);
- return true;
+ return;
}
if (superUnnamedConstructor.isDefaultConstructor &&
_enclosingClass
.isSuperConstructorAccessible(superUnnamedConstructor)) {
- return true;
+ return;
}
}
- // report problem
+
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT,
declaration.name,
[superType.displayName]);
- return true;
}
/**
@@ -4418,37 +4967,29 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
* [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR], and
* [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS].
*/
- bool _checkForNonAbstractClassInheritsAbstractMember(
+ void _checkForNonAbstractClassInheritsAbstractMember(
SimpleIdentifier classNameNode) {
if (_enclosingClass.isAbstract) {
- return false;
+ return;
+ } else if (_enclosingClass.hasNoSuchMethod) {
+ return;
}
//
// Store in local sets the set of all method and accessor names
//
- MethodElement method =
- _enclosingClass.getMethod(FunctionElement.NO_SUCH_METHOD_METHOD_NAME);
- if (method != null) {
- // If the enclosing class declares the method noSuchMethod(), then return.
- // From Spec: It is a static warning if a concrete class does not have an
- // implementation for a method in any of its superinterfaces unless it
- // declares its own noSuchMethod method (7.10).
- return false;
- }
HashSet<ExecutableElement> missingOverrides =
new HashSet<ExecutableElement>();
//
// Loop through the set of all executable elements declared in the implicit
// interface.
//
- MemberMap membersInheritedFromInterfaces = _inheritanceManager
- .getMapOfMembersInheritedFromInterfaces(_enclosingClass);
- MemberMap membersInheritedFromSuperclasses = _inheritanceManager
- .getMapOfMembersInheritedFromClasses(_enclosingClass);
- for (int i = 0; i < membersInheritedFromInterfaces.size; i++) {
- String memberName = membersInheritedFromInterfaces.getKey(i);
+ Map<String, ExecutableElement> membersInheritedFromInterfaces =
+ _inheritanceManager.getMembersInheritedFromInterfaces(_enclosingClass);
+ Map<String, ExecutableElement> membersInheritedFromSuperclasses =
+ _inheritanceManager.getMembersInheritedFromClasses(_enclosingClass);
+ for (String memberName in membersInheritedFromInterfaces.keys) {
ExecutableElement executableElt =
- membersInheritedFromInterfaces.getValue(i);
+ membersInheritedFromInterfaces[memberName];
if (memberName == null) {
break;
}
@@ -4469,7 +5010,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
}
// First check to see if this element was declared in the superclass
// chain, in which case there is already a concrete implementation.
- ExecutableElement elt = membersInheritedFromSuperclasses.get(memberName);
+ ExecutableElement elt = membersInheritedFromSuperclasses[memberName];
// Check to see if an element was found in the superclass chain with the
// correct name.
if (elt != null) {
@@ -4498,7 +5039,19 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
FunctionType requiredMemberFT = _inheritanceManager
.substituteTypeArgumentsInMemberFromInheritance(
requiredMemberType, memberName, enclosingType);
- if (_typeSystem.isSubtypeOf(foundConcreteFT, requiredMemberFT)) {
+ foundConcreteFT = _typeSystem.functionTypeToConcreteType(
+ _typeProvider, foundConcreteFT);
+ requiredMemberFT = _typeSystem.functionTypeToConcreteType(
+ _typeProvider, requiredMemberFT);
+
+ // Strong mode does override checking for types in CodeChecker, so
+ // we can skip it here. Doing it here leads to unnecessary duplicate
+ // error messages in subclasses that inherit from one that has an
+ // override error.
+ //
+ // See: https://github.com/dart-lang/sdk/issues/25232
+ if (_options.strongMode ||
+ _typeSystem.isSubtypeOf(foundConcreteFT, requiredMemberFT)) {
continue;
}
}
@@ -4511,19 +5064,18 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
// class.
int missingOverridesSize = missingOverrides.length;
if (missingOverridesSize == 0) {
- return false;
+ return;
}
List<ExecutableElement> missingOverridesArray =
new List.from(missingOverrides);
List<String> stringMembersArrayListSet = new List<String>();
for (int i = 0; i < missingOverridesArray.length; i++) {
String newStrMember;
- Element enclosingElement = missingOverridesArray[i].enclosingElement;
+ ExecutableElement element = missingOverridesArray[i];
+ Element enclosingElement = element.enclosingElement;
String prefix = StringUtilities.EMPTY;
- if (missingOverridesArray[i] is PropertyAccessorElement) {
- PropertyAccessorElement propertyAccessorElement =
- missingOverridesArray[i] as PropertyAccessorElement;
- if (propertyAccessorElement.isGetter) {
+ if (element is PropertyAccessorElement) {
+ if (element.isGetter) {
prefix = _GETTER_SPACE;
// "getter "
} else {
@@ -4533,13 +5085,14 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
}
if (enclosingElement != null) {
newStrMember =
- "$prefix'${enclosingElement.displayName}.${missingOverridesArray[i].displayName}'";
+ "$prefix'${enclosingElement.displayName}.${element.displayName}'";
} else {
- newStrMember = "$prefix'${missingOverridesArray[i].displayName}'";
+ newStrMember = "$prefix'${element.displayName}'";
}
stringMembersArrayListSet.add(newStrMember);
}
List<String> stringMembersArray = new List.from(stringMembersArrayListSet);
+ stringMembersArray.sort();
AnalysisErrorWithProperties analysisError;
if (stringMembersArray.length == 1) {
analysisError = _errorReporter.newErrorWithProperties(
@@ -4570,19 +5123,20 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
]);
} else {
analysisError = _errorReporter.newErrorWithProperties(
- StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS,
- classNameNode, [
- stringMembersArray[0],
- stringMembersArray[1],
- stringMembersArray[2],
- stringMembersArray[3],
- stringMembersArray.length - 4
- ]);
+ StaticWarningCode
+ .NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS,
+ classNameNode,
+ [
+ stringMembersArray[0],
+ stringMembersArray[1],
+ stringMembersArray[2],
+ stringMembersArray[3],
+ stringMembersArray.length - 4
+ ]);
}
analysisError.setProperty(
ErrorProperty.UNIMPLEMENTED_METHODS, missingOverridesArray);
_errorReporter.reportError(analysisError);
- return true;
}
/**
@@ -4591,15 +5145,13 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [StaticTypeWarningCode.NON_BOOL_CONDITION].
*/
- bool _checkForNonBoolCondition(Expression condition) {
+ void _checkForNonBoolCondition(Expression condition) {
DartType conditionType = getStaticType(condition);
if (conditionType != null &&
!_typeSystem.isAssignableTo(conditionType, _boolType)) {
_errorReporter.reportErrorForNode(
StaticTypeWarningCode.NON_BOOL_CONDITION, condition);
- return true;
}
- return false;
}
/**
@@ -4608,25 +5160,21 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [StaticTypeWarningCode.NON_BOOL_EXPRESSION].
*/
- bool _checkForNonBoolExpression(AssertStatement statement) {
+ void _checkForNonBoolExpression(AssertStatement statement) {
Expression expression = statement.condition;
DartType type = getStaticType(expression);
if (type is InterfaceType) {
if (!_typeSystem.isAssignableTo(type, _boolType)) {
_errorReporter.reportErrorForNode(
StaticTypeWarningCode.NON_BOOL_EXPRESSION, expression);
- return true;
}
} else if (type is FunctionType) {
- FunctionType functionType = type;
- if (functionType.typeArguments.length == 0 &&
- !_typeSystem.isAssignableTo(functionType.returnType, _boolType)) {
+ if (type.typeArguments.length == 0 &&
+ !_typeSystem.isAssignableTo(type.returnType, _boolType)) {
_errorReporter.reportErrorForNode(
StaticTypeWarningCode.NON_BOOL_EXPRESSION, expression);
- return true;
}
}
- return false;
}
/**
@@ -4634,15 +5182,13 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [StaticTypeWarningCode.NON_BOOL_NEGATION_EXPRESSION].
*/
- bool _checkForNonBoolNegationExpression(Expression expression) {
+ void _checkForNonBoolNegationExpression(Expression expression) {
DartType conditionType = getStaticType(expression);
if (conditionType != null &&
!_typeSystem.isAssignableTo(conditionType, _boolType)) {
_errorReporter.reportErrorForNode(
StaticTypeWarningCode.NON_BOOL_NEGATION_EXPRESSION, expression);
- return true;
}
- return false;
}
/**
@@ -4653,29 +5199,28 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT].
*/
- bool _checkForNonConstMapAsExpressionStatement(MapLiteral literal) {
+ void _checkForNonConstMapAsExpressionStatement(MapLiteral literal) {
// "const"
if (literal.constKeyword != null) {
- return false;
+ return;
}
// has type arguments
if (literal.typeArguments != null) {
- return false;
+ return;
}
// prepare statement
Statement statement =
literal.getAncestor((node) => node is ExpressionStatement);
if (statement == null) {
- return false;
+ return;
}
// OK, statement does not start with map
if (!identical(statement.beginToken, literal.beginToken)) {
- return false;
+ return;
}
- // report problem
+
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT, literal);
- return true;
}
/**
@@ -4684,11 +5229,11 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [StaticWarningCode.NON_VOID_RETURN_FOR_OPERATOR].
*/
- bool _checkForNonVoidReturnTypeForOperator(MethodDeclaration declaration) {
+ void _checkForNonVoidReturnTypeForOperator(MethodDeclaration declaration) {
// check that []= operator
SimpleIdentifier name = declaration.name;
if (name.name != "[]=") {
- return false;
+ return;
}
// check return type
TypeName typeName = declaration.returnType;
@@ -4699,8 +5244,6 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
StaticWarningCode.NON_VOID_RETURN_FOR_OPERATOR, typeName);
}
}
- // no warning
- return false;
}
/**
@@ -4709,7 +5252,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [StaticWarningCode.NON_VOID_RETURN_FOR_SETTER].
*/
- bool _checkForNonVoidReturnTypeForSetter(TypeName typeName) {
+ void _checkForNonVoidReturnTypeForSetter(TypeName typeName) {
if (typeName != null) {
DartType type = typeName.type;
if (type != null && !type.isVoid) {
@@ -4717,7 +5260,6 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
StaticWarningCode.NON_VOID_RETURN_FOR_SETTER, typeName);
}
}
- return false;
}
/**
@@ -4727,22 +5269,20 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.OPTIONAL_PARAMETER_IN_OPERATOR].
*/
- bool _checkForOptionalParameterInOperator(MethodDeclaration declaration) {
+ void _checkForOptionalParameterInOperator(MethodDeclaration declaration) {
FormalParameterList parameterList = declaration.parameters;
if (parameterList == null) {
- return false;
+ return;
}
- bool foundError = false;
+
NodeList<FormalParameter> formalParameters = parameterList.parameters;
for (FormalParameter formalParameter in formalParameters) {
if (formalParameter.kind.isOptional) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.OPTIONAL_PARAMETER_IN_OPERATOR,
formalParameter);
- foundError = true;
}
}
- return foundError;
}
/**
@@ -4750,20 +5290,19 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.PRIVATE_OPTIONAL_PARAMETER].
*/
- bool _checkForPrivateOptionalParameter(FormalParameter parameter) {
+ void _checkForPrivateOptionalParameter(FormalParameter parameter) {
// should be named parameter
if (parameter.kind != ParameterKind.NAMED) {
- return false;
+ return;
}
// name should start with '_'
SimpleIdentifier name = parameter.identifier;
if (name.isSynthetic || !StringUtilities.startsWithChar(name.name, 0x5F)) {
- return false;
+ return;
}
- // report problem
+
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.PRIVATE_OPTIONAL_PARAMETER, parameter);
- return true;
}
/**
@@ -4773,28 +5312,23 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.RECURSIVE_CONSTRUCTOR_REDIRECT].
*/
- bool _checkForRecursiveConstructorRedirect(ConstructorDeclaration declaration,
+ void _checkForRecursiveConstructorRedirect(ConstructorDeclaration declaration,
ConstructorElement constructorElement) {
// we check generative constructor here
if (declaration.factoryKeyword != null) {
- return false;
+ return;
}
- // try to find redirecting constructor invocation and analyzer it for
+ // try to find redirecting constructor invocation and analyze it for
// recursion
for (ConstructorInitializer initializer in declaration.initializers) {
if (initializer is RedirectingConstructorInvocation) {
- // OK if no cycle
- if (!_hasRedirectingFactoryConstructorCycle(constructorElement)) {
- return false;
+ if (_hasRedirectingFactoryConstructorCycle(constructorElement)) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.RECURSIVE_CONSTRUCTOR_REDIRECT, initializer);
}
- // report error
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.RECURSIVE_CONSTRUCTOR_REDIRECT, initializer);
- return true;
+ return;
}
}
- // OK, no redirecting constructor invocation
- return false;
}
/**
@@ -4830,12 +5364,12 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
* [CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_EXTENDS], and
* [CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEMENTS].
*/
- bool _checkForRecursiveInterfaceInheritance(ClassElement element) {
+ void _checkForRecursiveInterfaceInheritance(ClassElement element) {
if (element == null) {
- return false;
+ return;
}
- return _safeCheckForRecursiveInterfaceInheritance(
- element, new List<ClassElement>());
+
+ _safeCheckForRecursiveInterfaceInheritance(element, <ClassElement>[]);
}
/**
@@ -4849,21 +5383,18 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
* [CompileTimeErrorCode.SUPER_IN_REDIRECTING_CONSTRUCTOR], and
* [CompileTimeErrorCode.REDIRECT_GENERATIVE_TO_NON_GENERATIVE_CONSTRUCTOR].
*/
- bool _checkForRedirectingConstructorErrorCodes(
+ void _checkForRedirectingConstructorErrorCodes(
ConstructorDeclaration declaration) {
- bool errorReported = false;
- //
// Check for default values in the parameters
- //
ConstructorName redirectedConstructor = declaration.redirectedConstructor;
if (redirectedConstructor != null) {
for (FormalParameter parameter in declaration.parameters.parameters) {
if (parameter is DefaultFormalParameter &&
parameter.defaultValue != null) {
_errorReporter.reportErrorForNode(
- CompileTimeErrorCode.DEFAULT_VALUE_IN_REDIRECTING_FACTORY_CONSTRUCTOR,
+ CompileTimeErrorCode
+ .DEFAULT_VALUE_IN_REDIRECTING_FACTORY_CONSTRUCTOR,
parameter.identifier);
- errorReported = true;
}
}
}
@@ -4875,7 +5406,6 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.MULTIPLE_REDIRECTING_CONSTRUCTOR_INVOCATIONS,
initializer);
- errorReported = true;
}
if (declaration.factoryKeyword == null) {
RedirectingConstructorInvocation invocation = initializer;
@@ -4893,7 +5423,8 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
} else {
if (redirectingElement.isFactory) {
_errorReporter.reportErrorForNode(
- CompileTimeErrorCode.REDIRECT_GENERATIVE_TO_NON_GENERATIVE_CONSTRUCTOR,
+ CompileTimeErrorCode
+ .REDIRECT_GENERATIVE_TO_NON_GENERATIVE_CONSTRUCTOR,
initializer);
}
}
@@ -4908,18 +5439,14 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.SUPER_IN_REDIRECTING_CONSTRUCTOR,
initializer);
- errorReported = true;
}
if (initializer is ConstructorFieldInitializer) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR,
initializer);
- errorReported = true;
}
}
}
- // done
- return errorReported;
}
/**
@@ -4929,36 +5456,46 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.REDIRECT_TO_NON_CONST_CONSTRUCTOR].
*/
- bool _checkForRedirectToNonConstConstructor(
+ void _checkForRedirectToNonConstConstructor(
ConstructorDeclaration declaration, ConstructorElement element) {
// prepare redirected constructor
ConstructorName redirectedConstructorNode =
declaration.redirectedConstructor;
if (redirectedConstructorNode == null) {
- return false;
+ return;
}
// prepare element
if (element == null) {
- return false;
+ return;
}
// OK, it is not 'const'
if (!element.isConst) {
- return false;
+ return;
}
// prepare redirected constructor
ConstructorElement redirectedConstructor = element.redirectedConstructor;
if (redirectedConstructor == null) {
- return false;
+ return;
}
// OK, it is also 'const'
if (redirectedConstructor.isConst) {
- return false;
+ return;
}
- // report error
+
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.REDIRECT_TO_NON_CONST_CONSTRUCTOR,
redirectedConstructorNode);
- return true;
+ }
+
+ void _checkForReferenceBeforeDeclaration(SimpleIdentifier node) {
+ if (!node.inDeclarationContext() &&
+ _hiddenElements != null &&
+ _hiddenElements.contains(node.staticElement)) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION,
+ node,
+ [node.name]);
+ }
}
/**
@@ -4966,36 +5503,33 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH].
*/
- bool _checkForRethrowOutsideCatch(RethrowExpression expression) {
+ void _checkForRethrowOutsideCatch(RethrowExpression expression) {
if (!_isInCatchClause) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH, expression);
- return true;
}
- return false;
}
/**
- * Check that if the the given constructor [declaration] is generative, then
+ * Check that if the given constructor [declaration] is generative, then
* it does not have an expression function body.
*
* See [CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTRUCTOR].
*/
- bool _checkForReturnInGenerativeConstructor(
+ void _checkForReturnInGenerativeConstructor(
ConstructorDeclaration declaration) {
// ignore factory
if (declaration.factoryKeyword != null) {
- return false;
+ return;
}
// block body (with possible return statement) is checked elsewhere
FunctionBody body = declaration.body;
if (body is! ExpressionFunctionBody) {
- return false;
+ return;
}
- // report error
+
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTRUCTOR, body);
- return true;
}
/**
@@ -5007,23 +5541,23 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE].
*/
- bool _checkForReturnOfInvalidType(
+ void _checkForReturnOfInvalidType(
Expression returnExpression, DartType expectedReturnType) {
if (_enclosingFunction == null) {
- return false;
+ return;
}
if (_inGenerator) {
// "return expression;" is disallowed in generators, but this is checked
// elsewhere. Bare "return" is always allowed in generators regardless
// of the return type. So no need to do any further checking.
- return false;
+ return;
}
DartType staticReturnType = _computeReturnTypeForMethod(returnExpression);
if (expectedReturnType.isVoid) {
if (staticReturnType.isVoid ||
staticReturnType.isDynamic ||
staticReturnType.isBottom) {
- return false;
+ return;
}
_errorReporter.reportTypeErrorForNode(
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, returnExpression, [
@@ -5031,16 +5565,17 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
expectedReturnType,
_enclosingFunction.displayName
]);
- return true;
+ return;
}
- if (_typeSystem.isAssignableTo(staticReturnType, expectedReturnType)) {
- return false;
+ if (_expressionIsAssignableAtType(
+ returnExpression, staticReturnType, expectedReturnType)) {
+ return;
}
_errorReporter.reportTypeErrorForNode(
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE,
returnExpression,
[staticReturnType, expectedReturnType, _enclosingFunction.displayName]);
- return true;
+
// TODO(brianwilkerson) Define a hint corresponding to the warning and
// report it if appropriate.
// Type propagatedReturnType = returnExpression.getPropagatedType();
@@ -5058,31 +5593,33 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
}
/**
- * Check the given [typeReference] and that the [name] is not the reference to
+ * Check the given [typeReference] and that the [name] is not a reference to
* an instance member.
*
* See [StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER].
*/
- bool _checkForStaticAccessToInstanceMember(
+ void _checkForStaticAccessToInstanceMember(
ClassElement typeReference, SimpleIdentifier name) {
+ // OK, in comment
+ if (_isInComment) {
+ return;
+ }
// OK, target is not a type
if (typeReference == null) {
- return false;
+ return;
}
// prepare member Element
Element element = name.staticElement;
- if (element is! ExecutableElement) {
- return false;
- }
- ExecutableElement memberElement = element as ExecutableElement;
- // OK, static
- if (memberElement.isStatic) {
- return false;
+ if (element is ExecutableElement) {
+ // OK, static
+ if (element.isStatic) {
+ return;
+ }
+ _errorReporter.reportErrorForNode(
+ StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER,
+ name,
+ [name.name]);
}
- // report problem
- _errorReporter.reportErrorForNode(
- StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER, name, [name.name]);
- return true;
}
/**
@@ -5091,35 +5628,31 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [StaticWarningCode.SWITCH_EXPRESSION_NOT_ASSIGNABLE].
*/
- bool _checkForSwitchExpressionNotAssignable(SwitchStatement statement) {
+ void _checkForSwitchExpressionNotAssignable(SwitchStatement statement) {
// prepare 'switch' expression type
Expression expression = statement.expression;
DartType expressionType = getStaticType(expression);
if (expressionType == null) {
- return false;
+ return;
}
- // compare with type of the first 'case'
- NodeList<SwitchMember> members = statement.members;
- for (SwitchMember switchMember in members) {
- if (switchMember is! SwitchCase) {
- continue;
- }
- SwitchCase switchCase = switchMember as SwitchCase;
- // prepare 'case' type
- Expression caseExpression = switchCase.expression;
- DartType caseType = getStaticType(caseExpression);
- // check types
- if (_typeSystem.isAssignableTo(expressionType, caseType)) {
- return false;
- }
- // report problem
+
+ // compare with type of the first non-default 'case'
+ SwitchCase switchCase = statement.members
+ .firstWhere((member) => member is SwitchCase, orElse: () => null);
+ if (switchCase == null) {
+ return;
+ }
+
+ Expression caseExpression = switchCase.expression;
+ DartType caseType = getStaticType(caseExpression);
+
+ // check types
+ if (!_expressionIsAssignableAtType(expression, expressionType, caseType)) {
_errorReporter.reportErrorForNode(
StaticWarningCode.SWITCH_EXPRESSION_NOT_ASSIGNABLE,
expression,
[expressionType, caseType]);
- return true;
}
- return false;
}
/**
@@ -5128,15 +5661,12 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF].
*/
- bool _checkForTypeAliasCannotReferenceItself_function(
+ void _checkForTypeAliasCannotReferenceItself_function(
FunctionTypeAlias alias) {
- FunctionTypeAliasElement element = alias.element;
- if (!_hasTypedefSelfReference(element)) {
- return false;
+ if (_hasTypedefSelfReference(alias.element)) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, alias);
}
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, alias);
- return true;
}
/**
@@ -5144,12 +5674,11 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS].
*/
- bool _checkForTypeAnnotationDeferredClass(TypeName name) {
+ void _checkForTypeAnnotationDeferredClass(TypeName name) {
if (name != null && name.isDeferred) {
_errorReporter.reportErrorForNode(
StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, name, [name.name]);
}
- return false;
}
/**
@@ -5158,53 +5687,50 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS].
*/
- bool _checkForTypeArgumentNotMatchingBounds(TypeName typeName) {
+ void _checkForTypeArgumentNotMatchingBounds(TypeName typeName) {
if (typeName.typeArguments == null) {
- return false;
+ return;
}
// prepare Type
DartType type = typeName.type;
if (type == null) {
- return false;
+ return;
}
- // prepare ClassElement
Element element = type.element;
- if (element is! ClassElement) {
- return false;
- }
- ClassElement classElement = element as ClassElement;
- // prepare type parameters
- List<DartType> typeParameters = classElement.type.typeArguments;
- List<TypeParameterElement> boundingElts = classElement.typeParameters;
- // iterate over each bounded type parameter and corresponding argument
- NodeList<TypeName> typeNameArgList = typeName.typeArguments.arguments;
- List<DartType> typeArguments = (type as InterfaceType).typeArguments;
- int loopThroughIndex =
- math.min(typeNameArgList.length, boundingElts.length);
- bool foundError = false;
- for (int i = 0; i < loopThroughIndex; i++) {
- TypeName argTypeName = typeNameArgList[i];
- DartType argType = argTypeName.type;
- DartType boundType = boundingElts[i].bound;
- if (argType != null && boundType != null) {
- if (typeArguments.length != 0 &&
- typeArguments.length == typeParameters.length) {
- boundType = boundType.substitute2(typeArguments, typeParameters);
- }
- if (!_typeSystem.isSubtypeOf(argType, boundType)) {
- ErrorCode errorCode;
- if (_isInConstInstanceCreation) {
- errorCode = CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS;
- } else {
- errorCode = StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS;
+ if (element is ClassElement) {
+ // prepare type parameters
+ List<TypeParameterElement> parameterElements = element.typeParameters;
+ List<DartType> parameterTypes = element.type.typeArguments;
+ List<DartType> arguments = (type as ParameterizedType).typeArguments;
+ // iterate over each bounded type parameter and corresponding argument
+ NodeList<TypeName> typeNameArgList = typeName.typeArguments.arguments;
+ int loopThroughIndex =
+ math.min(typeNameArgList.length, parameterElements.length);
+ bool shouldSubstitute =
+ arguments.length != 0 && arguments.length == parameterTypes.length;
+ for (int i = 0; i < loopThroughIndex; i++) {
+ TypeName argTypeName = typeNameArgList[i];
+ DartType argType = argTypeName.type;
+ DartType boundType = parameterElements[i].bound;
+ if (argType != null && boundType != null) {
+ if (shouldSubstitute) {
+ boundType = boundType.substitute2(arguments, parameterTypes);
+ }
+ if (!_typeSystem.isSubtypeOf(argType, boundType)) {
+ ErrorCode errorCode;
+ if (_isInConstInstanceCreation) {
+ errorCode =
+ CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS;
+ } else {
+ errorCode =
+ StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS;
+ }
+ _errorReporter.reportTypeErrorForNode(
+ errorCode, argTypeName, [argType, boundType]);
}
- _errorReporter.reportTypeErrorForNode(
- errorCode, argTypeName, [argType, boundType]);
- foundError = true;
}
}
}
- return foundError;
}
/**
@@ -5213,16 +5739,18 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC].
*/
- bool _checkForTypeParameterReferencedByStatic(TypeName name) {
+ void _checkForTypeParameterReferencedByStatic(TypeName name) {
if (_isInStaticMethod || _isInStaticVariableDeclaration) {
DartType type = name.type;
- if (type is TypeParameterType) {
+ // The class's type parameters are not in scope for static methods.
+ // However all other type parameters are legal (e.g. the static method's
+ // type parameters, or a local function's type parameters).
+ if (type is TypeParameterType &&
+ type.element.enclosingElement is ClassElement) {
_errorReporter.reportErrorForNode(
StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC, name);
- return true;
}
}
- return false;
}
/**
@@ -5230,23 +5758,22 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND].
*/
- bool _checkForTypeParameterSupertypeOfItsBound(TypeParameter parameter) {
+ void _checkForTypeParameterSupertypeOfItsBound(TypeParameter parameter) {
TypeParameterElement element = parameter.element;
// prepare bound
DartType bound = element.bound;
if (bound == null) {
- return false;
+ return;
}
// OK, type parameter is not supertype of its bound
if (!bound.isMoreSpecificThan(element.type)) {
- return false;
+ return;
}
- // report problem
+
_errorReporter.reportErrorForNode(
StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND,
parameter,
[element.displayName]);
- return true;
}
/**
@@ -5258,40 +5785,36 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
* [CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR], and
* [StaticWarningCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT].
*/
- bool _checkForUndefinedConstructorInInitializerImplicit(
+ void _checkForUndefinedConstructorInInitializerImplicit(
ConstructorDeclaration constructor) {
if (_enclosingClass == null) {
- return false;
+ return;
}
// do nothing if mixin errors have already been reported for this class.
- ClassElementImpl enclosingClass = _enclosingClass;
- if (enclosingClass.doesMixinLackConstructors) {
- return false;
+ if (_enclosingClass.doesMixinLackConstructors) {
+ return;
}
- //
+
// Ignore if the constructor is not generative.
- //
if (constructor.factoryKeyword != null) {
- return false;
+ return;
}
- //
+
// Ignore if the constructor has either an implicit super constructor
// invocation or a redirecting constructor invocation.
- //
for (ConstructorInitializer constructorInitializer
in constructor.initializers) {
if (constructorInitializer is SuperConstructorInvocation ||
constructorInitializer is RedirectingConstructorInvocation) {
- return false;
+ return;
}
}
- //
+
// Check to see whether the superclass has a non-factory unnamed
// constructor.
- //
InterfaceType superType = _enclosingClass.supertype;
if (superType == null) {
- return false;
+ return;
}
ClassElement superElement = superType.element;
ConstructorElement superUnnamedConstructor =
@@ -5302,32 +5825,25 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR,
constructor.returnType,
[superUnnamedConstructor]);
- return true;
- }
- if (!superUnnamedConstructor.isDefaultConstructor ||
+ } else if (!superUnnamedConstructor.isDefaultConstructor ||
!_enclosingClass
.isSuperConstructorAccessible(superUnnamedConstructor)) {
- int offset;
- int length;
- {
- Identifier returnType = constructor.returnType;
- SimpleIdentifier name = constructor.name;
- offset = returnType.offset;
- length = (name != null ? name.end : returnType.end) - offset;
- }
+ Identifier returnType = constructor.returnType;
+ SimpleIdentifier name = constructor.name;
+ int offset = returnType.offset;
+ int length = (name != null ? name.end : returnType.end) - offset;
_errorReporter.reportErrorForOffset(
CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT,
offset,
length,
[superType.displayName]);
}
- return false;
+ } else {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT,
+ constructor.returnType,
+ [superElement.name]);
}
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT,
- constructor.returnType,
- [superElement.name]);
- return true;
}
/**
@@ -5336,28 +5852,30 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [StaticTypeWarningCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER].
*/
- bool _checkForUnqualifiedReferenceToNonLocalStaticMember(
+ void _checkForUnqualifiedReferenceToNonLocalStaticMember(
SimpleIdentifier name) {
Element element = name.staticElement;
if (element == null || element is TypeParameterElement) {
- return false;
+ return;
}
Element enclosingElement = element.enclosingElement;
+ if (identical(enclosingElement, _enclosingClass)) {
+ return;
+ }
+ if (identical(enclosingElement, _enclosingEnum)) {
+ return;
+ }
if (enclosingElement is! ClassElement) {
- return false;
+ return;
}
if ((element is MethodElement && !element.isStatic) ||
(element is PropertyAccessorElement && !element.isStatic)) {
- return false;
- }
- if (identical(enclosingElement, _enclosingClass)) {
- return false;
+ return;
}
_errorReporter.reportErrorForNode(
StaticTypeWarningCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER,
name,
[name.name]);
- return true;
}
void _checkForValidField(FieldFormalParameter parameter) {
@@ -5372,8 +5890,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
} else {
ParameterElement parameterElement = parameter.element;
if (parameterElement is FieldFormalParameterElementImpl) {
- FieldFormalParameterElementImpl fieldFormal = parameterElement;
- DartType declaredType = fieldFormal.type;
+ DartType declaredType = parameterElement.type;
DartType fieldType = fieldElement.type;
if (fieldElement.isSynthetic) {
_errorReporter.reportErrorForNode(
@@ -5419,14 +5936,13 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [StaticWarningCode.VOID_RETURN_FOR_GETTER].
*/
- bool _checkForVoidReturnType(MethodDeclaration getter) {
+ void _checkForVoidReturnType(MethodDeclaration getter) {
TypeName returnType = getter.returnType;
if (returnType == null || returnType.name.name != "void") {
- return false;
+ return;
}
_errorReporter.reportErrorForNode(
StaticWarningCode.VOID_RETURN_FOR_GETTER, returnType);
- return true;
}
/**
@@ -5438,18 +5954,18 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR].
*/
- bool _checkForWrongNumberOfParametersForOperator(
+ void _checkForWrongNumberOfParametersForOperator(
MethodDeclaration declaration) {
// prepare number of parameters
FormalParameterList parameterList = declaration.parameters;
if (parameterList == null) {
- return false;
+ return;
}
int numParameters = parameterList.parameters.length;
// prepare operator name
SimpleIdentifier nameNode = declaration.name;
if (nameNode == null) {
- return false;
+ return;
}
String name = nameNode.name;
// check for exact number of parameters
@@ -5481,18 +5997,12 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR,
nameNode,
[name, expected, numParameters]);
- return true;
- }
- // check for operator "-"
- if ("-" == name && numParameters > 1) {
+ } else if ("-" == name && numParameters > 1) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS,
nameNode,
[numParameters]);
- return true;
}
- // OK
- return false;
}
/**
@@ -5505,23 +6015,19 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER].
*/
- bool _checkForWrongNumberOfParametersForSetter(
+ void _checkForWrongNumberOfParametersForSetter(
SimpleIdentifier setterName, FormalParameterList parameterList) {
- if (setterName == null) {
- return false;
- }
- if (parameterList == null) {
- return false;
+ if (setterName == null || parameterList == null) {
+ return;
}
+
NodeList<FormalParameter> parameters = parameterList.parameters;
if (parameters.length != 1 ||
parameters[0].kind != ParameterKind.REQUIRED) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER,
setterName);
- return true;
}
- return false;
}
/**
@@ -5530,11 +6036,11 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* This method should only be called in generator functions.
*/
- bool _checkForYieldOfInvalidType(
+ void _checkForYieldOfInvalidType(
Expression yieldExpression, bool isYieldEach) {
assert(_inGenerator);
if (_enclosingFunction == null) {
- return false;
+ return;
}
DartType declaredReturnType = _enclosingFunction.returnType;
DartType staticYieldedType = getStaticType(yieldExpression);
@@ -5543,17 +6049,14 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
impliedReturnType = staticYieldedType;
} else if (_enclosingFunction.isAsynchronous) {
impliedReturnType =
- _typeProvider.streamType.substitute4(<DartType>[staticYieldedType]);
+ _typeProvider.streamType.instantiate(<DartType>[staticYieldedType]);
} else {
impliedReturnType =
- _typeProvider.iterableType.substitute4(<DartType>[staticYieldedType]);
+ _typeProvider.iterableType.instantiate(<DartType>[staticYieldedType]);
}
- if (!_typeSystem.isAssignableTo(impliedReturnType, declaredReturnType)) {
- _errorReporter.reportTypeErrorForNode(
- StaticTypeWarningCode.YIELD_OF_INVALID_TYPE,
- yieldExpression,
- [impliedReturnType, declaredReturnType]);
- return true;
+ if (!_checkForAssignableExpressionAtType(yieldExpression, impliedReturnType,
+ declaredReturnType, StaticTypeWarningCode.YIELD_OF_INVALID_TYPE)) {
+ return;
}
if (isYieldEach) {
// Since the declared return type might have been "dynamic", we need to
@@ -5570,10 +6073,9 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
StaticTypeWarningCode.YIELD_OF_INVALID_TYPE,
yieldExpression,
[impliedReturnType, requiredReturnType]);
- return true;
+ return;
}
}
- return false;
}
/**
@@ -5582,23 +6084,22 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [StaticWarningCode.FUNCTION_WITHOUT_CALL].
*/
- bool _checkImplementsFunctionWithoutCall(ClassDeclaration declaration) {
+ void _checkImplementsFunctionWithoutCall(ClassDeclaration declaration) {
if (declaration.isAbstract) {
- return false;
+ return;
}
ClassElement classElement = declaration.element;
if (classElement == null) {
- return false;
+ return;
}
if (!_typeSystem.isSubtypeOf(
classElement.type, _typeProvider.functionType)) {
- return false;
+ return;
}
// If there is a noSuchMethod method, then don't report the warning,
// see dartbug.com/16078
- if (classElement.getMethod(FunctionElement.NO_SUCH_METHOD_METHOD_NAME) !=
- null) {
- return false;
+ if (_enclosingClass.hasNoSuchMethod) {
+ return;
}
ExecutableElement callMethod = _inheritanceManager.lookupMember(
classElement, FunctionElement.CALL_METHOD_NAME);
@@ -5607,9 +6108,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
(callMethod as MethodElement).isAbstract) {
_errorReporter.reportErrorForNode(
StaticWarningCode.FUNCTION_WITHOUT_CALL, declaration.name);
- return true;
}
- return false;
}
/**
@@ -5618,30 +6117,103 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS].
*/
- bool _checkImplementsSuperClass(ClassDeclaration declaration) {
+ void _checkImplementsSuperClass(ClassDeclaration declaration) {
// prepare super type
InterfaceType superType = _enclosingClass.supertype;
if (superType == null) {
- return false;
+ return;
}
// prepare interfaces
ImplementsClause implementsClause = declaration.implementsClause;
if (implementsClause == null) {
- return false;
+ return;
}
// check interfaces
- bool hasProblem = false;
for (TypeName interfaceNode in implementsClause.interfaces) {
if (interfaceNode.type == superType) {
- hasProblem = true;
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS,
interfaceNode,
[superType.displayName]);
}
}
- // done
- return hasProblem;
+ }
+
+ /**
+ * Verify that the given [typeArguments] are all within their bounds, as
+ * defined by the given [element].
+ *
+ * See [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS].
+ */
+ void _checkTypeArguments(Element element, TypeArgumentList typeArguments,
+ [DartType targetType]) {
+ if (element == null || typeArguments == null) {
+ return;
+ }
+ void reportError(
+ TypeName argument, DartType argumentType, DartType parameterType) {
+ _errorReporter.reportTypeErrorForNode(
+ StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
+ argument,
+ [argumentType, parameterType]);
+ }
+
+ if (element is FunctionTypedElement) {
+ _checkTypeArgumentsAgainstBounds(
+ element.typeParameters, typeArguments, targetType, reportError);
+ } else if (element is ClassElement) {
+ _checkTypeArgumentsAgainstBounds(
+ element.typeParameters, typeArguments, targetType, reportError);
+ } else if (element is ParameterElement || element is LocalVariableElement) {
+ // TODO(brianwilkerson) Implement this case
+ } else {
+ print('Unhandled element type: ${element.runtimeType}');
+ }
+ }
+
+ void _checkTypeArgumentsAgainstBounds(
+ List<TypeParameterElement> typeParameters,
+ TypeArgumentList typeArgumentList,
+ DartType targetType,
+ void reportError(
+ TypeName argument, DartType argumentType, DartType parameterType)) {
+ NodeList<TypeName> typeArguments = typeArgumentList.arguments;
+ int argumentsLength = typeArguments.length;
+ int maxIndex = math.min(typeParameters.length, argumentsLength);
+
+ bool shouldSubstitute =
+ argumentsLength != 0 && argumentsLength == typeParameters.length;
+ List<DartType> argumentTypes = shouldSubstitute
+ ? typeArguments.map((TypeName typeName) => typeName.type).toList()
+ : null;
+ List<DartType> parameterTypes = shouldSubstitute
+ ? typeParameters
+ .map((TypeParameterElement element) => element.type)
+ .toList()
+ : null;
+ List<DartType> targetTypeParameterTypes = null;
+ for (int i = 0; i < maxIndex; i++) {
+ TypeName argTypeName = typeArguments[i];
+ DartType argType = argTypeName.type;
+ DartType boundType = typeParameters[i].bound;
+ if (argType != null && boundType != null) {
+ if (targetType is ParameterizedType) {
+ if (targetTypeParameterTypes == null) {
+ targetTypeParameterTypes = targetType.typeParameters
+ .map((TypeParameterElement element) => element.type)
+ .toList();
+ }
+ boundType = boundType.substitute2(
+ targetType.typeArguments, targetTypeParameterTypes);
+ }
+ if (shouldSubstitute) {
+ boundType = boundType.substitute2(argumentTypes, parameterTypes);
+ }
+ if (!_typeSystem.isSubtypeOf(argType, boundType)) {
+ reportError(argTypeName, argType, boundType);
+ }
+ }
+ }
}
DartType _computeReturnTypeForMethod(Expression returnExpression) {
@@ -5657,13 +6229,40 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
}
DartType staticReturnType = getStaticType(returnExpression);
if (staticReturnType != null && _enclosingFunction.isAsynchronous) {
- return _typeProvider.futureType.substitute4(<DartType>[
- StaticTypeAnalyzer.flattenFutures(_typeProvider, staticReturnType)
- ]);
+ return _typeProvider.futureType.instantiate(
+ <DartType>[staticReturnType.flattenFutures(_typeSystem)]);
}
return staticReturnType;
}
+ bool _expressionIsAssignableAtType(Expression expression,
+ DartType actualStaticType, DartType expectedStaticType) {
+ bool concrete = _options.strongMode && checker.isKnownFunction(expression);
+ if (concrete && actualStaticType is FunctionType) {
+ actualStaticType = _typeSystem.functionTypeToConcreteType(
+ _typeProvider, actualStaticType);
+ // TODO(leafp): Move the Downcast functionality here.
+ }
+ return _typeSystem.isAssignableTo(actualStaticType, expectedStaticType);
+ }
+
+ MethodElement _findOverriddenMemberThatMustCallSuper(MethodDeclaration node) {
+ ExecutableElement overriddenMember = _getOverriddenMember(node.element);
+ List<ExecutableElement> seen = <ExecutableElement>[];
+ while (
+ overriddenMember is MethodElement && !seen.contains(overriddenMember)) {
+ for (ElementAnnotation annotation in overriddenMember.metadata) {
+ if (annotation.isMustCallSuper) {
+ return overriddenMember;
+ }
+ }
+ seen.add(overriddenMember);
+ // Keep looking up the chain.
+ overriddenMember = _getOverriddenMember(overriddenMember);
+ }
+ return null;
+ }
+
/**
* Return the error code that should be used when the given class [element]
* references itself directly.
@@ -5671,15 +6270,18 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
ErrorCode _getBaseCaseErrorCode(ClassElement element) {
InterfaceType supertype = element.supertype;
if (supertype != null && _enclosingClass == supertype.element) {
- return CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_EXTENDS;
+ return CompileTimeErrorCode
+ .RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_EXTENDS;
}
List<InterfaceType> mixins = element.mixins;
for (int i = 0; i < mixins.length; i++) {
if (_enclosingClass == mixins[i].element) {
- return CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_WITH;
+ return CompileTimeErrorCode
+ .RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_WITH;
}
}
- return CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEMENTS;
+ return CompileTimeErrorCode
+ .RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEMENTS;
}
/**
@@ -5711,6 +6313,74 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
}
}
+ /**
+ * Return the name of the library that defines given [element].
+ */
+ String _getLibraryName(Element element) {
+ if (element == null) {
+ return StringUtilities.EMPTY;
+ }
+ LibraryElement library = element.library;
+ if (library == null) {
+ return StringUtilities.EMPTY;
+ }
+ List<ImportElement> imports = _currentLibrary.imports;
+ int count = imports.length;
+ for (int i = 0; i < count; i++) {
+ if (identical(imports[i].importedLibrary, library)) {
+ return library.definingCompilationUnit.displayName;
+ }
+ }
+ List<String> indirectSources = new List<String>();
+ for (int i = 0; i < count; i++) {
+ LibraryElement importedLibrary = imports[i].importedLibrary;
+ if (importedLibrary != null) {
+ for (LibraryElement exportedLibrary
+ in importedLibrary.exportedLibraries) {
+ if (identical(exportedLibrary, library)) {
+ indirectSources
+ .add(importedLibrary.definingCompilationUnit.displayName);
+ }
+ }
+ }
+ }
+ int indirectCount = indirectSources.length;
+ StringBuffer buffer = new StringBuffer();
+ buffer.write(library.definingCompilationUnit.displayName);
+ if (indirectCount > 0) {
+ buffer.write(" (via ");
+ if (indirectCount > 1) {
+ indirectSources.sort();
+ buffer.write(StringUtilities.printListOfQuotedNames(indirectSources));
+ } else {
+ buffer.write(indirectSources[0]);
+ }
+ buffer.write(")");
+ }
+ return buffer.toString();
+ }
+
+ ExecutableElement _getOverriddenMember(Element member) {
+ if (member == null) {
+ return null;
+ }
+ ClassElement classElement =
+ member.getAncestor((element) => element is ClassElement);
+ if (classElement == null) {
+ return null;
+ }
+ String name = member.name;
+ ClassElement superclass = classElement.supertype?.element;
+ while (superclass != null) {
+ ExecutableElement member = superclass.getMethod(name) ?? superclass.getGetter(name) ?? superclass.getSetter(name);
+ if (member != null) {
+ return member;
+ }
+ superclass = superclass.supertype?.element;
+ }
+ return null;
+ }
+
/**
* Return the type of the first and only parameter of the given [setter].
*/
@@ -5724,33 +6394,17 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
return setterParameters[0].type;
}
- /**
- * Given a list of [directives] that have the same prefix, generate an error
- * if there is more than one import and any of those imports is deferred.
- *
- * See [CompileTimeErrorCode.SHARED_DEFERRED_PREFIX].
- */
- bool _hasDeferredPrefixCollision(List<ImportDirective> directives) {
- bool foundError = false;
- int count = directives.length;
- if (count > 1) {
- for (int i = 0; i < count; i++) {
- sc.Token deferredToken = directives[i].deferredKeyword;
- if (deferredToken != null) {
- _errorReporter.reportErrorForToken(
- CompileTimeErrorCode.SHARED_DEFERRED_PREFIX, deferredToken);
- foundError = true;
- }
- }
- }
- return foundError;
- }
-
/**
* Return `true` if the given [constructor] redirects to itself, directly or
* indirectly.
*/
bool _hasRedirectingFactoryConstructorCycle(ConstructorElement constructor) {
+ ConstructorElement nonMember(ConstructorElement constructor) {
+ return constructor is ConstructorMember
+ ? constructor.baseElement
+ : constructor;
+ }
+
Set<ConstructorElement> constructors = new HashSet<ConstructorElement>();
ConstructorElement current = constructor;
while (current != null) {
@@ -5758,10 +6412,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
return identical(current, constructor);
}
constructors.add(current);
- current = current.redirectedConstructor;
- if (current is ConstructorMember) {
- current = (current as ConstructorMember).baseElement;
- }
+ current = nonMember(current.redirectedConstructor);
}
return false;
}
@@ -5773,7 +6424,8 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
bool _hasTypedefSelfReference(Element element) {
Set<Element> checked = new HashSet<Element>();
List<Element> toCheck = new List<Element>();
- GeneralizingElementVisitor_ErrorVerifier_hasTypedefSelfReference elementVisitor =
+ GeneralizingElementVisitor_ErrorVerifier_hasTypedefSelfReference
+ elementVisitor =
new GeneralizingElementVisitor_ErrorVerifier_hasTypedefSelfReference(
toCheck);
toCheck.add(element);
@@ -5835,22 +6487,21 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
String executableName = executableElement.name;
if (executableElement is MethodElement) {
foundElt = classElement.getMethod(executableName);
- if (foundElt != null && !(foundElt as MethodElement).isAbstract) {
+ if (foundElt != null && !foundElt.isAbstract) {
return true;
}
List<InterfaceType> mixins = classElement.mixins;
for (int i = 0; i < mixins.length && foundElt == null; i++) {
foundElt = mixins[i].getMethod(executableName);
}
- if (foundElt != null && !(foundElt as MethodElement).isAbstract) {
+ if (foundElt != null && !foundElt.isAbstract) {
return true;
}
} else if (executableElement is PropertyAccessorElement) {
- PropertyAccessorElement propertyAccessorElement = executableElement;
- if (propertyAccessorElement.isGetter) {
+ if (executableElement.isGetter) {
foundElt = classElement.getGetter(executableName);
}
- if (foundElt == null && propertyAccessorElement.isSetter) {
+ if (foundElt == null && executableElement.isSetter) {
foundElt = classElement.getSetter(executableName);
}
if (foundElt != null &&
@@ -5864,8 +6515,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
foundElt = mixins[i].getSetter(executableName);
}
}
- if (foundElt != null &&
- !(foundElt as PropertyAccessorElement).isAbstract) {
+ if (foundElt != null && !foundElt.isAbstract) {
return true;
}
}
@@ -5879,14 +6529,11 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
for (AstNode node = expression.parent; node != null; node = node.parent) {
if (node is CompilationUnit) {
return false;
- }
- if (node is ConstructorDeclaration) {
+ } else if (node is ConstructorDeclaration) {
return node.factoryKeyword == null;
- }
- if (node is ConstructorInitializer) {
+ } else if (node is ConstructorInitializer) {
return false;
- }
- if (node is MethodDeclaration) {
+ } else if (node is MethodDeclaration) {
return !node.isStatic;
}
}
@@ -5903,29 +6550,32 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
return true;
}
AstNode parent = identifier.parent;
- if (parent is ConstructorName ||
- parent is MethodInvocation ||
- parent is PropertyAccess ||
- parent is SuperConstructorInvocation) {
- return true;
+ if (parent is Annotation) {
+ return identical(parent.constructorName, identifier);
}
- if (parent is PrefixedIdentifier &&
- identical(parent.identifier, identifier)) {
- return true;
+ if (parent is CommentReference) {
+ return parent.newKeyword != null;
}
- if (parent is Annotation && identical(parent.constructorName, identifier)) {
- return true;
+ if (parent is ConstructorName) {
+ return identical(parent.name, identifier);
}
- if (parent is CommentReference) {
- CommentReference commentReference = parent;
- if (commentReference.newKeyword != null) {
- return true;
- }
+ if (parent is MethodInvocation) {
+ return identical(parent.methodName, identifier);
+ }
+ if (parent is PrefixedIdentifier) {
+ return identical(parent.identifier, identifier);
+ }
+ if (parent is PropertyAccess) {
+ return identical(parent.propertyName, identifier);
+ }
+ if (parent is SuperConstructorInvocation) {
+ return identical(parent.constructorName, identifier);
}
return false;
}
- bool _isUserDefinedObject(EvaluationResultImpl result) => result == null ||
+ bool _isUserDefinedObject(EvaluationResultImpl result) =>
+ result == null ||
(result.value != null && result.value.isUserDefinedObject);
/**
@@ -6037,6 +6687,12 @@ class GeneralizingElementVisitor_ErrorVerifier_hasTypedefSelfReference
return null;
}
+ @override
+ Object visitFunctionElement(FunctionElement element) {
+ _addTypeToCheck(element.returnType);
+ return super.visitFunctionElement(element);
+ }
+
@override
Object visitFunctionTypeAliasElement(FunctionTypeAliasElement element) {
_addTypeToCheck(element.returnType);
@@ -6063,10 +6719,186 @@ class GeneralizingElementVisitor_ErrorVerifier_hasTypedefSelfReference
toCheck.add(type.element);
// type arguments
if (type is InterfaceType) {
- InterfaceType interfaceType = type;
- for (DartType typeArgument in interfaceType.typeArguments) {
+ for (DartType typeArgument in type.typeArguments) {
_addTypeToCheck(typeArgument);
}
}
}
}
+
+/**
+ * A record of the elements that will be declared in some scope (block), but are
+ * not yet declared.
+ */
+class HiddenElements {
+ /**
+ * The elements hidden in outer scopes, or `null` if this is the outermost
+ * scope.
+ */
+ final HiddenElements outerElements;
+
+ /**
+ * A set containing the elements that will be declared in this scope, but are
+ * not yet declared.
+ */
+ Set<Element> _elements = new HashSet<Element>();
+
+ /**
+ * Initialize a newly created set of hidden elements to include all of the
+ * elements defined in the set of [outerElements] and all of the elements
+ * declared in the given [block].
+ */
+ HiddenElements(this.outerElements, Block block) {
+ _initializeElements(block);
+ }
+
+ /**
+ * Return `true` if this set of elements contains the given [element].
+ */
+ bool contains(Element element) {
+ if (_elements.contains(element)) {
+ return true;
+ } else if (outerElements != null) {
+ return outerElements.contains(element);
+ }
+ return false;
+ }
+
+ /**
+ * Record that the given [element] has been declared, so it is no longer
+ * hidden.
+ */
+ void declare(Element element) {
+ _elements.remove(element);
+ }
+
+ /**
+ * Initialize the list of elements that are not yet declared to be all of the
+ * elements declared somewhere in the given [block].
+ */
+ void _initializeElements(Block block) {
+ _elements.addAll(BlockScope.elementsInBlock(block));
+ }
+}
+
+/**
+ * A class used to compute a list of the constants whose value needs to be
+ * computed before errors can be computed by the [VerifyUnitTask].
+ */
+class RequiredConstantsComputer extends RecursiveAstVisitor {
+ /**
+ * The source with which any pending errors will be associated.
+ */
+ final Source source;
+
+ /**
+ * A list of the pending errors that were computed.
+ */
+ final List<PendingError> pendingErrors = <PendingError>[];
+
+ /**
+ * A list of the constants whose value needs to be computed before the pending
+ * errors can be used to compute an analysis error.
+ */
+ final List<ConstantEvaluationTarget> requiredConstants =
+ <ConstantEvaluationTarget>[];
+
+ /**
+ * Initialize a newly created computer to compute required constants within
+ * the given [source].
+ */
+ RequiredConstantsComputer(this.source);
+
+ @override
+ Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
+ _checkForMissingRequiredParam(
+ node.staticInvokeType, node.argumentList, node);
+ return super.visitFunctionExpressionInvocation(node);
+ }
+
+ @override
+ Object visitInstanceCreationExpression(InstanceCreationExpression node) {
+ DartType type = node.constructorName.type.type;
+ if (type is InterfaceType) {
+ _checkForMissingRequiredParam(
+ node.staticElement?.type, node.argumentList, node.constructorName);
+ }
+ return super.visitInstanceCreationExpression(node);
+ }
+
+ @override
+ Object visitMethodInvocation(MethodInvocation node) {
+ _checkForMissingRequiredParam(
+ node.staticInvokeType, node.argumentList, node.methodName);
+ return super.visitMethodInvocation(node);
+ }
+
+ @override
+ Object visitRedirectingConstructorInvocation(
+ RedirectingConstructorInvocation node) {
+ DartType type = node.staticElement?.type;
+ if (type != null) {
+ _checkForMissingRequiredParam(type, node.argumentList, node);
+ }
+ return super.visitRedirectingConstructorInvocation(node);
+ }
+
+ @override
+ Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
+ DartType type = node.staticElement?.type;
+ if (type != null) {
+ _checkForMissingRequiredParam(type, node.argumentList, node);
+ }
+ return super.visitSuperConstructorInvocation(node);
+ }
+
+ void _checkForMissingRequiredParam(
+ DartType type, ArgumentList argumentList, AstNode node) {
+ if (type is FunctionType) {
+ for (ParameterElement parameter in type.parameters) {
+ if (parameter.parameterKind == ParameterKind.NAMED) {
+ ElementAnnotationImpl annotation = _getRequiredAnnotation(parameter);
+ if (annotation != null) {
+ String parameterName = parameter.name;
+ if (!_containsNamedExpression(argumentList, parameterName)) {
+ requiredConstants.add(annotation);
+ pendingErrors.add(new PendingMissingRequiredParameterError(
+ source, parameterName, node, annotation));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ bool _containsNamedExpression(ArgumentList args, String name) {
+ NodeList<Expression> arguments = args.arguments;
+ for (int i = arguments.length - 1; i >= 0; i--) {
+ Expression expression = arguments[i];
+ if (expression is NamedExpression) {
+ if (expression.name.label.name == name) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ ElementAnnotationImpl _getRequiredAnnotation(ParameterElement param) => param
+ .metadata
+ .firstWhere((ElementAnnotation e) => e.isRequired, orElse: () => null);
+}
+
+/**
+ * Recursively visits an AST, looking for method invocations.
+ */
+class _InvocationCollector extends RecursiveAstVisitor {
+ final List<String> superCalls = <String>[];
+
+ @override
+ visitMethodInvocation(MethodInvocation node) {
+ if (node.target is SuperExpression) {
+ superCalls.add(node.methodName.name);
+ }
+ }
+}
« no previous file with comments | « packages/analyzer/lib/src/generated/error.dart ('k') | packages/analyzer/lib/src/generated/html.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698