blob: 28132160b9da7aa61b80b5e9509bb1e7e85884e0 [file] [log] [blame]
// 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.
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/exception/exception.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/builder.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/generated/resolver.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<void> {
/// The compilation unit containing the AST nodes being visited.
CompilationUnitElementImpl _enclosingUnit;
/// The [ElementWalker] we are using to keep track of progress through the
/// element model.
ElementWalker _walker;
DeclarationResolver();
/// 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) {
_enclosingUnit = element;
_walker = new ElementWalker.forCompilationUnit(element);
unit.element = element;
try {
unit.accept(this);
_walker.validate();
} on Error catch (e, st) {
throw new _ElementMismatchException(
element, _walker.element, new CaughtException(e, st));
}
}
@override
void visitAnnotation(Annotation node) {
// Annotations can only contain elements in certain erroneous situations,
// in which case the elements are disconnected from the rest of the element
// model, thus we can't reconnect to them. To avoid crashes, just create
// fresh elements.
ElementHolder elementHolder = new ElementHolder();
new ElementBuilder(elementHolder, _enclosingUnit).visitAnnotation(node);
}
@override
void visitBlockFunctionBody(BlockFunctionBody node) {
if (_isBodyToCreateElementsFor(node)) {
_walker.consumeLocalElements();
node.accept(_walker.elementBuilder);
} else {
super.visitBlockFunctionBody(node);
}
}
@override
void visitCatchClause(CatchClause node) {
_walker.elementBuilder.buildCatchVariableElements(node);
super.visitCatchClause(node);
}
@override
void visitClassDeclaration(ClassDeclaration node) {
ClassElement element = _match(node.name, _walker.getClass());
_walk(new ElementWalker.forClass(element), () {
super.visitClassDeclaration(node);
});
resolveMetadata(node, node.metadata, element);
}
@override
void visitClassTypeAlias(ClassTypeAlias node) {
ClassElement element = _match(node.name, _walker.getClass());
_walk(new ElementWalker.forClass(element), () {
super.visitClassTypeAlias(node);
});
resolveMetadata(node, node.metadata, element);
}
@override
void visitConstructorDeclaration(ConstructorDeclaration node) {
ConstructorElement element = _match(node.name, _walker.getConstructor(),
offset: node.name?.offset ?? node.returnType.offset);
_walk(new ElementWalker.forExecutable(element, _enclosingUnit), () {
(node as ConstructorDeclarationImpl).declaredElement = element;
super.visitConstructorDeclaration(node);
});
resolveMetadata(node, node.metadata, element);
}
@override
void visitDeclaredIdentifier(DeclaredIdentifier node) {
// Declared identifiers can only occur inside executable elements.
_walker.elementBuilder.visitDeclaredIdentifier(node);
}
@override
void visitDefaultFormalParameter(DefaultFormalParameter node) {
NormalFormalParameter normalParameter = node.parameter;
ParameterElement element =
_match(normalParameter.identifier, _walker.getParameter());
if (normalParameter is SimpleFormalParameterImpl) {
normalParameter.declaredElement = element;
_setGenericFunctionType(normalParameter.type, element.type);
}
if (normalParameter is FieldFormalParameterImpl) {
_setGenericFunctionType(normalParameter.type, element.type);
}
Expression defaultValue = node.defaultValue;
if (defaultValue != null) {
_walk(
new ElementWalker.forExecutable(element.initializer, _enclosingUnit),
() {
defaultValue.accept(this);
});
}
_walk(new ElementWalker.forParameter(element), () {
normalParameter.accept(this);
});
resolveMetadata(node, node.metadata, element);
}
@override
void visitEnumDeclaration(EnumDeclaration node) {
ClassElement element = _match(node.name, _walker.getEnum());
resolveMetadata(node, node.metadata, element);
_walk(new ElementWalker.forClass(element), () {
for (EnumConstantDeclaration constant in node.constants) {
VariableElement field = _match(constant.name, _walker.getVariable());
resolveMetadata(node, constant.metadata, field);
constant.name.staticElement = field;
constant.name.staticType = field.type;
}
_walker.getFunction(); // toString()
super.visitEnumDeclaration(node);
});
}
@override
void visitExportDirective(ExportDirective node) {
super.visitExportDirective(node);
List<ElementAnnotation> annotations =
_enclosingUnit.getAnnotations(node.offset);
if (annotations.isEmpty && node.metadata.isNotEmpty) {
int index = (node.parent as CompilationUnit)
.directives
.where((directive) => directive is ExportDirective)
.toList()
.indexOf(node);
annotations = _walker.element.library.exports[index].metadata;
}
resolveAnnotations(node, node.metadata, annotations);
}
@override
void visitExpressionFunctionBody(ExpressionFunctionBody node) {
if (_isBodyToCreateElementsFor(node)) {
_walker.consumeLocalElements();
node.accept(_walker.elementBuilder);
} else {
super.visitExpressionFunctionBody(node);
}
}
@override
void visitExtensionDeclaration(ExtensionDeclaration node) {
ExtensionElement element = _match(node.name, _walker.getExtension());
(node as ExtensionDeclarationImpl).declaredElement = element;
_walk(new ElementWalker.forExtension(element), () {
super.visitExtensionDeclaration(node);
});
resolveMetadata(node, node.metadata, element);
}
@override
void visitFieldDeclaration(FieldDeclaration node) {
super.visitFieldDeclaration(node);
FieldElement firstFieldElement = node.fields.variables[0].declaredElement;
resolveMetadata(node, node.metadata, firstFieldElement);
}
@override
void visitFieldFormalParameter(FieldFormalParameter node) {
if (node.parent is! DefaultFormalParameter) {
ParameterElement element =
_match(node.identifier, _walker.getParameter());
_walk(new ElementWalker.forParameter(element), () {
super.visitFieldFormalParameter(node);
});
resolveMetadata(node, node.metadata, element);
_setGenericFunctionType(node.type, element.type);
} else {
super.visitFieldFormalParameter(node);
}
}
@override
void visitFunctionDeclaration(FunctionDeclaration node) {
SimpleIdentifier functionName = node.name;
Token property = node.propertyKeyword;
ExecutableElement element;
if (property == null) {
element = _match(functionName, _walker.getFunction());
} else {
if (_walker.element is ExecutableElement) {
element = _match(functionName, _walker.getFunction());
} else if (property.keyword == Keyword.GET) {
element = _match(functionName, _walker.getAccessor());
} else {
assert(property.keyword == Keyword.SET);
element = _match(functionName, _walker.getAccessor(),
elementName: functionName.name + '=');
}
}
_setGenericFunctionType(node.returnType, element.returnType);
(node.functionExpression as FunctionExpressionImpl).declaredElement =
element;
node.returnType?.accept(this);
_walker._elementHolder?.addFunction(element);
_walk(new ElementWalker.forExecutable(element, _enclosingUnit), () {
super.visitFunctionDeclaration(node);
});
resolveMetadata(node, node.metadata, element);
}
@override
void visitFunctionExpression(FunctionExpression node) {
if (node.parent is! FunctionDeclaration) {
node.accept(_walker.elementBuilder);
} else {
super.visitFunctionExpression(node);
}
}
@override
void visitFunctionTypeAlias(FunctionTypeAlias node) {
FunctionTypeAliasElement element = _match(node.name, _walker.getTypedef());
_walk(new ElementWalker.forTypedef(element), () {
super.visitFunctionTypeAlias(node);
});
resolveMetadata(node, node.metadata, element);
}
@override
void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
if (node.parent is! DefaultFormalParameter) {
ParameterElement element =
_match(node.identifier, _walker.getParameter());
_walk(new ElementWalker.forParameter(element), () {
super.visitFunctionTypedFormalParameter(node);
});
resolveMetadata(node, node.metadata, element);
} else {
super.visitFunctionTypedFormalParameter(node);
}
}
@override
void visitGenericFunctionType(GenericFunctionType node) {
var builder = new LocalElementBuilder(ElementHolder(), _enclosingUnit);
node.accept(builder);
var nodeImpl = node as GenericFunctionTypeImpl;
_enclosingUnit.encloseElement(
nodeImpl.declaredElement as GenericFunctionTypeElementImpl,
);
}
@override
void visitGenericTypeAlias(GenericTypeAlias node) {
GenericTypeAliasElementImpl element =
_match(node.name, _walker.getTypedef());
_setGenericFunctionType(node.functionType, element.function?.type);
_walk(new ElementWalker.forGenericTypeAlias(element), () {
super.visitGenericTypeAlias(node);
});
resolveMetadata(node, node.metadata, element);
}
@override
void visitImportDirective(ImportDirective node) {
super.visitImportDirective(node);
List<ElementAnnotation> annotations =
_enclosingUnit.getAnnotations(node.offset);
if (annotations.isEmpty && node.metadata.isNotEmpty) {
int index = (node.parent as CompilationUnit)
.directives
.where((directive) => directive is ImportDirective)
.toList()
.indexOf(node);
annotations = _walker.element.library.imports[index].metadata;
}
resolveAnnotations(node, node.metadata, annotations);
}
@override
void visitLabeledStatement(LabeledStatement node) {
bool onSwitchStatement = node.statement is SwitchStatement;
_walker.elementBuilder
.buildLabelElements(node.labels, onSwitchStatement, false);
super.visitLabeledStatement(node);
}
@override
void visitLibraryDirective(LibraryDirective node) {
super.visitLibraryDirective(node);
List<ElementAnnotation> annotations =
_enclosingUnit.getAnnotations(node.offset);
if (annotations.isEmpty && node.metadata.isNotEmpty) {
annotations = _walker.element.library.metadata;
}
resolveAnnotations(node, node.metadata, annotations);
}
@override
void visitMethodDeclaration(MethodDeclaration node) {
Token property = node.propertyKeyword;
SimpleIdentifier methodName = node.name;
String nameOfMethod = methodName.name;
ExecutableElement element;
if (property == null) {
String elementName = nameOfMethod == '-' &&
node.parameters != null &&
node.parameters.parameters.isEmpty
? 'unary-'
: nameOfMethod;
element =
_match(methodName, _walker.getFunction(), elementName: elementName);
} else {
if (property.keyword == Keyword.GET) {
element = _match(methodName, _walker.getAccessor());
} else {
assert(property.keyword == Keyword.SET);
element = _match(methodName, _walker.getAccessor(),
elementName: nameOfMethod + '=');
}
}
_setGenericFunctionType(node.returnType, element.returnType);
node.returnType?.accept(this);
_walk(new ElementWalker.forExecutable(element, _enclosingUnit), () {
super.visitMethodDeclaration(node);
});
resolveMetadata(node, node.metadata, element);
}
@override
void visitMixinDeclaration(MixinDeclaration node) {
ClassElement element = _match(node.name, _walker.getMixin());
_walk(new ElementWalker.forClass(element), () {
super.visitMixinDeclaration(node);
});
resolveMetadata(node, node.metadata, element);
}
@override
void visitPartDirective(PartDirective node) {
super.visitPartDirective(node);
List<ElementAnnotation> annotations =
_enclosingUnit.getAnnotations(node.offset);
if (annotations.isEmpty && node.metadata.isNotEmpty) {
int index = (node.parent as CompilationUnit)
.directives
.where((directive) => directive is PartDirective)
.toList()
.indexOf(node);
annotations = _walker.element.library.parts[index].metadata;
}
resolveAnnotations(node, node.metadata, annotations);
}
@override
void visitPartOfDirective(PartOfDirective node) {
node.element = _enclosingUnit.library;
super.visitPartOfDirective(node);
}
@override
void visitSimpleFormalParameter(SimpleFormalParameter node) {
if (node.parent is! DefaultFormalParameter) {
ParameterElement element =
_match(node.identifier, _walker.getParameter());
(node as SimpleFormalParameterImpl).declaredElement = element;
_setGenericFunctionType(node.type, element.type);
_walk(new ElementWalker.forParameter(element), () {
super.visitSimpleFormalParameter(node);
});
resolveMetadata(node, node.metadata, element);
} else {
super.visitSimpleFormalParameter(node);
}
}
@override
void visitSwitchCase(SwitchCase node) {
_walker.elementBuilder.buildLabelElements(node.labels, false, true);
super.visitSwitchCase(node);
}
@override
void visitSwitchDefault(SwitchDefault node) {
_walker.elementBuilder.buildLabelElements(node.labels, false, true);
super.visitSwitchDefault(node);
}
@override
void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
super.visitTopLevelVariableDeclaration(node);
VariableElement firstElement = node.variables.variables[0].declaredElement;
resolveMetadata(node, node.metadata, firstElement);
}
@override
void visitTypeParameter(TypeParameter node) {
TypeParameterElement element =
_match(node.name, _walker.getTypeParameter());
_setGenericFunctionType(node.bound, element.bound);
super.visitTypeParameter(node);
resolveMetadata(node, node.metadata, element);
}
@override
void visitVariableDeclaration(VariableDeclaration node) {
VariableElement element = _match(node.name, _walker.getVariable());
Expression initializer = node.initializer;
if (initializer != null) {
_walk(
new ElementWalker.forExecutable(element.initializer, _enclosingUnit),
() {
super.visitVariableDeclaration(node);
});
} else {
super.visitVariableDeclaration(node);
}
}
@override
void visitVariableDeclarationList(VariableDeclarationList node) {
if (_walker.elementBuilder != null) {
_walker.elementBuilder.visitVariableDeclarationList(node);
} else {
node.variables.accept(this);
VariableElement firstVariable = node.variables[0].declaredElement;
_setGenericFunctionType(node.type, firstVariable.type);
node.type?.accept(this);
if (node.parent is! FieldDeclaration &&
node.parent is! TopLevelVariableDeclaration) {
resolveMetadata(node, node.metadata, firstVariable);
}
}
}
/// Updates [identifier] to point to [element], after ensuring that the
/// element has the expected name.
///
/// If no [elementName] is given, it defaults to the name of the [identifier]
/// (or the empty string if [identifier] is `null`).
///
/// If [identifier] is `null`, nothing is updated, but the element name is
/// still checked.
E _match<E extends Element>(SimpleIdentifier identifier, E element,
{String elementName, int offset}) {
elementName ??= identifier?.name ?? '';
offset ??= identifier?.offset ?? -1;
if (element.name != elementName) {
throw new StateError(
'Expected an element matching `$elementName`, got `${element.name}`');
}
identifier?.staticElement = element;
_matchOffset(element, offset);
return element;
}
void _matchOffset(Element element, int offset) {
if (element.nameOffset > 0 && element.nameOffset != offset) {
throw new StateError('Element offset mismatch');
} else {
(element as ElementImpl).nameOffset = offset;
}
}
/// If the given [typeNode] is a [GenericFunctionType], set its [type].
void _setGenericFunctionType(TypeAnnotation typeNode, DartType type) {
if (typeNode is GenericFunctionTypeImpl) {
typeNode.type = type;
typeNode.declaredElement = type.element;
} else if (typeNode is NamedType) {
typeNode.type = type;
if (type is ParameterizedType) {
List<TypeAnnotation> nodes =
typeNode.typeArguments?.arguments ?? const [];
List<DartType> types = type.typeArguments;
if (nodes.length == types.length) {
for (int i = 0; i < nodes.length; i++) {
_setGenericFunctionType(nodes[i], types[i]);
}
}
}
}
}
/// Recurses through the element model and AST, verifying that all elements
/// are matched.
///
/// Executes [callback] with [_walker] pointing to the given [walker] (which
/// should be a new instance of [ElementWalker]). Once [callback] returns,
/// uses [ElementWalker.validate] to verify that all expected elements have
/// been matched.
void _walk(ElementWalker walker, void callback()) {
ElementWalker outerWalker = _walker;
_walker = walker;
callback();
walker.validate();
_walker = outerWalker;
}
/// Associate each of the annotation [nodes] with the corresponding
/// [ElementAnnotation] in [annotations]. If there is a problem, report it
/// against the given [parent] node.
static void resolveAnnotations(AstNode parent, NodeList<Annotation> nodes,
List<ElementAnnotation> annotations) {
int nodeCount = nodes.length;
if (nodeCount != annotations.length) {
throw new StateError('Found $nodeCount annotation nodes and '
'${annotations.length} element annotations');
}
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.
static void resolveMetadata(
AstNode parent, NodeList<Annotation> nodes, Element element) {
if (element != null) {
resolveAnnotations(parent, nodes, element.metadata);
}
}
static bool _isBodyToCreateElementsFor(FunctionBody node) {
AstNode parent = node.parent;
return parent is ConstructorDeclaration ||
parent is MethodDeclaration ||
parent.parent is FunctionDeclaration &&
parent.parent.parent is CompilationUnit;
}
}
/// Keeps track of the set of non-synthetic child elements of an element,
/// yielding them one at a time in response to "get" method calls.
class ElementWalker {
/// The element whose child elements are being walked.
final Element element;
/// If [element] is an executable element, an element builder which is
/// accumulating the executable element's local variables and labels.
/// Otherwise `null`.
LocalElementBuilder elementBuilder;
/// If [element] is an executable element, the element holder associated with
/// [elementBuilder]. Otherwise `null`.
ElementHolder _elementHolder;
List<PropertyAccessorElement> _accessors;
int _accessorIndex = 0;
List<ClassElement> _classes;
int _classIndex = 0;
List<ConstructorElement> _constructors;
int _constructorIndex = 0;
List<ClassElement> _enums;
int _enumIndex = 0;
List<ExtensionElement> _extensions;
int _extensionIndex = 0;
List<ExecutableElement> _functions;
int _functionIndex = 0;
List<ClassElement> _mixins;
int _mixinIndex = 0;
List<ParameterElement> _parameters;
int _parameterIndex = 0;
List<FunctionTypeAliasElement> _typedefs;
int _typedefIndex = 0;
List<TypeParameterElement> _typeParameters;
int _typeParameterIndex = 0;
List<VariableElement> _variables;
int _variableIndex = 0;
/// Creates an [ElementWalker] which walks the child elements of a class
/// element.
ElementWalker.forClass(ClassElement element)
: element = element,
_accessors = element.accessors.where(_isNotSynthetic).toList(),
_constructors = element.isMixinApplication
? null
: element.constructors.where(_isNotSynthetic).toList(),
_functions = element.methods,
_typeParameters = element.typeParameters,
_variables = element.fields.where(_isNotSynthetic).toList();
/// Creates an [ElementWalker] which walks the child elements of a compilation
/// unit element.
ElementWalker.forCompilationUnit(CompilationUnitElement compilationUnit)
: element = compilationUnit,
_accessors = compilationUnit.accessors.where(_isNotSynthetic).toList(),
_classes = compilationUnit.types,
_enums = compilationUnit.enums,
_extensions = compilationUnit.extensions,
_functions = compilationUnit.functions,
_mixins = compilationUnit.mixins,
_typedefs = compilationUnit.functionTypeAliases,
_variables =
compilationUnit.topLevelVariables.where(_isNotSynthetic).toList();
/// Creates an [ElementWalker] which walks the child elements of a compilation
/// unit element.
ElementWalker.forExecutable(
ExecutableElement element, CompilationUnitElement compilationUnit)
: this._forExecutable(element, compilationUnit, new ElementHolder());
/// Creates an [ElementWalker] which walks the child elements of an extension
/// element.
ElementWalker.forExtension(ExtensionElement element)
: element = element,
_accessors = element.accessors.where(_isNotSynthetic).toList(),
_functions = element.methods,
_typeParameters = element.typeParameters,
_variables = element.fields.where(_isNotSynthetic).toList();
/// Creates an [ElementWalker] which walks the child elements of a typedef
/// element.
ElementWalker.forGenericFunctionType(GenericFunctionTypeElement element)
: element = element,
_parameters = element.parameters,
_typeParameters = element.typeParameters;
/// Creates an [ElementWalker] which walks the child elements of a typedef
/// element defined using a generic function type.
ElementWalker.forGenericTypeAlias(FunctionTypeAliasElement element)
: element = element,
_typeParameters = element.typeParameters;
/// Creates an [ElementWalker] which walks the child elements of a parameter
/// element.
ElementWalker.forParameter(ParameterElement element)
: element = element,
_parameters = element.parameters,
_typeParameters = element.typeParameters;
/// Creates an [ElementWalker] which walks the child elements of a typedef
/// element.
ElementWalker.forTypedef(GenericTypeAliasElementImpl element)
: element = element,
_parameters = element.parameters,
_typeParameters = element.typeParameters;
ElementWalker._forExecutable(ExecutableElement element,
CompilationUnitElement compilationUnit, ElementHolder elementHolder)
: element = element,
elementBuilder =
new LocalElementBuilder(elementHolder, compilationUnit),
_elementHolder = elementHolder,
_functions = const <ExecutableElement>[],
_parameters = element.parameters,
_typeParameters = element.typeParameters;
void consumeLocalElements() {
_functionIndex = _functions.length;
}
void consumeParameters() {
_parameterIndex = _parameters.length;
}
/// Returns the next non-synthetic child of [element] which is an accessor;
/// throws an [IndexError] if there are no more.
PropertyAccessorElement getAccessor() => _accessors[_accessorIndex++];
/// Returns the next non-synthetic child of [element] which is a class; throws
/// an [IndexError] if there are no more.
ClassElement getClass() => _classes[_classIndex++];
/// Returns the next non-synthetic child of [element] which is a constructor;
/// throws an [IndexError] if there are no more.
ConstructorElement getConstructor() => _constructors[_constructorIndex++];
/// Returns the next non-synthetic child of [element] which is an enum; throws
/// an [IndexError] if there are no more.
ClassElement getEnum() => _enums[_enumIndex++];
ExtensionElement getExtension() => _extensions[_extensionIndex++];
/// Returns the next non-synthetic child of [element] which is a top level
/// function, method, or local function; throws an [IndexError] if there are
/// no more.
ExecutableElement getFunction() => _functions[_functionIndex++];
/// Returns the next non-synthetic child of [element] which is a mixin; throws
/// an [IndexError] if there are no more.
ClassElement getMixin() => _mixins[_mixinIndex++];
/// Returns the next non-synthetic child of [element] which is a parameter;
/// throws an [IndexError] if there are no more.
ParameterElement getParameter() => _parameters[_parameterIndex++];
/// Returns the next non-synthetic child of [element] which is a typedef;
/// throws an [IndexError] if there are no more.
FunctionTypeAliasElement getTypedef() => _typedefs[_typedefIndex++];
/// Returns the next non-synthetic child of [element] which is a type
/// parameter; throws an [IndexError] if there are no more.
TypeParameterElement getTypeParameter() =>
_typeParameters[_typeParameterIndex++];
/// Returns the next non-synthetic child of [element] which is a top level
/// variable, field, or local variable; throws an [IndexError] if there are no
/// more.
VariableElement getVariable() => _variables[_variableIndex++];
/// Verifies that all non-synthetic children of [element] have been obtained
/// from their corresponding "get" method calls; if not, throws a
/// [StateError].
void validate() {
void check(List<Element> elements, int index) {
if (elements != null && elements.length != index) {
throw new StateError(
'Unmatched ${elements[index].runtimeType} ${elements[index]}');
}
}
check(_accessors, _accessorIndex);
check(_classes, _classIndex);
check(_constructors, _constructorIndex);
check(_enums, _enumIndex);
check(_functions, _functionIndex);
check(_parameters, _parameterIndex);
check(_typedefs, _typedefIndex);
check(_typeParameters, _typeParameterIndex);
check(_variables, _variableIndex);
Element element = this.element;
if (element is ExecutableElementImpl) {
element.encloseElements(_elementHolder.functions);
element.encloseElements(_elementHolder.labels);
element.encloseElements(_elementHolder.localVariables);
}
}
static bool _isNotSynthetic(Element e) => !e.isSynthetic;
}
class _ElementMismatchException extends AnalysisException {
/// Creates an exception to refer to the given [compilationUnit], [element],
/// and [cause].
_ElementMismatchException(
CompilationUnitElement compilationUnit, Element element,
[CaughtException cause])
: super('Element mismatch in $compilationUnit at $element', cause);
}