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

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

Issue 2406863003: Move class DeclarationResolver to its own file. (Closed)
Patch Set: Created 4 years, 2 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 | « pkg/analyzer/lib/src/dart/element/utilities.dart ('k') | pkg/analyzer/lib/src/generated/resolver.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analyzer/lib/src/generated/declaration_resolver.dart
diff --git a/pkg/analyzer/lib/src/generated/declaration_resolver.dart b/pkg/analyzer/lib/src/generated/declaration_resolver.dart
new file mode 100644
index 0000000000000000000000000000000000000000..bc34f2a1c1fb8cf23ac76043add64d3b0ac1d8c2
--- /dev/null
+++ b/pkg/analyzer/lib/src/generated/declaration_resolver.dart
@@ -0,0 +1,729 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// 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 analyzer.src.generated.declaration_resolver;
+
+import 'dart:collection';
+
+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/visitor.dart';
+import 'package:analyzer/exception/exception.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+
+/**
+ * A visitor that resolves declarations in an AST structure to already built
+ * elements.
+ *
+ * The resulting AST must have everything resolved that would have been resolved
+ * by a [CompilationUnitBuilder] (that is, must be a valid [RESOLVED_UNIT1]).
+ * This class must not assume that the [CompilationUnitElement] passed to it is
+ * any more complete than a [COMPILATION_UNIT_ELEMENT].
+ */
+class DeclarationResolver extends RecursiveAstVisitor<Object>
+ with _ExistingElementResolver {
+ /**
+ * The elements that are reachable from the compilation unit element. When a
+ * compilation unit has been resolved, this set should be empty.
+ */
+ Set<Element> _expectedElements;
+
+ /**
+ * The function type alias containing the AST nodes being visited, or `null`
+ * if we are not in the scope of a function type alias.
+ */
+ FunctionTypeAliasElement _enclosingAlias;
+
+ /**
+ * The class containing the AST nodes being visited, or `null` if we are not
+ * in the scope of a class.
+ */
+ ClassElement _enclosingClass;
+
+ /**
+ * The method or function containing the AST nodes being visited, or `null` if
+ * we are not in the scope of a method or function.
+ */
+ ExecutableElement _enclosingExecutable;
+
+ /**
+ * The parameter containing the AST nodes being visited, or `null` if we are
+ * not in the scope of a parameter.
+ */
+ ParameterElement _enclosingParameter;
+
+ /**
+ * Resolve the declarations within the given compilation [unit] to the
+ * elements rooted at the given [element]. Throw an [ElementMismatchException]
+ * if the element model and compilation unit do not match each other.
+ */
+ void resolve(CompilationUnit unit, CompilationUnitElement element) {
+ _ElementGatherer gatherer = new _ElementGatherer();
+ element.accept(gatherer);
+ _expectedElements = gatherer.elements;
+ _enclosingUnit = element;
+ _expectedElements.remove(element);
+ unit.element = element;
+ unit.accept(this);
+ _validateResolution();
+ }
+
+ @override
+ Object visitCatchClause(CatchClause node) {
+ SimpleIdentifier exceptionParameter = node.exceptionParameter;
+ if (exceptionParameter != null) {
+ List<LocalVariableElement> localVariables =
+ _enclosingExecutable.localVariables;
+ _findIdentifier(localVariables, exceptionParameter);
+ SimpleIdentifier stackTraceParameter = node.stackTraceParameter;
+ if (stackTraceParameter != null) {
+ _findIdentifier(localVariables, stackTraceParameter);
+ }
+ }
+ return super.visitCatchClause(node);
+ }
+
+ @override
+ Object visitClassDeclaration(ClassDeclaration node) {
+ ClassElement outerClass = _enclosingClass;
+ try {
+ SimpleIdentifier className = node.name;
+ _enclosingClass = _findIdentifier(_enclosingUnit.types, className);
+ super.visitClassDeclaration(node);
+ _resolveMetadata(node, node.metadata, _enclosingClass);
+ return null;
+ } finally {
+ _enclosingClass = outerClass;
+ }
+ }
+
+ @override
+ Object visitClassTypeAlias(ClassTypeAlias node) {
+ ClassElement outerClass = _enclosingClass;
+ try {
+ SimpleIdentifier className = node.name;
+ _enclosingClass = _findIdentifier(_enclosingUnit.types, className);
+ super.visitClassTypeAlias(node);
+ _resolveMetadata(node, node.metadata, _enclosingClass);
+ return null;
+ } finally {
+ _enclosingClass = outerClass;
+ }
+ }
+
+ @override
+ Object visitConstructorDeclaration(ConstructorDeclaration node) {
+ ExecutableElement outerExecutable = _enclosingExecutable;
+ try {
+ SimpleIdentifier constructorName = node.name;
+ if (constructorName == null) {
+ _enclosingExecutable = _enclosingClass.unnamedConstructor;
+ if (_enclosingExecutable == null) {
+ _mismatch('Could not find default constructor', node);
+ }
+ } else {
+ _enclosingExecutable =
+ _enclosingClass.getNamedConstructor(constructorName.name);
+ if (_enclosingExecutable == null) {
+ _mismatch(
+ 'Could not find constructor element with name "${constructorName.name}',
+ node);
+ }
+ constructorName.staticElement = _enclosingExecutable;
+ }
+ _expectedElements.remove(_enclosingExecutable);
+ node.element = _enclosingExecutable as ConstructorElement;
+ super.visitConstructorDeclaration(node);
+ _resolveMetadata(node, node.metadata, _enclosingExecutable);
+ return null;
+ } finally {
+ _enclosingExecutable = outerExecutable;
+ }
+ }
+
+ @override
+ Object visitDeclaredIdentifier(DeclaredIdentifier node) {
+ SimpleIdentifier variableName = node.identifier;
+ Element element =
+ _findIdentifier(_enclosingExecutable.localVariables, variableName);
+ super.visitDeclaredIdentifier(node);
+ _resolveMetadata(node, node.metadata, element);
+ return null;
+ }
+
+ @override
+ Object visitDefaultFormalParameter(DefaultFormalParameter node) {
+ SimpleIdentifier parameterName = node.parameter.identifier;
+ ParameterElement element = _getElementForParameter(node, parameterName);
+ Expression defaultValue = node.defaultValue;
+ if (defaultValue != null) {
+ ExecutableElement outerExecutable = _enclosingExecutable;
+ try {
+ _enclosingExecutable = element.initializer;
+ defaultValue.accept(this);
+ } finally {
+ _enclosingExecutable = outerExecutable;
+ }
+ }
+ ParameterElement outerParameter = _enclosingParameter;
+ try {
+ _enclosingParameter = element;
+ super.visitDefaultFormalParameter(node);
+ _resolveMetadata(node, node.metadata, element);
+ return null;
+ } finally {
+ _enclosingParameter = outerParameter;
+ }
+ }
+
+ @override
+ Object visitEnumDeclaration(EnumDeclaration node) {
+ ClassElement enclosingEnum =
+ _findIdentifier(_enclosingUnit.enums, node.name);
+ List<FieldElement> constants = enclosingEnum.fields;
+ for (EnumConstantDeclaration constant in node.constants) {
+ _findIdentifier(constants, constant.name);
+ }
+ super.visitEnumDeclaration(node);
+ _resolveMetadata(node, node.metadata, enclosingEnum);
+ return null;
+ }
+
+ @override
+ Object visitExportDirective(ExportDirective node) {
+ super.visitExportDirective(node);
+ _resolveAnnotations(
+ node, node.metadata, _enclosingUnit.getAnnotations(node.offset));
+ return null;
+ }
+
+ @override
+ Object visitFieldDeclaration(FieldDeclaration node) {
+ super.visitFieldDeclaration(node);
+ _resolveMetadata(node, node.metadata, node.fields.variables[0].element);
+ return null;
+ }
+
+ @override
+ Object visitFieldFormalParameter(FieldFormalParameter node) {
+ if (node.parent is! DefaultFormalParameter) {
+ SimpleIdentifier parameterName = node.identifier;
+ ParameterElement element = _getElementForParameter(node, parameterName);
+ ParameterElement outerParameter = _enclosingParameter;
+ try {
+ _enclosingParameter = element;
+ super.visitFieldFormalParameter(node);
+ _resolveMetadata(node, node.metadata, element);
+ return null;
+ } finally {
+ _enclosingParameter = outerParameter;
+ }
+ } else {
+ return super.visitFieldFormalParameter(node);
+ }
+ }
+
+ @override
+ Object visitFunctionDeclaration(FunctionDeclaration node) {
+ ExecutableElement outerExecutable = _enclosingExecutable;
+ try {
+ SimpleIdentifier functionName = node.name;
+ Token property = node.propertyKeyword;
+ if (property == null) {
+ if (_enclosingExecutable != null) {
+ _enclosingExecutable =
+ _findIdentifier(_enclosingExecutable.functions, functionName);
+ } else {
+ _enclosingExecutable =
+ _findIdentifier(_enclosingUnit.functions, functionName);
+ }
+ } else {
+ if (_enclosingExecutable != null) {
+ _enclosingExecutable =
+ _findIdentifier(_enclosingExecutable.functions, functionName);
+ } else {
+ List<PropertyAccessorElement> accessors;
+ if (_enclosingClass != null) {
+ accessors = _enclosingClass.accessors;
+ } else {
+ accessors = _enclosingUnit.accessors;
+ }
+ PropertyAccessorElement accessor;
+ if (property.keyword == Keyword.GET) {
+ accessor = _findIdentifier(accessors, functionName);
+ } else if (property.keyword == Keyword.SET) {
+ accessor = _findWithNameAndOffset(accessors, functionName,
+ functionName.name + '=', functionName.offset);
+ _expectedElements.remove(accessor);
+ functionName.staticElement = accessor;
+ }
+ _enclosingExecutable = accessor;
+ }
+ }
+ node.functionExpression.element = _enclosingExecutable;
+ super.visitFunctionDeclaration(node);
+ _resolveMetadata(node, node.metadata, _enclosingExecutable);
+ return null;
+ } finally {
+ _enclosingExecutable = outerExecutable;
+ }
+ }
+
+ @override
+ Object visitFunctionExpression(FunctionExpression node) {
+ if (node.parent is! FunctionDeclaration) {
+ FunctionElement element = _findAtOffset(
+ _enclosingExecutable.functions, node, node.beginToken.offset);
+ _expectedElements.remove(element);
+ node.element = element;
+ }
+ ExecutableElement outerExecutable = _enclosingExecutable;
+ try {
+ _enclosingExecutable = node.element;
+ return super.visitFunctionExpression(node);
+ } finally {
+ _enclosingExecutable = outerExecutable;
+ }
+ }
+
+ @override
+ Object visitFunctionTypeAlias(FunctionTypeAlias node) {
+ FunctionTypeAliasElement outerAlias = _enclosingAlias;
+ try {
+ SimpleIdentifier aliasName = node.name;
+ _enclosingAlias =
+ _findIdentifier(_enclosingUnit.functionTypeAliases, aliasName);
+ super.visitFunctionTypeAlias(node);
+ _resolveMetadata(node, node.metadata, _enclosingAlias);
+ return null;
+ } finally {
+ _enclosingAlias = outerAlias;
+ }
+ }
+
+ @override
+ Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
+ if (node.parent is! DefaultFormalParameter) {
+ SimpleIdentifier parameterName = node.identifier;
+ ParameterElement element = _getElementForParameter(node, parameterName);
+ ParameterElement outerParameter = _enclosingParameter;
+ try {
+ _enclosingParameter = element;
+ super.visitFunctionTypedFormalParameter(node);
+ _resolveMetadata(node, node.metadata, _enclosingParameter);
+ return null;
+ } finally {
+ _enclosingParameter = outerParameter;
+ }
+ } else {
+ return super.visitFunctionTypedFormalParameter(node);
+ }
+ }
+
+ @override
+ Object visitImportDirective(ImportDirective node) {
+ super.visitImportDirective(node);
+ _resolveAnnotations(
+ node, node.metadata, _enclosingUnit.getAnnotations(node.offset));
+ return null;
+ }
+
+ @override
+ Object visitLabeledStatement(LabeledStatement node) {
+ for (Label label in node.labels) {
+ SimpleIdentifier labelName = label.label;
+ _findIdentifier(_enclosingExecutable.labels, labelName);
+ }
+ return super.visitLabeledStatement(node);
+ }
+
+ @override
+ Object visitLibraryDirective(LibraryDirective node) {
+ super.visitLibraryDirective(node);
+ _resolveAnnotations(
+ node, node.metadata, _enclosingUnit.getAnnotations(node.offset));
+ return null;
+ }
+
+ @override
+ Object visitMethodDeclaration(MethodDeclaration node) {
+ ExecutableElement outerExecutable = _enclosingExecutable;
+ try {
+ Token property = node.propertyKeyword;
+ SimpleIdentifier methodName = node.name;
+ String nameOfMethod = methodName.name;
+ if (property == null) {
+ String elementName = nameOfMethod == '-' &&
+ node.parameters != null &&
+ node.parameters.parameters.isEmpty
+ ? 'unary-'
+ : nameOfMethod;
+ _enclosingExecutable = _findWithNameAndOffset(_enclosingClass.methods,
+ methodName, elementName, methodName.offset);
+ _expectedElements.remove(_enclosingExecutable);
+ methodName.staticElement = _enclosingExecutable;
+ } else {
+ PropertyAccessorElement accessor;
+ if (property.keyword == Keyword.GET) {
+ accessor = _findIdentifier(_enclosingClass.accessors, methodName);
+ } else if (property.keyword == Keyword.SET) {
+ accessor = _findWithNameAndOffset(_enclosingClass.accessors,
+ methodName, nameOfMethod + '=', methodName.offset);
+ _expectedElements.remove(accessor);
+ methodName.staticElement = accessor;
+ }
+ _enclosingExecutable = accessor;
+ }
+ super.visitMethodDeclaration(node);
+ _resolveMetadata(node, node.metadata, _enclosingExecutable);
+ return null;
+ } finally {
+ _enclosingExecutable = outerExecutable;
+ }
+ }
+
+ @override
+ Object visitPartDirective(PartDirective node) {
+ super.visitPartDirective(node);
+ _resolveAnnotations(
+ node, node.metadata, _enclosingUnit.getAnnotations(node.offset));
+ return null;
+ }
+
+ @override
+ Object visitPartOfDirective(PartOfDirective node) {
+ node.element = _enclosingUnit.library;
+ return super.visitPartOfDirective(node);
+ }
+
+ @override
+ Object visitSimpleFormalParameter(SimpleFormalParameter node) {
+ if (node.parent is! DefaultFormalParameter) {
+ SimpleIdentifier parameterName = node.identifier;
+ ParameterElement element = _getElementForParameter(node, parameterName);
+ ParameterElement outerParameter = _enclosingParameter;
+ try {
+ _enclosingParameter = element;
+ super.visitSimpleFormalParameter(node);
+ _resolveMetadata(node, node.metadata, element);
+ return null;
+ } finally {
+ _enclosingParameter = outerParameter;
+ }
+ } else {}
+ return super.visitSimpleFormalParameter(node);
+ }
+
+ @override
+ Object visitSwitchCase(SwitchCase node) {
+ for (Label label in node.labels) {
+ SimpleIdentifier labelName = label.label;
+ _findIdentifier(_enclosingExecutable.labels, labelName);
+ }
+ return super.visitSwitchCase(node);
+ }
+
+ @override
+ Object visitSwitchDefault(SwitchDefault node) {
+ for (Label label in node.labels) {
+ SimpleIdentifier labelName = label.label;
+ _findIdentifier(_enclosingExecutable.labels, labelName);
+ }
+ return super.visitSwitchDefault(node);
+ }
+
+ @override
+ Object visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+ super.visitTopLevelVariableDeclaration(node);
+ _resolveMetadata(node, node.metadata, node.variables.variables[0].element);
+ return null;
+ }
+
+ @override
+ Object visitTypeParameter(TypeParameter node) {
+ SimpleIdentifier parameterName = node.name;
+ Element element = null;
+ if (_enclosingExecutable != null) {
+ element = _findIdentifier(
+ _enclosingExecutable.typeParameters, parameterName,
+ required: false);
+ }
+ if (element == null) {
+ if (_enclosingClass != null) {
+ element =
+ _findIdentifier(_enclosingClass.typeParameters, parameterName);
+ } else if (_enclosingAlias != null) {
+ element =
+ _findIdentifier(_enclosingAlias.typeParameters, parameterName);
+ }
+ }
+ if (element == null) {
+ String name = parameterName.name;
+ int offset = parameterName.offset;
+ _mismatch(
+ 'Could not find type parameter with name "$name" at $offset', node);
+ }
+ super.visitTypeParameter(node);
+ _resolveMetadata(node, node.metadata, element);
+ return null;
+ }
+
+ @override
+ Object visitVariableDeclaration(VariableDeclaration node) {
+ VariableElement element = null;
+ SimpleIdentifier variableName = node.name;
+ if (_enclosingExecutable != null) {
+ element = _findIdentifier(
+ _enclosingExecutable.localVariables, variableName,
+ required: false);
+ }
+ if (element == null && _enclosingClass != null) {
+ element = _findIdentifier(_enclosingClass.fields, variableName,
+ required: false);
+ }
+ if (element == null && _enclosingUnit != null) {
+ element = _findIdentifier(_enclosingUnit.topLevelVariables, variableName);
+ }
+ Expression initializer = node.initializer;
+ if (initializer != null) {
+ ExecutableElement outerExecutable = _enclosingExecutable;
+ try {
+ _enclosingExecutable = element.initializer;
+ return super.visitVariableDeclaration(node);
+ } finally {
+ _enclosingExecutable = outerExecutable;
+ }
+ }
+ return super.visitVariableDeclaration(node);
+ }
+
+ @override
+ Object visitVariableDeclarationList(VariableDeclarationList node) {
+ super.visitVariableDeclarationList(node);
+ if (node.parent is! FieldDeclaration &&
+ node.parent is! TopLevelVariableDeclaration) {
+ _resolveMetadata(node, node.metadata, node.variables[0].element);
+ }
+ return null;
+ }
+
+ /**
+ * Return the element in the given list of [elements] that was created for the
+ * declaration at the given [offset]. Throw an [ElementMismatchException] if
+ * an element at that offset cannot be found.
+ *
+ * This method should only be used when there is no name associated with the
+ * node.
+ */
+ Element _findAtOffset(List<Element> elements, AstNode node, int offset) =>
+ _findWithNameAndOffset(elements, node, '', offset);
+
+ /**
+ * Return the element in the given list of [elements] that was created for the
+ * declaration with the given [identifier]. As a side-effect, associate the
+ * returned element with the identifier. Throw an [ElementMismatchException]
+ * if an element corresponding to the identifier cannot be found unless
+ * [required] is `false`, in which case return `null`.
+ */
+ Element _findIdentifier(List<Element> elements, SimpleIdentifier identifier,
+ {bool required: true}) {
+ Element element = _findWithNameAndOffset(
+ elements, identifier, identifier.name, identifier.offset,
+ required: required);
+ _expectedElements.remove(element);
+ identifier.staticElement = element;
+ return element;
+ }
+
+ /**
+ * Return the element in the given list of [elements] that was created for the
+ * declaration with the given [name] at the given [offset]. Throw an
+ * [ElementMismatchException] if an element corresponding to the identifier
+ * cannot be found unless [required] is `false`, in which case return `null`.
+ */
+ Element _findWithNameAndOffset(
+ List<Element> elements, AstNode node, String name, int offset,
+ {bool required: true}) {
+ int length = elements.length;
+ for (int i = 0; i < length; i++) {
+ Element element = elements[i];
+ if (element.nameOffset == offset && element.name == name) {
+ return element;
+ }
+ }
+ if (!required) {
+ return null;
+ }
+ for (int i = 0; i < length; i++) {
+ Element element = elements[i];
+ if (element.name == name) {
+ _mismatch(
+ 'Found element with name "$name" at ${element.nameOffset}, '
+ 'but expected offset of $offset',
+ node);
+ }
+ if (element.nameOffset == offset) {
+ _mismatch(
+ 'Found element with name "${element.name}" at $offset, '
+ 'but expected element with name "$name"',
+ node);
+ }
+ }
+ _mismatch('Could not find element with name "$name" at $offset', node);
+ return null; // Never reached
+ }
+
+ /**
+ * Search the most closely enclosing list of parameter elements for a
+ * parameter, defined by the given [node], with the given [parameterName].
+ * Return the element that was found, or throw an [ElementMismatchException]
+ * if an element corresponding to the identifier cannot be found.
+ */
+ ParameterElement _getElementForParameter(
+ FormalParameter node, SimpleIdentifier parameterName) {
+ List<ParameterElement> parameters = null;
+ if (_enclosingParameter != null) {
+ parameters = _enclosingParameter.parameters;
+ }
+ if (parameters == null && _enclosingExecutable != null) {
+ parameters = _enclosingExecutable.parameters;
+ }
+ if (parameters == null && _enclosingAlias != null) {
+ parameters = _enclosingAlias.parameters;
+ }
+ if (parameters == null) {
+ StringBuffer buffer = new StringBuffer();
+ buffer.writeln('Could not find parameter in enclosing scope');
+ buffer.writeln(
+ '(_enclosingParameter == null) == ${_enclosingParameter == null}');
+ buffer.writeln(
+ '(_enclosingExecutable == null) == ${_enclosingExecutable == null}');
+ buffer.writeln('(_enclosingAlias == null) == ${_enclosingAlias == null}');
+ _mismatch(buffer.toString(), parameterName);
+ }
+ return _findIdentifier(parameters, parameterName);
+ }
+
+ /**
+ * Associate each of the annotation [nodes] with the corresponding
+ * [ElementAnnotation] in [annotations]. If there is a problem, report it
+ * against the given [parent] node.
+ */
+ void _resolveAnnotations(AstNode parent, NodeList<Annotation> nodes,
+ List<ElementAnnotation> annotations) {
+ int nodeCount = nodes.length;
+ if (nodeCount != annotations.length) {
+ _mismatch(
+ 'Found $nodeCount annotation nodes and '
+ '${annotations.length} element annotations',
+ parent);
+ }
+ for (int i = 0; i < nodeCount; i++) {
+ nodes[i].elementAnnotation = annotations[i];
+ }
+ }
+
+ /**
+ * If [element] is not `null`, associate each of the annotation [nodes] with
+ * the corresponding [ElementAnnotation] in [element.metadata]. If there is a
+ * problem, report it against the given [parent] node.
+ *
+ * If [element] is `null`, do nothing--this allows us to be robust in the
+ * case where we are operating on an element model that hasn't been fully
+ * built.
+ */
+ void _resolveMetadata(
+ AstNode parent, NodeList<Annotation> nodes, Element element) {
+ if (element != null) {
+ _resolveAnnotations(parent, nodes, element.metadata);
+ }
+ }
+
+ /**
+ * Throw an exception if there are non-synthetic elements in the element model
+ * that were not associated with an AST node.
+ */
+ void _validateResolution() {
+ if (_expectedElements.isNotEmpty) {
+ StringBuffer buffer = new StringBuffer();
+ buffer.write(_expectedElements.length);
+ buffer.writeln(' unmatched elements found:');
+ for (Element element in _expectedElements) {
+ buffer.write(' ');
+ buffer.writeln(element);
+ }
+ throw new _ElementMismatchException(buffer.toString());
+ }
+ }
+}
+
+/**
+ * A visitor that can be used to collect all of the non-synthetic elements in an
+ * element model.
+ */
+class _ElementGatherer extends GeneralizingElementVisitor {
+ /**
+ * The set in which the elements are collected.
+ */
+ final Set<Element> elements = new HashSet<Element>();
+
+ /**
+ * Initialize the visitor.
+ */
+ _ElementGatherer();
+
+ @override
+ void visitElement(Element element) {
+ if (!element.isSynthetic) {
+ elements.add(element);
+ }
+ super.visitElement(element);
+ }
+}
+
+class _ElementMismatchException extends AnalysisException {
+ /**
+ * Initialize a newly created exception to have the given [message] and
+ * [cause].
+ */
+ _ElementMismatchException(String message, [CaughtException cause = null])
+ : super(message, cause);
+}
+
+/**
+ * A mixin for classes that use an existing element model to resolve a portion
+ * of an AST structure.
+ */
+class _ExistingElementResolver {
+ /**
+ * The compilation unit containing the AST nodes being visited.
+ */
+ CompilationUnitElementImpl _enclosingUnit;
+
+ /**
+ * Throw an [ElementMismatchException] to report that the element model and the
+ * AST do not match. The [message] will have the path to the given [node]
+ * appended to it.
+ */
+ void _mismatch(String message, AstNode node) {
+ StringBuffer buffer = new StringBuffer();
+ buffer.write('Mismatch in ');
+ buffer.write(runtimeType);
+ buffer.write(' while resolving ');
+ buffer.writeln(_enclosingUnit?.source?.fullName);
+ buffer.writeln(message);
+ buffer.write('Path to root:');
+ String separator = ' ';
+ AstNode parent = node;
+ while (parent != null) {
+ buffer.write(separator);
+ buffer.write(parent.runtimeType.toString());
+ separator = ', ';
+ parent = parent.parent;
+ }
+ throw new _ElementMismatchException(buffer.toString());
+ }
+}
« no previous file with comments | « pkg/analyzer/lib/src/dart/element/utilities.dart ('k') | pkg/analyzer/lib/src/generated/resolver.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698