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

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

Issue 2290373003: Move error checking from scope creation to error reporter (take 2) (Closed)
Patch Set: Created 4 years, 4 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
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.
*
« no previous file with comments | « pkg/analyzer/lib/src/dart/resolver/scope.dart ('k') | pkg/analyzer/test/generated/compile_time_error_code_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698