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

Unified Diff: pkg/analyzer/lib/src/dart/element/builder.dart

Issue 2425853003: Begin separating API and local element builders. (Closed)
Patch Set: remove debug code 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 | « no previous file | pkg/analyzer/test/generated/all_the_rest_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analyzer/lib/src/dart/element/builder.dart
diff --git a/pkg/analyzer/lib/src/dart/element/builder.dart b/pkg/analyzer/lib/src/dart/element/builder.dart
index 85a1ff6eab5e7ab3778c44d6677e4c0f96f51f9d..7505ad7a72f7338e7819b48e1af66f578d195613 100644
--- a/pkg/analyzer/lib/src/dart/element/builder.dart
+++ b/pkg/analyzer/lib/src/dart/element/builder.dart
@@ -23,434 +23,118 @@ import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
/**
- * A `CompilationUnitBuilder` builds an element model for a single compilation
- * unit.
- */
-class CompilationUnitBuilder {
- /**
- * Build the compilation unit element for the given [source] based on the
- * compilation [unit] associated with the source. Throw an AnalysisException
- * if the element could not be built. [librarySource] is the source for the
- * containing library.
- */
- CompilationUnitElementImpl buildCompilationUnit(
- Source source, CompilationUnit unit, Source librarySource) {
- return PerformanceStatistics.resolve.makeCurrentWhile(() {
- if (unit == null) {
- return null;
- }
- ElementHolder holder = new ElementHolder();
- CompilationUnitElementImpl element =
- new CompilationUnitElementImpl(source.shortName);
- ElementBuilder builder = new ElementBuilder(holder, element);
- unit.accept(builder);
- element.accessors = holder.accessors;
- element.enums = holder.enums;
- element.functions = holder.functions;
- element.source = source;
- element.librarySource = librarySource;
- element.typeAliases = holder.typeAliases;
- element.types = holder.types;
- element.topLevelVariables = holder.topLevelVariables;
- unit.element = element;
- holder.validate();
- return element;
- });
- }
-}
-
-/**
- * Instances of the class `DirectiveElementBuilder` build elements for top
- * level library directives.
+ * Instances of the class `ApiElementBuilder` traverse an AST structure and
+ * build elements outside of function bodies and initializers.
*/
-class DirectiveElementBuilder extends SimpleAstVisitor<Object> {
- /**
- * The analysis context within which directive elements are being built.
- */
- final AnalysisContext context;
-
- /**
- * The library element for which directive elements are being built.
- */
- final LibraryElementImpl libraryElement;
-
- /**
- * Map from sources referenced by this library to their modification times.
- */
- final Map<Source, int> sourceModificationTimeMap;
-
- /**
- * Map from sources imported by this library to their corresponding library
- * elements.
- */
- final Map<Source, LibraryElement> importLibraryMap;
-
- /**
- * Map from sources imported by this library to their corresponding source
- * kinds.
- */
- final Map<Source, SourceKind> importSourceKindMap;
-
- /**
- * Map from sources exported by this library to their corresponding library
- * elements.
- */
- final Map<Source, LibraryElement> exportLibraryMap;
-
- /**
- * Map from sources exported by this library to their corresponding source
- * kinds.
- */
- final Map<Source, SourceKind> exportSourceKindMap;
-
+class ApiElementBuilder extends _BaseElementBuilder {
/**
- * The [ImportElement]s created so far.
+ * A flag indicating whether a variable declaration is within the body of a method or function.
*/
- final List<ImportElement> imports = <ImportElement>[];
+ bool _inFunction = false;
/**
- * The [ExportElement]s created so far.
+ * A table mapping field names to field elements for the fields defined in the current class, or
+ * `null` if we are not in the scope of a class.
*/
- final List<ExportElement> exports = <ExportElement>[];
+ HashMap<String, FieldElement> _fieldMap;
/**
- * The errors found while building directive elements.
+ * Initialize a newly created element builder to build the elements for a
+ * compilation unit. The [initialHolder] is the element holder to which the
+ * children of the visited compilation unit node will be added.
*/
- final List<AnalysisError> errors = <AnalysisError>[];
+ ApiElementBuilder(ElementHolder initialHolder,
+ CompilationUnitElementImpl compilationUnitElement)
+ : super(initialHolder, compilationUnitElement);
/**
- * Map from prefix names to their corresponding elements.
+ * Prepares for incremental resolution of a function body.
*/
- final HashMap<String, PrefixElementImpl> nameToPrefixMap =
- new HashMap<String, PrefixElementImpl>();
+ void initForFunctionBodyIncrementalResolution() {
+ _inFunction = true;
+ }
- /**
- * Indicates whether an explicit import of `dart:core` has been found.
- */
- bool explicitlyImportsCore = false;
+ @override
+ Object visitAnnotation(Annotation node) {
+ // Although it isn't valid to do so because closures are not constant
+ // expressions, it's possible for one of the arguments to the constructor to
+ // contain a closure. Wrapping the processing of the annotation this way
+ // prevents these closures from being added to the list of functions in the
+ // annotated declaration.
+ ElementHolder holder = new ElementHolder();
+ ElementHolder previousHolder = _currentHolder;
+ _currentHolder = holder;
+ try {
+ super.visitAnnotation(node);
+ } finally {
+ _currentHolder = previousHolder;
+ }
+ return null;
+ }
- DirectiveElementBuilder(
- this.context,
- this.libraryElement,
- this.sourceModificationTimeMap,
- this.importLibraryMap,
- this.importSourceKindMap,
- this.exportLibraryMap,
- this.exportSourceKindMap);
+ @override
+ Object visitBlockFunctionBody(BlockFunctionBody node) {
+ return null;
+ }
@override
- Object visitCompilationUnit(CompilationUnit node) {
+ Object visitClassDeclaration(ClassDeclaration node) {
+ ElementHolder holder = new ElementHolder();
//
- // Resolve directives.
+ // Process field declarations before constructors and methods so that field
+ // formal parameters can be correctly resolved to their fields.
//
- for (Directive directive in node.directives) {
- directive.accept(this);
+ ElementHolder previousHolder = _currentHolder;
+ _currentHolder = holder;
+ try {
+ List<ClassMember> nonFields = new List<ClassMember>();
+ node.visitChildren(
+ new _ElementBuilder_visitClassDeclaration(this, nonFields));
+ _buildFieldMap(holder.fieldsWithoutFlushing);
+ int count = nonFields.length;
+ for (int i = 0; i < count; i++) {
+ nonFields[i].accept(this);
+ }
+ } finally {
+ _currentHolder = previousHolder;
}
- //
- // Ensure "dart:core" import.
- //
- Source librarySource = libraryElement.source;
- Source coreLibrarySource = context.sourceFactory.forUri(DartSdk.DART_CORE);
- if (!explicitlyImportsCore && coreLibrarySource != librarySource) {
- ImportElementImpl importElement = new ImportElementImpl(-1);
- importElement.importedLibrary = importLibraryMap[coreLibrarySource];
- importElement.synthetic = true;
- imports.add(importElement);
+ SimpleIdentifier className = node.name;
+ ClassElementImpl element = new ClassElementImpl.forNode(className);
+ _setCodeRange(element, node);
+ element.metadata = _createElementAnnotations(node.metadata);
+ element.typeParameters = holder.typeParameters;
+ setElementDocumentationComment(element, node);
+ element.abstract = node.isAbstract;
+ element.accessors = holder.accessors;
+ List<ConstructorElement> constructors = holder.constructors;
+ if (constructors.isEmpty) {
+ constructors = _createDefaultConstructors(element);
}
- //
- // Populate the library element.
- //
- libraryElement.imports = imports;
- libraryElement.exports = exports;
+ element.constructors = constructors;
+ element.fields = holder.fields;
+ element.methods = holder.methods;
+ _currentHolder.addType(element);
+ className.staticElement = element;
+ _fieldMap = null;
+ holder.validate();
return null;
}
@override
- Object visitExportDirective(ExportDirective node) {
- // Remove previous element. (It will remain null if the target is missing.)
- node.element = null;
- Source exportedSource = node.selectedSource;
- int exportedTime = sourceModificationTimeMap[exportedSource] ?? -1;
- // The exported source will be null if the URI in the export
- // directive was invalid.
- LibraryElement exportedLibrary = exportLibraryMap[exportedSource];
- if (exportedLibrary != null) {
- ExportElementImpl exportElement = new ExportElementImpl(node.offset);
- exportElement.metadata = _getElementAnnotations(node.metadata);
- StringLiteral uriLiteral = node.uri;
- if (uriLiteral != null) {
- exportElement.uriOffset = uriLiteral.offset;
- exportElement.uriEnd = uriLiteral.end;
- }
- exportElement.uri = node.selectedUriContent;
- exportElement.combinators = _buildCombinators(node);
- exportElement.exportedLibrary = exportedLibrary;
- setElementDocumentationComment(exportElement, node);
- node.element = exportElement;
- exports.add(exportElement);
- if (exportedTime >= 0 &&
- exportSourceKindMap[exportedSource] != SourceKind.LIBRARY) {
- int offset = node.offset;
- int length = node.length;
- if (uriLiteral != null) {
- offset = uriLiteral.offset;
- length = uriLiteral.length;
- }
- errors.add(new AnalysisError(
- libraryElement.source,
- offset,
- length,
- CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY,
- [uriLiteral.toSource()]));
- }
- }
- return null;
- }
-
- @override
- Object visitImportDirective(ImportDirective node) {
- // Remove previous element. (It will remain null if the target is missing.)
- node.element = null;
- Source importedSource = node.selectedSource;
- int importedTime = sourceModificationTimeMap[importedSource] ?? -1;
- // The imported source will be null if the URI in the import
- // directive was invalid.
- LibraryElement importedLibrary = importLibraryMap[importedSource];
- if (importedLibrary != null) {
- if (importedLibrary.isDartCore) {
- explicitlyImportsCore = true;
- }
- ImportElementImpl importElement = new ImportElementImpl(node.offset);
- importElement.metadata = _getElementAnnotations(node.metadata);
- StringLiteral uriLiteral = node.uri;
- if (uriLiteral != null) {
- importElement.uriOffset = uriLiteral.offset;
- importElement.uriEnd = uriLiteral.end;
- }
- importElement.uri = node.selectedUriContent;
- importElement.deferred = node.deferredKeyword != null;
- importElement.combinators = _buildCombinators(node);
- importElement.importedLibrary = importedLibrary;
- setElementDocumentationComment(importElement, node);
- SimpleIdentifier prefixNode = node.prefix;
- if (prefixNode != null) {
- importElement.prefixOffset = prefixNode.offset;
- String prefixName = prefixNode.name;
- PrefixElementImpl prefix = nameToPrefixMap[prefixName];
- if (prefix == null) {
- prefix = new PrefixElementImpl.forNode(prefixNode);
- nameToPrefixMap[prefixName] = prefix;
- }
- importElement.prefix = prefix;
- prefixNode.staticElement = prefix;
- }
- node.element = importElement;
- imports.add(importElement);
- if (importedTime >= 0 &&
- importSourceKindMap[importedSource] != SourceKind.LIBRARY) {
- int offset = node.offset;
- int length = node.length;
- if (uriLiteral != null) {
- offset = uriLiteral.offset;
- length = uriLiteral.length;
- }
- ErrorCode errorCode = importElement.isDeferred
- ? StaticWarningCode.IMPORT_OF_NON_LIBRARY
- : CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY;
- errors.add(new AnalysisError(libraryElement.source, offset, length,
- errorCode, [uriLiteral.toSource()]));
- }
- }
- return null;
- }
-
- @override
- Object visitLibraryDirective(LibraryDirective node) {
- (node.element as LibraryElementImpl)?.metadata =
- _getElementAnnotations(node.metadata);
- return null;
- }
-
- @override
- Object visitPartDirective(PartDirective node) {
- (node.element as CompilationUnitElementImpl)?.metadata =
- _getElementAnnotations(node.metadata);
- return null;
- }
-
- /**
- * Gather a list of the [ElementAnnotation]s referred to by the [Annotation]s
- * in [metadata].
- */
- List<ElementAnnotation> _getElementAnnotations(
- NodeList<Annotation> metadata) {
- if (metadata.isEmpty) {
- return ElementAnnotation.EMPTY_LIST;
- }
- return metadata.map((Annotation a) => a.elementAnnotation).toList();
- }
-
- /**
- * Build the element model representing the combinators declared by
- * the given [directive].
- */
- static List<NamespaceCombinator> _buildCombinators(
- NamespaceDirective directive) {
- _NamespaceCombinatorBuilder namespaceCombinatorBuilder =
- new _NamespaceCombinatorBuilder();
- for (Combinator combinator in directive.combinators) {
- combinator.accept(namespaceCombinatorBuilder);
- }
- return namespaceCombinatorBuilder.combinators;
- }
-}
-
-/**
- * Instances of the class `ElementBuilder` traverse an AST structure and build the element
- * model representing the AST structure.
- */
-class ElementBuilder extends RecursiveAstVisitor<Object> {
- /**
- * The compilation unit element into which the elements being built will be
- * stored.
- */
- final CompilationUnitElementImpl compilationUnitElement;
-
- /**
- * The element holder associated with the element that is currently being built.
- */
- ElementHolder _currentHolder;
-
- /**
- * A flag indicating whether a variable declaration is within the body of a method or function.
- */
- bool _inFunction = false;
-
- /**
- * A table mapping field names to field elements for the fields defined in the current class, or
- * `null` if we are not in the scope of a class.
- */
- HashMap<String, FieldElement> _fieldMap;
-
- /**
- * Initialize a newly created element builder to build the elements for a
- * compilation unit. The [initialHolder] is the element holder to which the
- * children of the visited compilation unit node will be added.
- */
- ElementBuilder(ElementHolder initialHolder, this.compilationUnitElement) {
- _currentHolder = initialHolder;
- }
-
- /**
- * Prepares for incremental resolution of a function body.
- */
- void initForFunctionBodyIncrementalResolution() {
- _inFunction = true;
- }
-
- @override
- Object visitAnnotation(Annotation node) {
- // Although it isn't valid to do so because closures are not constant
- // expressions, it's possible for one of the arguments to the constructor to
- // contain a closure. Wrapping the processing of the annotation this way
- // prevents these closures from being added to the list of functions in the
- // annotated declaration.
- ElementHolder holder = new ElementHolder();
- ElementHolder previousHolder = _currentHolder;
- _currentHolder = holder;
- try {
- super.visitAnnotation(node);
- } finally {
- _currentHolder = previousHolder;
- }
- return null;
- }
-
- @override
- Object visitCatchClause(CatchClause node) {
- SimpleIdentifier exceptionParameter = node.exceptionParameter;
- if (exceptionParameter != null) {
- // exception
- LocalVariableElementImpl exception =
- new LocalVariableElementImpl.forNode(exceptionParameter);
- if (node.exceptionType == null) {
- exception.hasImplicitType = true;
- }
- exception.setVisibleRange(node.offset, node.length);
- _currentHolder.addLocalVariable(exception);
- exceptionParameter.staticElement = exception;
- // stack trace
- SimpleIdentifier stackTraceParameter = node.stackTraceParameter;
- if (stackTraceParameter != null) {
- LocalVariableElementImpl stackTrace =
- new LocalVariableElementImpl.forNode(stackTraceParameter);
- _setCodeRange(stackTrace, stackTraceParameter);
- stackTrace.setVisibleRange(node.offset, node.length);
- _currentHolder.addLocalVariable(stackTrace);
- stackTraceParameter.staticElement = stackTrace;
- }
- }
- return super.visitCatchClause(node);
- }
-
- @override
- Object visitClassDeclaration(ClassDeclaration node) {
- ElementHolder holder = new ElementHolder();
- //
- // Process field declarations before constructors and methods so that field
- // formal parameters can be correctly resolved to their fields.
- //
- ElementHolder previousHolder = _currentHolder;
- _currentHolder = holder;
- try {
- List<ClassMember> nonFields = new List<ClassMember>();
- node.visitChildren(
- new _ElementBuilder_visitClassDeclaration(this, nonFields));
- _buildFieldMap(holder.fieldsWithoutFlushing);
- int count = nonFields.length;
- for (int i = 0; i < count; i++) {
- nonFields[i].accept(this);
- }
- } finally {
- _currentHolder = previousHolder;
- }
- SimpleIdentifier className = node.name;
- ClassElementImpl element = new ClassElementImpl.forNode(className);
- _setCodeRange(element, node);
- element.metadata = _createElementAnnotations(node.metadata);
- element.typeParameters = holder.typeParameters;
- setElementDocumentationComment(element, node);
- element.abstract = node.isAbstract;
- element.accessors = holder.accessors;
- List<ConstructorElement> constructors = holder.constructors;
- if (constructors.isEmpty) {
- constructors = _createDefaultConstructors(element);
- }
- element.constructors = constructors;
- element.fields = holder.fields;
- element.methods = holder.methods;
- _currentHolder.addType(element);
- className.staticElement = element;
- _fieldMap = null;
- holder.validate();
- return null;
- }
-
- @override
- Object visitClassTypeAlias(ClassTypeAlias node) {
- ElementHolder holder = new ElementHolder();
- _visitChildren(holder, node);
- SimpleIdentifier className = node.name;
- ClassElementImpl element = new ClassElementImpl.forNode(className);
- _setCodeRange(element, node);
- element.metadata = _createElementAnnotations(node.metadata);
- element.abstract = node.abstractKeyword != null;
- element.mixinApplication = true;
- element.typeParameters = holder.typeParameters;
- setElementDocumentationComment(element, node);
- _currentHolder.addType(element);
- className.staticElement = element;
- holder.validate();
+ Object visitClassTypeAlias(ClassTypeAlias node) {
+ ElementHolder holder = new ElementHolder();
+ _visitChildren(holder, node);
+ SimpleIdentifier className = node.name;
+ ClassElementImpl element = new ClassElementImpl.forNode(className);
+ _setCodeRange(element, node);
+ element.metadata = _createElementAnnotations(node.metadata);
+ element.abstract = node.abstractKeyword != null;
+ element.mixinApplication = true;
+ element.typeParameters = holder.typeParameters;
+ setElementDocumentationComment(element, node);
+ _currentHolder.addType(element);
+ className.staticElement = element;
+ holder.validate();
return null;
}
@@ -514,75 +198,6 @@ class ElementBuilder extends RecursiveAstVisitor<Object> {
}
@override
- Object visitDeclaredIdentifier(DeclaredIdentifier node) {
- SimpleIdentifier variableName = node.identifier;
- LocalVariableElementImpl element =
- new LocalVariableElementImpl.forNode(variableName);
- _setCodeRange(element, node);
- element.metadata = _createElementAnnotations(node.metadata);
- ForEachStatement statement = node.parent as ForEachStatement;
- element.setVisibleRange(statement.offset, statement.length);
- element.const3 = node.isConst;
- element.final2 = node.isFinal;
- if (node.type == null) {
- element.hasImplicitType = true;
- }
- _currentHolder.addLocalVariable(element);
- variableName.staticElement = element;
- return super.visitDeclaredIdentifier(node);
- }
-
- @override
- Object visitDefaultFormalParameter(DefaultFormalParameter node) {
- ElementHolder holder = new ElementHolder();
- NormalFormalParameter normalParameter = node.parameter;
- SimpleIdentifier parameterName = normalParameter.identifier;
- ParameterElementImpl parameter;
- if (normalParameter is FieldFormalParameter) {
- parameter =
- new DefaultFieldFormalParameterElementImpl.forNode(parameterName);
- FieldElement field =
- _fieldMap == null ? null : _fieldMap[parameterName.name];
- if (field != null) {
- (parameter as DefaultFieldFormalParameterElementImpl).field = field;
- }
- } else {
- parameter = new DefaultParameterElementImpl.forNode(parameterName);
- }
- _setCodeRange(parameter, node);
- parameter.const3 = node.isConst;
- parameter.final2 = node.isFinal;
- parameter.parameterKind = node.kind;
- // set initializer, default value range
- Expression defaultValue = node.defaultValue;
- if (defaultValue != null) {
- _visit(holder, defaultValue);
- FunctionElementImpl initializer =
- new FunctionElementImpl.forOffset(defaultValue.beginToken.offset);
- initializer.hasImplicitReturnType = true;
- initializer.functions = holder.functions;
- initializer.labels = holder.labels;
- initializer.localVariables = holder.localVariables;
- initializer.parameters = holder.parameters;
- initializer.synthetic = true;
- initializer.type = new FunctionTypeImpl(initializer);
- parameter.initializer = initializer;
- parameter.defaultValueCode = defaultValue.toSource();
- }
- // visible range
- _setParameterVisibleRange(node, parameter);
- if (normalParameter is SimpleFormalParameter &&
- normalParameter.type == null) {
- parameter.hasImplicitType = true;
- }
- _currentHolder.addParameter(parameter);
- parameterName.staticElement = parameter;
- normalParameter.accept(this);
- holder.validate();
- return null;
- }
-
- @override
Object visitEnumDeclaration(EnumDeclaration node) {
SimpleIdentifier enumName = node.name;
EnumElementImpl enumElement = new EnumElementImpl.forNode(enumName);
@@ -625,6 +240,11 @@ class ElementBuilder extends RecursiveAstVisitor<Object> {
}
@override
+ Object visitExpressionFunctionBody(ExpressionFunctionBody node) {
+ return null;
+ }
+
+ @override
Object visitFieldFormalParameter(FieldFormalParameter node) {
if (node.parent is! DefaultFormalParameter) {
SimpleIdentifier parameterName = node.identifier;
@@ -851,32 +471,6 @@ class ElementBuilder extends RecursiveAstVisitor<Object> {
}
@override
- Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
- if (node.parent is! DefaultFormalParameter) {
- SimpleIdentifier parameterName = node.identifier;
- ParameterElementImpl parameter =
- new ParameterElementImpl.forNode(parameterName);
- _setCodeRange(parameter, node);
- parameter.parameterKind = node.kind;
- _setParameterVisibleRange(node, parameter);
- _currentHolder.addParameter(parameter);
- parameterName.staticElement = parameter;
- }
- //
- // The children of this parameter include any parameters defined on the type
- //of this parameter.
- //
- ElementHolder holder = new ElementHolder();
- _visitChildren(holder, node);
- ParameterElementImpl element = node.element;
- element.metadata = _createElementAnnotations(node.metadata);
- element.parameters = holder.parameters;
- element.typeParameters = holder.typeParameters;
- holder.validate();
- return null;
- }
-
- @override
Object visitImportDirective(ImportDirective node) {
List<ElementAnnotation> annotations =
_createElementAnnotations(node.metadata);
@@ -885,19 +479,6 @@ class ElementBuilder extends RecursiveAstVisitor<Object> {
}
@override
- Object visitLabeledStatement(LabeledStatement node) {
- bool onSwitchStatement = node.statement is SwitchStatement;
- for (Label label in node.labels) {
- SimpleIdentifier labelName = label.label;
- LabelElementImpl element =
- new LabelElementImpl.forNode(labelName, onSwitchStatement, false);
- _currentHolder.addLabel(element);
- labelName.staticElement = element;
- }
- return super.visitLabeledStatement(node);
- }
-
- @override
Object visitLibraryDirective(LibraryDirective node) {
List<ElementAnnotation> annotations =
_createElementAnnotations(node.metadata);
@@ -1063,11 +644,792 @@ class ElementBuilder extends RecursiveAstVisitor<Object> {
}
@override
- Object visitPartDirective(PartDirective node) {
- List<ElementAnnotation> annotations =
- _createElementAnnotations(node.metadata);
- compilationUnitElement.setAnnotations(node.offset, annotations);
- return super.visitPartDirective(node);
+ Object visitPartDirective(PartDirective node) {
+ List<ElementAnnotation> annotations =
+ _createElementAnnotations(node.metadata);
+ compilationUnitElement.setAnnotations(node.offset, annotations);
+ return super.visitPartDirective(node);
+ }
+
+ @override
+ Object visitVariableDeclaration(VariableDeclaration node) {
+ bool isConst = node.isConst;
+ bool isFinal = node.isFinal;
+ Expression initializerNode = node.initializer;
+ bool hasInitializer = initializerNode != null;
+ VariableDeclarationList varList = node.parent;
+ FieldDeclaration fieldNode =
+ varList.parent is FieldDeclaration ? varList.parent : null;
+ VariableElementImpl element;
+ if (fieldNode != null) {
+ SimpleIdentifier fieldName = node.name;
+ FieldElementImpl field;
+ if ((isConst || isFinal && !fieldNode.isStatic) && hasInitializer) {
+ field = new ConstFieldElementImpl.forNode(fieldName);
+ } else {
+ field = new FieldElementImpl.forNode(fieldName);
+ }
+ element = field;
+ field.static = fieldNode.isStatic;
+ _setCodeRange(element, node);
+ setElementDocumentationComment(element, fieldNode);
+ field.hasImplicitType = varList.type == null;
+ _currentHolder.addField(field);
+ fieldName.staticElement = field;
+ } else {
+ SimpleIdentifier variableName = node.name;
+ TopLevelVariableElementImpl variable;
+ if (isConst && hasInitializer) {
+ variable = new ConstTopLevelVariableElementImpl.forNode(variableName);
+ } else {
+ variable = new TopLevelVariableElementImpl.forNode(variableName);
+ }
+ element = variable;
+ _setCodeRange(element, node);
+ if (varList.parent is TopLevelVariableDeclaration) {
+ setElementDocumentationComment(element, varList.parent);
+ }
+ variable.hasImplicitType = varList.type == null;
+ _currentHolder.addTopLevelVariable(variable);
+ variableName.staticElement = element;
+ }
+ element.const3 = isConst;
+ element.final2 = isFinal;
+ if (element is PropertyInducingElementImpl) {
+ PropertyAccessorElementImpl_ImplicitGetter getter =
+ new PropertyAccessorElementImpl_ImplicitGetter(element);
+ _currentHolder.addAccessor(getter);
+ if (!isConst && !isFinal) {
+ PropertyAccessorElementImpl_ImplicitSetter setter =
+ new PropertyAccessorElementImpl_ImplicitSetter(element);
+ _currentHolder.addAccessor(setter);
+ }
+ }
+ return null;
+ }
+
+ @override
+ Object visitVariableDeclarationList(VariableDeclarationList node) {
+ super.visitVariableDeclarationList(node);
+ AstNode parent = node.parent;
+ List<ElementAnnotation> elementAnnotations;
+ if (parent is FieldDeclaration) {
+ elementAnnotations = _createElementAnnotations(parent.metadata);
+ } else if (parent is TopLevelVariableDeclaration) {
+ elementAnnotations = _createElementAnnotations(parent.metadata);
+ } else {
+ // Local variable declaration
+ elementAnnotations = _createElementAnnotations(node.metadata);
+ }
+ _setVariableDeclarationListAnnotations(node, elementAnnotations);
+ return null;
+ }
+
+ /**
+ * Build the table mapping field names to field elements for the fields defined in the current
+ * class.
+ *
+ * @param fields the field elements defined in the current class
+ */
+ void _buildFieldMap(List<FieldElement> fields) {
+ _fieldMap = new HashMap<String, FieldElement>();
+ int count = fields.length;
+ for (int i = 0; i < count; i++) {
+ FieldElement field = fields[i];
+ _fieldMap[field.name] ??= field;
+ }
+ }
+
+ /**
+ * Creates the [ConstructorElement]s array with the single default constructor element.
+ *
+ * @param interfaceType the interface type for which to create a default constructor
+ * @return the [ConstructorElement]s array with the single default constructor element
+ */
+ List<ConstructorElement> _createDefaultConstructors(
+ ClassElementImpl definingClass) {
+ ConstructorElementImpl constructor =
+ new ConstructorElementImpl.forNode(null);
+ constructor.synthetic = true;
+ constructor.enclosingElement = definingClass;
+ return <ConstructorElement>[constructor];
+ }
+
+ /**
+ * Create the types associated with the given type parameters, setting the type of each type
+ * parameter, and return an array of types corresponding to the given parameters.
+ *
+ * @param typeParameters the type parameters for which types are to be created
+ * @return an array of types corresponding to the given parameters
+ */
+ List<DartType> _createTypeParameterTypes(
+ List<TypeParameterElement> typeParameters) {
+ int typeParameterCount = typeParameters.length;
+ List<DartType> typeArguments = new List<DartType>(typeParameterCount);
+ for (int i = 0; i < typeParameterCount; i++) {
+ TypeParameterElementImpl typeParameter =
+ typeParameters[i] as TypeParameterElementImpl;
+ TypeParameterTypeImpl typeParameterType =
+ new TypeParameterTypeImpl(typeParameter);
+ typeParameter.type = typeParameterType;
+ typeArguments[i] = typeParameterType;
+ }
+ return typeArguments;
+ }
+
+ @override
+ void _setFieldParameterField(FieldFormalParameterElementImpl parameter) {
+ FieldElement field = _fieldMap == null ? null : _fieldMap[parameter.name];
+ if (field != null) {
+ parameter.field = field;
+ }
+ }
+}
+
+/**
+ * A `CompilationUnitBuilder` builds an element model for a single compilation
+ * unit.
+ */
+class CompilationUnitBuilder {
+ /**
+ * Build the compilation unit element for the given [source] based on the
+ * compilation [unit] associated with the source. Throw an AnalysisException
+ * if the element could not be built. [librarySource] is the source for the
+ * containing library.
+ */
+ CompilationUnitElementImpl buildCompilationUnit(
+ Source source, CompilationUnit unit, Source librarySource) {
+ return PerformanceStatistics.resolve.makeCurrentWhile(() {
+ if (unit == null) {
+ return null;
+ }
+ ElementHolder holder = new ElementHolder();
+ CompilationUnitElementImpl element =
+ new CompilationUnitElementImpl(source.shortName);
+ ElementBuilder builder = new ElementBuilder(holder, element);
+ unit.accept(builder);
+ element.accessors = holder.accessors;
+ element.enums = holder.enums;
+ element.functions = holder.functions;
+ element.source = source;
+ element.librarySource = librarySource;
+ element.typeAliases = holder.typeAliases;
+ element.types = holder.types;
+ element.topLevelVariables = holder.topLevelVariables;
+ unit.element = element;
+ holder.validate();
+ return element;
+ });
+ }
+}
+
+/**
+ * Instances of the class `DirectiveElementBuilder` build elements for top
+ * level library directives.
+ */
+class DirectiveElementBuilder extends SimpleAstVisitor<Object> {
+ /**
+ * The analysis context within which directive elements are being built.
+ */
+ final AnalysisContext context;
+
+ /**
+ * The library element for which directive elements are being built.
+ */
+ final LibraryElementImpl libraryElement;
+
+ /**
+ * Map from sources referenced by this library to their modification times.
+ */
+ final Map<Source, int> sourceModificationTimeMap;
+
+ /**
+ * Map from sources imported by this library to their corresponding library
+ * elements.
+ */
+ final Map<Source, LibraryElement> importLibraryMap;
+
+ /**
+ * Map from sources imported by this library to their corresponding source
+ * kinds.
+ */
+ final Map<Source, SourceKind> importSourceKindMap;
+
+ /**
+ * Map from sources exported by this library to their corresponding library
+ * elements.
+ */
+ final Map<Source, LibraryElement> exportLibraryMap;
+
+ /**
+ * Map from sources exported by this library to their corresponding source
+ * kinds.
+ */
+ final Map<Source, SourceKind> exportSourceKindMap;
+
+ /**
+ * The [ImportElement]s created so far.
+ */
+ final List<ImportElement> imports = <ImportElement>[];
+
+ /**
+ * The [ExportElement]s created so far.
+ */
+ final List<ExportElement> exports = <ExportElement>[];
+
+ /**
+ * The errors found while building directive elements.
+ */
+ final List<AnalysisError> errors = <AnalysisError>[];
+
+ /**
+ * Map from prefix names to their corresponding elements.
+ */
+ final HashMap<String, PrefixElementImpl> nameToPrefixMap =
+ new HashMap<String, PrefixElementImpl>();
+
+ /**
+ * Indicates whether an explicit import of `dart:core` has been found.
+ */
+ bool explicitlyImportsCore = false;
+
+ DirectiveElementBuilder(
+ this.context,
+ this.libraryElement,
+ this.sourceModificationTimeMap,
+ this.importLibraryMap,
+ this.importSourceKindMap,
+ this.exportLibraryMap,
+ this.exportSourceKindMap);
+
+ @override
+ Object visitCompilationUnit(CompilationUnit node) {
+ //
+ // Resolve directives.
+ //
+ for (Directive directive in node.directives) {
+ directive.accept(this);
+ }
+ //
+ // Ensure "dart:core" import.
+ //
+ Source librarySource = libraryElement.source;
+ Source coreLibrarySource = context.sourceFactory.forUri(DartSdk.DART_CORE);
+ if (!explicitlyImportsCore && coreLibrarySource != librarySource) {
+ ImportElementImpl importElement = new ImportElementImpl(-1);
+ importElement.importedLibrary = importLibraryMap[coreLibrarySource];
+ importElement.synthetic = true;
+ imports.add(importElement);
+ }
+ //
+ // Populate the library element.
+ //
+ libraryElement.imports = imports;
+ libraryElement.exports = exports;
+ return null;
+ }
+
+ @override
+ Object visitExportDirective(ExportDirective node) {
+ // Remove previous element. (It will remain null if the target is missing.)
+ node.element = null;
+ Source exportedSource = node.selectedSource;
+ int exportedTime = sourceModificationTimeMap[exportedSource] ?? -1;
+ // The exported source will be null if the URI in the export
+ // directive was invalid.
+ LibraryElement exportedLibrary = exportLibraryMap[exportedSource];
+ if (exportedLibrary != null) {
+ ExportElementImpl exportElement = new ExportElementImpl(node.offset);
+ exportElement.metadata = _getElementAnnotations(node.metadata);
+ StringLiteral uriLiteral = node.uri;
+ if (uriLiteral != null) {
+ exportElement.uriOffset = uriLiteral.offset;
+ exportElement.uriEnd = uriLiteral.end;
+ }
+ exportElement.uri = node.selectedUriContent;
+ exportElement.combinators = _buildCombinators(node);
+ exportElement.exportedLibrary = exportedLibrary;
+ setElementDocumentationComment(exportElement, node);
+ node.element = exportElement;
+ exports.add(exportElement);
+ if (exportedTime >= 0 &&
+ exportSourceKindMap[exportedSource] != SourceKind.LIBRARY) {
+ int offset = node.offset;
+ int length = node.length;
+ if (uriLiteral != null) {
+ offset = uriLiteral.offset;
+ length = uriLiteral.length;
+ }
+ errors.add(new AnalysisError(
+ libraryElement.source,
+ offset,
+ length,
+ CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY,
+ [uriLiteral.toSource()]));
+ }
+ }
+ return null;
+ }
+
+ @override
+ Object visitImportDirective(ImportDirective node) {
+ // Remove previous element. (It will remain null if the target is missing.)
+ node.element = null;
+ Source importedSource = node.selectedSource;
+ int importedTime = sourceModificationTimeMap[importedSource] ?? -1;
+ // The imported source will be null if the URI in the import
+ // directive was invalid.
+ LibraryElement importedLibrary = importLibraryMap[importedSource];
+ if (importedLibrary != null) {
+ if (importedLibrary.isDartCore) {
+ explicitlyImportsCore = true;
+ }
+ ImportElementImpl importElement = new ImportElementImpl(node.offset);
+ importElement.metadata = _getElementAnnotations(node.metadata);
+ StringLiteral uriLiteral = node.uri;
+ if (uriLiteral != null) {
+ importElement.uriOffset = uriLiteral.offset;
+ importElement.uriEnd = uriLiteral.end;
+ }
+ importElement.uri = node.selectedUriContent;
+ importElement.deferred = node.deferredKeyword != null;
+ importElement.combinators = _buildCombinators(node);
+ importElement.importedLibrary = importedLibrary;
+ setElementDocumentationComment(importElement, node);
+ SimpleIdentifier prefixNode = node.prefix;
+ if (prefixNode != null) {
+ importElement.prefixOffset = prefixNode.offset;
+ String prefixName = prefixNode.name;
+ PrefixElementImpl prefix = nameToPrefixMap[prefixName];
+ if (prefix == null) {
+ prefix = new PrefixElementImpl.forNode(prefixNode);
+ nameToPrefixMap[prefixName] = prefix;
+ }
+ importElement.prefix = prefix;
+ prefixNode.staticElement = prefix;
+ }
+ node.element = importElement;
+ imports.add(importElement);
+ if (importedTime >= 0 &&
+ importSourceKindMap[importedSource] != SourceKind.LIBRARY) {
+ int offset = node.offset;
+ int length = node.length;
+ if (uriLiteral != null) {
+ offset = uriLiteral.offset;
+ length = uriLiteral.length;
+ }
+ ErrorCode errorCode = importElement.isDeferred
+ ? StaticWarningCode.IMPORT_OF_NON_LIBRARY
+ : CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY;
+ errors.add(new AnalysisError(libraryElement.source, offset, length,
+ errorCode, [uriLiteral.toSource()]));
+ }
+ }
+ return null;
+ }
+
+ @override
+ Object visitLibraryDirective(LibraryDirective node) {
+ (node.element as LibraryElementImpl)?.metadata =
+ _getElementAnnotations(node.metadata);
+ return null;
+ }
+
+ @override
+ Object visitPartDirective(PartDirective node) {
+ (node.element as CompilationUnitElementImpl)?.metadata =
+ _getElementAnnotations(node.metadata);
+ return null;
+ }
+
+ /**
+ * Gather a list of the [ElementAnnotation]s referred to by the [Annotation]s
+ * in [metadata].
+ */
+ List<ElementAnnotation> _getElementAnnotations(
+ NodeList<Annotation> metadata) {
+ if (metadata.isEmpty) {
+ return ElementAnnotation.EMPTY_LIST;
+ }
+ return metadata.map((Annotation a) => a.elementAnnotation).toList();
+ }
+
+ /**
+ * Build the element model representing the combinators declared by
+ * the given [directive].
+ */
+ static List<NamespaceCombinator> _buildCombinators(
+ NamespaceDirective directive) {
+ _NamespaceCombinatorBuilder namespaceCombinatorBuilder =
+ new _NamespaceCombinatorBuilder();
+ for (Combinator combinator in directive.combinators) {
+ combinator.accept(namespaceCombinatorBuilder);
+ }
+ return namespaceCombinatorBuilder.combinators;
+ }
+}
+
+/**
+ * Instances of the class `ElementBuilder` traverse an AST structure and build the element
+ * model representing the AST structure.
+ */
+class ElementBuilder extends ApiElementBuilder {
+ /**
+ * Initialize a newly created element builder to build the elements for a
+ * compilation unit. The [initialHolder] is the element holder to which the
+ * children of the visited compilation unit node will be added.
+ */
+ ElementBuilder(ElementHolder initialHolder,
+ CompilationUnitElement compilationUnitElement)
+ : super(initialHolder, compilationUnitElement);
+
+ @override
+ Object visitBlockFunctionBody(BlockFunctionBody node) {
+ _buildLocal(node);
+ return null;
+ }
+
+ @override
+ Object visitExpressionFunctionBody(ExpressionFunctionBody node) {
+ _buildLocal(node);
+ return null;
+ }
+
+ @override
+ Object visitVariableDeclaration(VariableDeclaration node) {
+ super.visitVariableDeclaration(node);
+ VariableElementImpl element = node.element as VariableElementImpl;
+ _buildVariableInitializer(element, node.initializer);
+ return null;
+ }
+
+ void _buildLocal(AstNode node) {
+ node.accept(
+ new LocalElementBuilder(_currentHolder, compilationUnitElement));
+ }
+}
+
+/**
+ * Traverse a [FunctionBody] and build elements for AST structures.
+ */
+class LocalElementBuilder extends _BaseElementBuilder {
+ /**
+ * Initialize a newly created element builder to build the elements for a
+ * compilation unit. The [initialHolder] is the element holder to which the
+ * children of the visited compilation unit node will be added.
+ */
+ LocalElementBuilder(ElementHolder initialHolder,
+ CompilationUnitElementImpl compilationUnitElement)
+ : super(initialHolder, compilationUnitElement);
+
+ @override
+ Object visitCatchClause(CatchClause node) {
+ SimpleIdentifier exceptionParameter = node.exceptionParameter;
+ if (exceptionParameter != null) {
+ // exception
+ LocalVariableElementImpl exception =
+ new LocalVariableElementImpl.forNode(exceptionParameter);
+ if (node.exceptionType == null) {
+ exception.hasImplicitType = true;
+ }
+ exception.setVisibleRange(node.offset, node.length);
+ _currentHolder.addLocalVariable(exception);
+ exceptionParameter.staticElement = exception;
+ // stack trace
+ SimpleIdentifier stackTraceParameter = node.stackTraceParameter;
+ if (stackTraceParameter != null) {
+ LocalVariableElementImpl stackTrace =
+ new LocalVariableElementImpl.forNode(stackTraceParameter);
+ _setCodeRange(stackTrace, stackTraceParameter);
+ stackTrace.setVisibleRange(node.offset, node.length);
+ _currentHolder.addLocalVariable(stackTrace);
+ stackTraceParameter.staticElement = stackTrace;
+ }
+ }
+ return super.visitCatchClause(node);
+ }
+
+ @override
+ Object visitDeclaredIdentifier(DeclaredIdentifier node) {
+ SimpleIdentifier variableName = node.identifier;
+ LocalVariableElementImpl element =
+ new LocalVariableElementImpl.forNode(variableName);
+ _setCodeRange(element, node);
+ element.metadata = _createElementAnnotations(node.metadata);
+ ForEachStatement statement = node.parent as ForEachStatement;
+ element.setVisibleRange(statement.offset, statement.length);
+ element.const3 = node.isConst;
+ element.final2 = node.isFinal;
+ if (node.type == null) {
+ element.hasImplicitType = true;
+ }
+ _currentHolder.addLocalVariable(element);
+ variableName.staticElement = element;
+ return null;
+ }
+
+ @override
+ Object visitFunctionDeclaration(FunctionDeclaration node) {
+ FunctionExpression expression = node.functionExpression;
+ if (expression == null) {
+ return null;
+ }
+
+ ElementHolder holder = new ElementHolder();
+ _visitChildren(holder, node);
+
+ FunctionElementImpl element = new FunctionElementImpl.forNode(node.name);
+ _setCodeRange(element, node);
+ setElementDocumentationComment(element, node);
+ element.metadata = _createElementAnnotations(node.metadata);
+ if (node.externalKeyword != null) {
+ element.external = true;
+ }
+ element.functions = holder.functions;
+ element.labels = holder.labels;
+ element.localVariables = holder.localVariables;
+ element.parameters = holder.parameters;
+ element.typeParameters = holder.typeParameters;
+
+ FunctionBody body = expression.body;
+ if (body.isAsynchronous) {
+ element.asynchronous = body.isAsynchronous;
+ }
+ if (body.isGenerator) {
+ element.generator = true;
+ }
+
+ {
+ Block enclosingBlock = node.getAncestor((node) => node is Block);
+ if (enclosingBlock != null) {
+ element.setVisibleRange(enclosingBlock.offset, enclosingBlock.length);
+ }
+ }
+
+ if (node.returnType == null) {
+ element.hasImplicitReturnType = true;
+ }
+
+ _currentHolder.addFunction(element);
+ expression.element = element;
+ node.name.staticElement = element;
+ holder.validate();
+ return null;
+ }
+
+ @override
+ Object visitFunctionExpression(FunctionExpression node) {
+ if (node.parent is FunctionDeclaration) {
+ // visitFunctionDeclaration has already created the element for the
+ // declaration. We just need to visit children.
+ return super.visitFunctionExpression(node);
+ }
+
+ ElementHolder holder = new ElementHolder();
+ _visitChildren(holder, node);
+ FunctionElementImpl element =
+ new FunctionElementImpl.forOffset(node.beginToken.offset);
+ _setCodeRange(element, node);
+ element.functions = holder.functions;
+ element.labels = holder.labels;
+ element.localVariables = holder.localVariables;
+ element.parameters = holder.parameters;
+ element.typeParameters = holder.typeParameters;
+
+ FunctionBody body = node.body;
+ if (body.isAsynchronous) {
+ element.asynchronous = true;
+ }
+ if (body.isGenerator) {
+ element.generator = true;
+ }
+
+ {
+ Block enclosingBlock = node.getAncestor((node) => node is Block);
+ if (enclosingBlock != null) {
+ element.setVisibleRange(enclosingBlock.offset, enclosingBlock.length);
+ }
+ }
+
+ element.type = new FunctionTypeImpl(element);
+ element.hasImplicitReturnType = true;
+ _currentHolder.addFunction(element);
+ node.element = element;
+ holder.validate();
+ return null;
+ }
+
+ @override
+ Object visitLabeledStatement(LabeledStatement node) {
+ bool onSwitchStatement = node.statement is SwitchStatement;
+ for (Label label in node.labels) {
+ SimpleIdentifier labelName = label.label;
+ LabelElementImpl element =
+ new LabelElementImpl.forNode(labelName, onSwitchStatement, false);
+ _currentHolder.addLabel(element);
+ labelName.staticElement = element;
+ }
+ return super.visitLabeledStatement(node);
+ }
+
+ @override
+ Object visitSwitchCase(SwitchCase node) {
+ for (Label label in node.labels) {
+ SimpleIdentifier labelName = label.label;
+ LabelElementImpl element =
+ new LabelElementImpl.forNode(labelName, false, true);
+ _currentHolder.addLabel(element);
+ labelName.staticElement = element;
+ }
+ return super.visitSwitchCase(node);
+ }
+
+ @override
+ Object visitSwitchDefault(SwitchDefault node) {
+ for (Label label in node.labels) {
+ SimpleIdentifier labelName = label.label;
+ LabelElementImpl element =
+ new LabelElementImpl.forNode(labelName, false, true);
+ _currentHolder.addLabel(element);
+ labelName.staticElement = element;
+ }
+ return super.visitSwitchDefault(node);
+ }
+
+ @override
+ Object visitVariableDeclaration(VariableDeclaration node) {
+ bool isConst = node.isConst;
+ bool isFinal = node.isFinal;
+ Expression initializerNode = node.initializer;
+ VariableDeclarationList varList = node.parent;
+ SimpleIdentifier variableName = node.name;
+ LocalVariableElementImpl element;
+ if (isConst && initializerNode != null) {
+ element = new ConstLocalVariableElementImpl.forNode(variableName);
+ } else {
+ element = new LocalVariableElementImpl.forNode(variableName);
+ }
+ _setCodeRange(element, node);
+ _setVariableVisibleRange(element, node);
+ element.hasImplicitType = varList.type == null;
+ _currentHolder.addLocalVariable(element);
+ variableName.staticElement = element;
+ element.const3 = isConst;
+ element.final2 = isFinal;
+ _buildVariableInitializer(element, initializerNode);
+ return null;
+ }
+
+ @override
+ Object visitVariableDeclarationList(VariableDeclarationList node) {
+ super.visitVariableDeclarationList(node);
+ List<ElementAnnotation> elementAnnotations =
+ _createElementAnnotations(node.metadata);
+ _setVariableDeclarationListAnnotations(node, elementAnnotations);
+ return null;
+ }
+
+ void _setVariableVisibleRange(
+ LocalVariableElementImpl element, VariableDeclaration node) {
+ AstNode scopeNode;
+ AstNode parent2 = node.parent.parent;
+ if (parent2 is ForStatement) {
+ scopeNode = parent2;
+ } else {
+ scopeNode = node.getAncestor((node) => node is Block);
+ }
+ element.setVisibleRange(scopeNode.offset, scopeNode.length);
+ }
+}
+
+/**
+ * Base class for API and local element builders.
+ */
+abstract class _BaseElementBuilder extends RecursiveAstVisitor<Object> {
+ /**
+ * The compilation unit element into which the elements being built will be
+ * stored.
+ */
+ final CompilationUnitElementImpl compilationUnitElement;
+
+ /**
+ * The element holder associated with the element that is currently being built.
+ */
+ ElementHolder _currentHolder;
+
+ _BaseElementBuilder(this._currentHolder, this.compilationUnitElement);
+
+ @override
+ Object visitDefaultFormalParameter(DefaultFormalParameter node) {
+ ElementHolder holder = new ElementHolder();
+ NormalFormalParameter normalParameter = node.parameter;
+ SimpleIdentifier parameterName = normalParameter.identifier;
+ ParameterElementImpl parameter;
+ if (normalParameter is FieldFormalParameter) {
+ DefaultFieldFormalParameterElementImpl fieldParameter =
+ new DefaultFieldFormalParameterElementImpl.forNode(parameterName);
+ _setFieldParameterField(fieldParameter);
+ parameter = fieldParameter;
+ } else {
+ parameter = new DefaultParameterElementImpl.forNode(parameterName);
+ }
+ _setCodeRange(parameter, node);
+ parameter.const3 = node.isConst;
+ parameter.final2 = node.isFinal;
+ parameter.parameterKind = node.kind;
+ // set initializer, default value range
+ Expression defaultValue = node.defaultValue;
+ if (defaultValue != null) {
+ _visit(holder, defaultValue);
+ FunctionElementImpl initializer =
+ new FunctionElementImpl.forOffset(defaultValue.beginToken.offset);
+ initializer.hasImplicitReturnType = true;
+ initializer.functions = holder.functions;
+ initializer.labels = holder.labels;
+ initializer.localVariables = holder.localVariables;
+ initializer.parameters = holder.parameters;
+ initializer.synthetic = true;
+ initializer.type = new FunctionTypeImpl(initializer);
+ parameter.initializer = initializer;
+ parameter.defaultValueCode = defaultValue.toSource();
+ }
+ // visible range
+ _setParameterVisibleRange(node, parameter);
+ if (normalParameter is SimpleFormalParameter &&
+ normalParameter.type == null) {
+ parameter.hasImplicitType = true;
+ }
+ _currentHolder.addParameter(parameter);
+ parameterName.staticElement = parameter;
+ normalParameter.accept(this);
+ holder.validate();
+ return null;
+ }
+
+ @override
+ Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
+ if (node.parent is! DefaultFormalParameter) {
+ SimpleIdentifier parameterName = node.identifier;
+ ParameterElementImpl parameter =
+ new ParameterElementImpl.forNode(parameterName);
+ _setCodeRange(parameter, node);
+ parameter.parameterKind = node.kind;
+ _setParameterVisibleRange(node, parameter);
+ _currentHolder.addParameter(parameter);
+ parameterName.staticElement = parameter;
+ }
+ //
+ // The children of this parameter include any parameters defined on the type
+ //of this parameter.
+ //
+ ElementHolder holder = new ElementHolder();
+ _visitChildren(holder, node);
+ ParameterElementImpl element = node.element;
+ element.metadata = _createElementAnnotations(node.metadata);
+ element.parameters = holder.parameters;
+ element.typeParameters = holder.typeParameters;
+ holder.validate();
+ return null;
}
@override
@@ -1094,30 +1456,6 @@ class ElementBuilder extends RecursiveAstVisitor<Object> {
}
@override
- Object visitSwitchCase(SwitchCase node) {
- for (Label label in node.labels) {
- SimpleIdentifier labelName = label.label;
- LabelElementImpl element =
- new LabelElementImpl.forNode(labelName, false, true);
- _currentHolder.addLabel(element);
- labelName.staticElement = element;
- }
- return super.visitSwitchCase(node);
- }
-
- @override
- Object visitSwitchDefault(SwitchDefault node) {
- for (Label label in node.labels) {
- SimpleIdentifier labelName = label.label;
- LabelElementImpl element =
- new LabelElementImpl.forNode(labelName, false, true);
- _currentHolder.addLabel(element);
- labelName.staticElement = element;
- }
- return super.visitSwitchDefault(node);
- }
-
- @override
Object visitTypeParameter(TypeParameter node) {
SimpleIdentifier parameterName = node.name;
TypeParameterElementImpl typeParameter =
@@ -1132,68 +1470,12 @@ class ElementBuilder extends RecursiveAstVisitor<Object> {
return super.visitTypeParameter(node);
}
- @override
- Object visitVariableDeclaration(VariableDeclaration node) {
- bool isConst = node.isConst;
- bool isFinal = node.isFinal;
- bool hasInitializer = node.initializer != null;
- VariableDeclarationList varList = node.parent;
- FieldDeclaration fieldNode =
- varList.parent is FieldDeclaration ? varList.parent : null;
- VariableElementImpl element;
- if (fieldNode != null) {
- SimpleIdentifier fieldName = node.name;
- FieldElementImpl field;
- if ((isConst || isFinal && !fieldNode.isStatic) && hasInitializer) {
- field = new ConstFieldElementImpl.forNode(fieldName);
- } else {
- field = new FieldElementImpl.forNode(fieldName);
- }
- element = field;
- field.static = fieldNode.isStatic;
- _setCodeRange(element, node);
- setElementDocumentationComment(element, fieldNode);
- field.hasImplicitType = varList.type == null;
- _currentHolder.addField(field);
- fieldName.staticElement = field;
- } else if (_inFunction) {
- SimpleIdentifier variableName = node.name;
- LocalVariableElementImpl variable;
- if (isConst && hasInitializer) {
- variable = new ConstLocalVariableElementImpl.forNode(variableName);
- } else {
- variable = new LocalVariableElementImpl.forNode(variableName);
- }
- element = variable;
- _setCodeRange(element, node);
- _setVariableVisibleRange(variable, node);
- variable.hasImplicitType = varList.type == null;
- _currentHolder.addLocalVariable(variable);
- variableName.staticElement = element;
- } else {
- SimpleIdentifier variableName = node.name;
- TopLevelVariableElementImpl variable;
- if (isConst && hasInitializer) {
- variable = new ConstTopLevelVariableElementImpl.forNode(variableName);
- } else {
- variable = new TopLevelVariableElementImpl.forNode(variableName);
- }
- element = variable;
- _setCodeRange(element, node);
- if (varList.parent is TopLevelVariableDeclaration) {
- setElementDocumentationComment(element, varList.parent);
- }
- variable.hasImplicitType = varList.type == null;
- _currentHolder.addTopLevelVariable(variable);
- variableName.staticElement = element;
- }
- element.const3 = isConst;
- element.final2 = isFinal;
- if (hasInitializer) {
+ void _buildVariableInitializer(VariableElementImpl element, Expression node) {
+ if (node != null) {
ElementHolder holder = new ElementHolder();
- _visit(holder, node.initializer);
+ _visit(holder, node);
FunctionElementImpl initializer =
- new FunctionElementImpl.forOffset(node.initializer.beginToken.offset);
+ new FunctionElementImpl.forOffset(node.beginToken.offset);
initializer.hasImplicitReturnType = true;
initializer.functions = holder.functions;
initializer.labels = holder.labels;
@@ -1203,68 +1485,6 @@ class ElementBuilder extends RecursiveAstVisitor<Object> {
element.initializer = initializer;
holder.validate();
}
- if (element is PropertyInducingElementImpl) {
- PropertyAccessorElementImpl_ImplicitGetter getter =
- new PropertyAccessorElementImpl_ImplicitGetter(element);
- _currentHolder.addAccessor(getter);
- if (!isConst && !isFinal) {
- PropertyAccessorElementImpl_ImplicitSetter setter =
- new PropertyAccessorElementImpl_ImplicitSetter(element);
- _currentHolder.addAccessor(setter);
- }
- }
- return null;
- }
-
- @override
- Object visitVariableDeclarationList(VariableDeclarationList node) {
- super.visitVariableDeclarationList(node);
- AstNode parent = node.parent;
- List<ElementAnnotation> elementAnnotations;
- if (parent is FieldDeclaration) {
- elementAnnotations = _createElementAnnotations(parent.metadata);
- } else if (parent is TopLevelVariableDeclaration) {
- elementAnnotations = _createElementAnnotations(parent.metadata);
- } else {
- // Local variable declaration
- elementAnnotations = _createElementAnnotations(node.metadata);
- }
- for (VariableDeclaration variableDeclaration in node.variables) {
- ElementImpl element = variableDeclaration.element as ElementImpl;
- _setCodeRange(element, node.parent);
- element.metadata = elementAnnotations;
- }
- return null;
- }
-
- /**
- * Build the table mapping field names to field elements for the fields defined in the current
- * class.
- *
- * @param fields the field elements defined in the current class
- */
- void _buildFieldMap(List<FieldElement> fields) {
- _fieldMap = new HashMap<String, FieldElement>();
- int count = fields.length;
- for (int i = 0; i < count; i++) {
- FieldElement field = fields[i];
- _fieldMap[field.name] ??= field;
- }
- }
-
- /**
- * Creates the [ConstructorElement]s array with the single default constructor element.
- *
- * @param interfaceType the interface type for which to create a default constructor
- * @return the [ConstructorElement]s array with the single default constructor element
- */
- List<ConstructorElement> _createDefaultConstructors(
- ClassElementImpl definingClass) {
- ConstructorElementImpl constructor =
- new ConstructorElementImpl.forNode(null);
- constructor.synthetic = true;
- constructor.enclosingElement = definingClass;
- return <ConstructorElement>[constructor];
}
/**
@@ -1285,28 +1505,6 @@ class ElementBuilder extends RecursiveAstVisitor<Object> {
}
/**
- * Create the types associated with the given type parameters, setting the type of each type
- * parameter, and return an array of types corresponding to the given parameters.
- *
- * @param typeParameters the type parameters for which types are to be created
- * @return an array of types corresponding to the given parameters
- */
- List<DartType> _createTypeParameterTypes(
- List<TypeParameterElement> typeParameters) {
- int typeParameterCount = typeParameters.length;
- List<DartType> typeArguments = new List<DartType>(typeParameterCount);
- for (int i = 0; i < typeParameterCount; i++) {
- TypeParameterElementImpl typeParameter =
- typeParameters[i] as TypeParameterElementImpl;
- TypeParameterTypeImpl typeParameterType =
- new TypeParameterTypeImpl(typeParameter);
- typeParameter.type = typeParameterType;
- typeArguments[i] = typeParameterType;
- }
- return typeArguments;
- }
-
- /**
* Return the body of the function that contains the given [parameter], or
* `null` if no function body could be found.
*/
@@ -1326,6 +1524,8 @@ class ElementBuilder extends RecursiveAstVisitor<Object> {
element.setCodeRange(node.offset, node.length);
}
+ void _setFieldParameterField(FieldFormalParameterElementImpl parameter) {}
+
/**
* Sets the visible source range for formal parameter.
*/
@@ -1337,16 +1537,13 @@ class ElementBuilder extends RecursiveAstVisitor<Object> {
}
}
- void _setVariableVisibleRange(
- LocalVariableElementImpl element, VariableDeclaration node) {
- AstNode scopeNode;
- AstNode parent2 = node.parent.parent;
- if (parent2 is ForStatement) {
- scopeNode = parent2;
- } else {
- scopeNode = node.getAncestor((node) => node is Block);
+ void _setVariableDeclarationListAnnotations(VariableDeclarationList node,
+ List<ElementAnnotation> elementAnnotations) {
+ for (VariableDeclaration variableDeclaration in node.variables) {
+ ElementImpl element = variableDeclaration.element as ElementImpl;
+ _setCodeRange(element, node.parent);
+ element.metadata = elementAnnotations;
}
- element.setVisibleRange(scopeNode.offset, scopeNode.length);
}
/**
« no previous file with comments | « no previous file | pkg/analyzer/test/generated/all_the_rest_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698