| Index: pkg/analyzer/lib/src/generated/error_verifier.dart
|
| diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
|
| index 4e2de26ef741e7e097642f627009fe7a94ade766..abf47ca9ce73580466b2de0f6a13854fe26e50e1 100644
|
| --- a/pkg/analyzer/lib/src/generated/error_verifier.dart
|
| +++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
|
| @@ -387,6 +387,12 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
|
| }
|
|
|
| @override
|
| + Object visitBlock(Block node) {
|
| + _checkDuplicateDeclarationInStatements(node.statements);
|
| + return super.visitBlock(node);
|
| + }
|
| +
|
| + @override
|
| Object visitBlockFunctionBody(BlockFunctionBody node) {
|
| bool wasInAsync = _inAsync;
|
| bool wasInGenerator = _inGenerator;
|
| @@ -426,6 +432,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
|
|
|
| @override
|
| Object visitCatchClause(CatchClause node) {
|
| + _checkDuplicateDefinitionInCatchClause(node);
|
| bool previousIsInCatchClause = _isInCatchClause;
|
| try {
|
| _isInCatchClause = true;
|
| @@ -442,14 +449,15 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
|
| try {
|
| _isInNativeClass = node.nativeClause != null;
|
| _enclosingClass = AbstractClassElementImpl.getImpl(node.element);
|
| - ExtendsClause extendsClause = node.extendsClause;
|
| - ImplementsClause implementsClause = node.implementsClause;
|
| - WithClause withClause = node.withClause;
|
| + _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 ||
|
| @@ -544,6 +552,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
|
|
|
| @override
|
| Object visitCompilationUnit(CompilationUnit node) {
|
| + _checkDuplicateUnitMembers(node);
|
| _checkForDeferredPrefixCollisions(node);
|
| return super.visitCompilationUnit(node);
|
| }
|
| @@ -633,6 +642,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
|
| ClassElement outerEnum = _enclosingEnum;
|
| try {
|
| _enclosingEnum = node.element;
|
| + _checkDuplicateEnumMembers(node);
|
| return super.visitEnumDeclaration(node);
|
| } finally {
|
| _enclosingEnum = outerEnum;
|
| @@ -719,10 +729,19 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
|
| }
|
|
|
| @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);
|
| }
|
|
|
| @@ -1110,6 +1129,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);
|
| _checkForCaseBlocksNotTerminated(node);
|
| @@ -1162,6 +1193,12 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
|
| }
|
|
|
| @override
|
| + Object visitTypeParameterList(TypeParameterList node) {
|
| + _checkDuplicateDefinitionInTypeParameterList(node);
|
| + return super.visitTypeParameterList(node);
|
| + }
|
| +
|
| + @override
|
| Object visitVariableDeclaration(VariableDeclaration node) {
|
| SimpleIdentifier nameNode = node.name;
|
| Expression initializerNode = node.initializer;
|
| @@ -1259,6 +1296,222 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
|
| }
|
|
|
| /**
|
| + * 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.
|
| *
|
|
|