| 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);
|
| }
|
|
|
| /**
|
|
|