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

Unified Diff: pkg/analyzer/lib/src/summary/resynthesize.dart

Issue 1833743002: Resynthesize _DeferredClassElement instead of actual ClassElementImpl. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/analyzer/lib/src/summary/resynthesize.dart
diff --git a/pkg/analyzer/lib/src/summary/resynthesize.dart b/pkg/analyzer/lib/src/summary/resynthesize.dart
index 59117e144fb1faa3202cc353c87f6a27cfc8a7ca..63099c5150d4098f80c565f239b4d7eba81ab90d 100644
--- a/pkg/analyzer/lib/src/summary/resynthesize.dart
+++ b/pkg/analyzer/lib/src/summary/resynthesize.dart
@@ -272,7 +272,7 @@ abstract class SummaryResynthesizer extends ElementResynthesizer {
* Builder of [Expression]s from [UnlinkedConst]s.
*/
class _ConstExprBuilder {
- final _LibraryResynthesizer resynthesizer;
+ final _UnitResynthesizer resynthesizer;
final UnlinkedConst uc;
int intPtr = 0;
@@ -645,6 +645,59 @@ class _ConstExprBuilder {
}
/**
+ * The class element that has been resynthesized from a summary. The actual
Paul Berry 2016/03/24 19:40:14 s/The class element/A class element/
+ * element won't be constructed until it is requested. But properties
+ * [context], [displayName], [enclosingElement] and [name] can be used without
+ * creating the actual element. This allows to put these elements into
+ * namespaces without creating actual elements until they are really needed.
+ */
+class _DeferredClassElement extends ClassElementHandle {
+ final _UnitResynthesizer unitResynthesizer;
+ final CompilationUnitElement unitElement;
+ final UnlinkedClass serializedClass;
+
+ ClassElementImpl _actualElement;
+
+ @override
+ final String name;
+
+ factory _DeferredClassElement(_UnitResynthesizer unitResynthesizer,
+ CompilationUnitElement unitElement, UnlinkedClass serializedClass) {
+ String name = serializedClass.name;
+ List<String> components =
+ unitResynthesizer.unit.location.components.toList();
+ components.add(name);
+ ElementLocationImpl location = new ElementLocationImpl.con3(components);
+ return new _DeferredClassElement._(
+ unitResynthesizer, unitElement, serializedClass, name, location);
+ }
+
+ _DeferredClassElement._(this.unitResynthesizer, this.unitElement,
+ this.serializedClass, this.name, ElementLocation location)
+ : super(null, location);
+
+ @override
+ ClassElementImpl get actualElement {
+ if (_actualElement == null) {
+ _actualElement = unitResynthesizer.buildClassImpl(serializedClass);
+ _actualElement.enclosingElement = unitElement;
+ }
+ return _actualElement;
+ }
+
+ @override
+ AnalysisContext get context => unitElement.context;
+
+ @override
+ String get displayName => name;
+
+ @override
+ CompilationUnitElement get enclosingElement {
+ return unitElement;
+ }
+}
+
+/**
* The constructor element that has been resynthesized from a summary. The
* actual element won't be constructed until it is requested. But properties
* [displayName], [enclosingElement] and [name] can be used without creating
@@ -690,7 +743,7 @@ class _DeferredConstructorElement extends ConstructorElementHandle {
}
/**
- * Local function element representing the intializer for a variable that has
+ * Local function element representing the initializer for a variable that has
* been resynthesized from a summary. The actual element won't be constructed
* until it is requested. But properties [context] and [enclosingElement] can
* be used without creating the actual element.
@@ -786,63 +839,569 @@ class _DeferredLocalVariableElement extends LocalVariableElementHandle {
}
/**
- * An instance of [_LibraryResynthesizer] is responsible for resynthesizing the
- * elements in a single library from that library's summary.
+ * An instance of [_LibraryResynthesizer] is responsible for resynthesizing the
+ * elements in a single library from that library's summary.
+ */
+class _LibraryResynthesizer {
+ /**
+ * The [SummaryResynthesizer] which is being used to obtain summaries.
+ */
+ final SummaryResynthesizer summaryResynthesizer;
+
+ /**
+ * Linked summary of the library to be resynthesized.
+ */
+ final LinkedLibrary linkedLibrary;
+
+ /**
+ * Unlinked compilation units constituting the library to be resynthesized.
+ */
+ final List<UnlinkedUnit> unlinkedUnits;
+
+ /**
+ * [Source] object for the library to be resynthesized.
+ */
+ final Source librarySource;
+
+ /**
+ * Indicates whether [librarySource] is the `dart:core` library.
+ */
+ bool isCoreLibrary;
+
+ /**
+ * Classes which should have their supertype set to "object" once
+ * resynthesis is complete. Only used if [isCoreLibrary] is `true`.
+ */
+ List<ClassElementImpl> delayedObjectSubclasses = <ClassElementImpl>[];
+
+ /**
+ * Map of compilation unit elements that have been resynthesized so far. The
+ * key is the URI of the compilation unit.
+ */
+ final Map<String, CompilationUnitElement> resynthesizedUnits =
+ <String, CompilationUnitElement>{};
+
+ /**
+ * Map of top level elements that have been resynthesized so far. The first
+ * key is the URI of the compilation unit; the second is the name of the top
+ * level element.
+ */
+ final Map<String, Map<String, Element>> resynthesizedElements =
+ <String, Map<String, Element>>{};
+
+ _LibraryResynthesizer(this.summaryResynthesizer, this.linkedLibrary,
+ this.unlinkedUnits, this.librarySource) {
+ isCoreLibrary = librarySource.uri.toString() == 'dart:core';
+ }
+
+ /**
+ * Resynthesize a [NamespaceCombinator].
+ */
+ NamespaceCombinator buildCombinator(UnlinkedCombinator serializedCombinator) {
+ if (serializedCombinator.shows.isNotEmpty) {
+ ShowElementCombinatorImpl combinator = new ShowElementCombinatorImpl();
+ // Note: we call toList() so that we don't retain a reference to the
+ // deserialized data structure.
+ combinator.shownNames = serializedCombinator.shows.toList();
+ combinator.offset = serializedCombinator.offset;
+ combinator.end = serializedCombinator.end;
+ return combinator;
+ } else {
+ HideElementCombinatorImpl combinator = new HideElementCombinatorImpl();
+ // Note: we call toList() so that we don't retain a reference to the
+ // deserialized data structure.
+ combinator.hiddenNames = serializedCombinator.hides.toList();
+ return combinator;
+ }
+ }
+
+ /**
+ * Resynthesize an [ExportElement],
+ */
+ ExportElement buildExport(
+ _UnitResynthesizer definingUnitResynthesizer,
+ UnlinkedExportPublic serializedExportPublic,
+ UnlinkedExportNonPublic serializedExportNonPublic) {
+ ExportElementImpl exportElement =
+ new ExportElementImpl(serializedExportNonPublic.offset);
+ String exportedLibraryUri = summaryResynthesizer.sourceFactory
+ .resolveUri(librarySource, serializedExportPublic.uri)
+ .uri
+ .toString();
+ exportElement.exportedLibrary = new LibraryElementHandle(
+ summaryResynthesizer,
+ new ElementLocationImpl.con3(<String>[exportedLibraryUri]));
+ exportElement.uri = serializedExportPublic.uri;
+ exportElement.combinators =
+ serializedExportPublic.combinators.map(buildCombinator).toList();
+ exportElement.uriOffset = serializedExportNonPublic.uriOffset;
+ exportElement.uriEnd = serializedExportNonPublic.uriEnd;
+ definingUnitResynthesizer.buildAnnotations(
+ exportElement, serializedExportNonPublic.annotations);
+ return exportElement;
+ }
+
+ /**
+ * Build an [ElementHandle] referring to the entity referred to by the given
+ * [exportName].
+ */
+ ElementHandle buildExportName(LinkedExportName exportName) {
+ String name = exportName.name;
+ if (exportName.kind == ReferenceKind.topLevelPropertyAccessor &&
+ !name.endsWith('=')) {
+ name += '?';
+ }
+ ElementLocationImpl location = new ElementLocationImpl.con3(
+ getReferencedLocationComponents(
+ exportName.dependency, exportName.unit, name));
+ switch (exportName.kind) {
+ case ReferenceKind.classOrEnum:
+ return new ClassElementHandle(summaryResynthesizer, location);
+ case ReferenceKind.typedef:
+ return new FunctionTypeAliasElementHandle(
+ summaryResynthesizer, location);
+ case ReferenceKind.topLevelFunction:
+ return new FunctionElementHandle(summaryResynthesizer, location);
+ case ReferenceKind.topLevelPropertyAccessor:
+ return new PropertyAccessorElementHandle(
+ summaryResynthesizer, location);
+ case ReferenceKind.constructor:
+ case ReferenceKind.function:
+ case ReferenceKind.propertyAccessor:
+ case ReferenceKind.method:
+ case ReferenceKind.length:
+ case ReferenceKind.prefix:
+ case ReferenceKind.unresolved:
+ case ReferenceKind.variable:
+ // Should never happen. Exported names never refer to import prefixes,
+ // and they always refer to defined top-level entities.
+ throw new StateError('Unexpected export name kind: ${exportName.kind}');
+ }
+ }
+
+ /**
+ * Build the export namespace for the library by aggregating together its
+ * [publicNamespace] and [exportNames].
+ */
+ Namespace buildExportNamespace(
+ Namespace publicNamespace, List<LinkedExportName> exportNames) {
+ HashMap<String, Element> definedNames = new HashMap<String, Element>();
+ // Start by populating all the public names from [publicNamespace].
+ publicNamespace.definedNames.forEach((String name, Element element) {
+ definedNames[name] = element;
+ });
+ // Add all the names from [exportNames].
+ for (LinkedExportName exportName in exportNames) {
+ definedNames.putIfAbsent(
+ exportName.name, () => buildExportName(exportName));
+ }
+ return new Namespace(definedNames);
+ }
+
+ /**
+ * Resynthesize an [ImportElement].
+ */
+ ImportElement buildImport(_UnitResynthesizer definingUnitResynthesizer,
+ UnlinkedImport serializedImport, int dependency) {
+ bool isSynthetic = serializedImport.isImplicit;
+ ImportElementImpl importElement =
+ new ImportElementImpl(isSynthetic ? -1 : serializedImport.offset);
+ String absoluteUri = summaryResynthesizer.sourceFactory
+ .resolveUri(librarySource, linkedLibrary.dependencies[dependency].uri)
+ .uri
+ .toString();
+ importElement.importedLibrary = new LibraryElementHandle(
+ summaryResynthesizer,
+ new ElementLocationImpl.con3(<String>[absoluteUri]));
+ if (isSynthetic) {
+ importElement.synthetic = true;
+ } else {
+ importElement.uri = serializedImport.uri;
+ importElement.uriOffset = serializedImport.uriOffset;
+ importElement.uriEnd = serializedImport.uriEnd;
+ importElement.deferred = serializedImport.isDeferred;
+ definingUnitResynthesizer.buildAnnotations(
+ importElement, serializedImport.annotations);
+ }
+ importElement.prefixOffset = serializedImport.prefixOffset;
+ if (serializedImport.prefixReference != 0) {
+ UnlinkedReference serializedPrefix =
+ unlinkedUnits[0].references[serializedImport.prefixReference];
+ importElement.prefix = new PrefixElementImpl(
+ serializedPrefix.name, serializedImport.prefixOffset);
+ }
+ importElement.combinators =
+ serializedImport.combinators.map(buildCombinator).toList();
+ return importElement;
+ }
+
+ /**
+ * Main entry point. Resynthesize the [LibraryElement] and return it.
+ */
+ LibraryElement buildLibrary() {
+ CompilationUnitElementImpl definingUnit =
+ new CompilationUnitElementImpl(librarySource.shortName);
+ _UnitResynthesizer definingUnitResynthesizer =
+ createUnitResynthesizer(definingUnit, 0);
+ // Create LibraryElementImpl.
+ bool hasName = unlinkedUnits[0].libraryName.isNotEmpty;
+ LibraryElementImpl library = new LibraryElementImpl(
+ summaryResynthesizer.context,
+ unlinkedUnits[0].libraryName,
+ hasName ? unlinkedUnits[0].libraryNameOffset : -1,
+ unlinkedUnits[0].libraryNameLength);
+ definingUnitResynthesizer.buildDocumentation(
+ library, unlinkedUnits[0].libraryDocumentationComment);
+ definingUnitResynthesizer.buildAnnotations(
+ library, unlinkedUnits[0].libraryAnnotations);
+ library.definingCompilationUnit = definingUnit;
+ definingUnit.source = librarySource;
+ definingUnit.librarySource = librarySource;
+ // Create parts.
+ List<CompilationUnitElement> partUnits = <CompilationUnitElement>[];
+ UnlinkedUnit unlinkedDefiningUnit = unlinkedUnits[0];
+ assert(unlinkedDefiningUnit.publicNamespace.parts.length + 1 ==
+ linkedLibrary.units.length);
+ for (int i = 1; i < linkedLibrary.units.length; i++) {
+ CompilationUnitElementImpl part = buildPart(
+ definingUnitResynthesizer,
+ unlinkedDefiningUnit.publicNamespace.parts[i - 1],
+ unlinkedDefiningUnit.parts[i - 1],
+ i);
+ partUnits.add(part);
+ }
+ library.parts = partUnits;
+ // Create imports.
+ List<ImportElement> imports = <ImportElement>[];
+ for (int i = 0; i < unlinkedDefiningUnit.imports.length; i++) {
+ imports.add(buildImport(
+ definingUnitResynthesizer,
+ unlinkedDefiningUnit.imports[i],
+ linkedLibrary.importDependencies[i]));
+ }
+ library.imports = imports;
+ // Create exports.
+ List<ExportElement> exports = <ExportElement>[];
+ assert(unlinkedDefiningUnit.exports.length ==
+ unlinkedDefiningUnit.publicNamespace.exports.length);
+ for (int i = 0; i < unlinkedDefiningUnit.exports.length; i++) {
+ exports.add(buildExport(
+ definingUnitResynthesizer,
+ unlinkedDefiningUnit.publicNamespace.exports[i],
+ unlinkedDefiningUnit.exports[i]));
+ }
+ library.exports = exports;
+ // Populate units.
+ populateUnit(definingUnitResynthesizer);
+ for (int i = 0; i < partUnits.length; i++) {
+ _UnitResynthesizer partResynthesizer =
+ createUnitResynthesizer(partUnits[i], i + 1);
+ populateUnit(partResynthesizer);
+ }
+ BuildLibraryElementUtils.patchTopLevelAccessors(library);
+ // Update delayed Object class references.
+ if (isCoreLibrary) {
+ ClassElement objectElement = library.getType('Object');
+ assert(objectElement != null);
+ for (ClassElementImpl classElement in delayedObjectSubclasses) {
+ classElement.supertype = objectElement.type;
+ }
+ }
+ // Compute namespaces.
+ library.publicNamespace =
+ new NamespaceBuilder().createPublicNamespaceForLibrary(library);
+ library.exportNamespace = buildExportNamespace(
+ library.publicNamespace, linkedLibrary.exportNames);
+ // Find the entry point. Note: we can't use element.isEntryPoint because
+ // that will trigger resynthesis of exported libraries.
+ Element entryPoint =
+ library.exportNamespace.get(FunctionElement.MAIN_FUNCTION_NAME);
+ if (entryPoint is FunctionElement) {
+ library.entryPoint = entryPoint;
+ }
+ // Create the synthetic element for `loadLibrary`.
+ // Until the client received dart:core and dart:async, we cannot do this,
+ // because the TypeProvider is not fully initialized. So, it is up to the
+ // Dart SDK client to initialize TypeProvider and finish the dart:core and
+ // dart:async libraries creation.
+ if (library.name != 'dart.core' && library.name != 'dart.async') {
+ library.createLoadLibraryFunction(summaryResynthesizer.typeProvider);
+ }
+ // Done.
+ return library;
+ }
+
+ /**
+ * Create, but do not populate, the [CompilationUnitElement] for a part other
+ * than the defining compilation unit.
+ */
+ CompilationUnitElementImpl buildPart(
+ _UnitResynthesizer definingUnitResynthesizer,
+ String uri,
+ UnlinkedPart partDecl,
+ int unitNum) {
+ Source unitSource =
+ summaryResynthesizer.sourceFactory.resolveUri(librarySource, uri);
+ CompilationUnitElementImpl partUnit =
+ new CompilationUnitElementImpl(unitSource.shortName);
+ partUnit.uriOffset = partDecl.uriOffset;
+ partUnit.uriEnd = partDecl.uriEnd;
+ partUnit.source = unitSource;
+ partUnit.librarySource = librarySource;
+ partUnit.uri = uri;
+ definingUnitResynthesizer.buildAnnotations(partUnit, partDecl.annotations);
+ return partUnit;
+ }
+
+ /**
+ * Set up data structures for deserializing a compilation unit.
+ */
+ _UnitResynthesizer createUnitResynthesizer(
+ CompilationUnitElementImpl unit, int unitNum) {
+ LinkedUnit linkedUnit = linkedLibrary.units[unitNum];
+ UnlinkedUnit unlinkedUnit = unlinkedUnits[unitNum];
+ return new _UnitResynthesizer(this, unlinkedUnit, linkedUnit, unit);
+ }
+
+ /**
+ * Build the components of an [ElementLocationImpl] for the entity in the
+ * given [unit] of the dependency located at [dependencyIndex], and having
+ * the given [name].
+ */
+ List<String> getReferencedLocationComponents(
+ int dependencyIndex, int unit, String name) {
+ if (dependencyIndex == 0) {
+ String referencedLibraryUri = librarySource.uri.toString();
+ String partUri;
+ if (unit != 0) {
+ String uri = unlinkedUnits[0].publicNamespace.parts[unit - 1];
+ Source partSource =
+ summaryResynthesizer.sourceFactory.resolveUri(librarySource, uri);
+ partUri = partSource.uri.toString();
+ } else {
+ partUri = referencedLibraryUri;
+ }
+ return <String>[referencedLibraryUri, partUri, name];
+ }
+ LinkedDependency dependency = linkedLibrary.dependencies[dependencyIndex];
+ Source referencedLibrarySource = summaryResynthesizer.sourceFactory
+ .resolveUri(librarySource, dependency.uri);
+ String referencedLibraryUri = referencedLibrarySource.uri.toString();
+ String partUri;
+ if (unit != 0) {
+ String uri = dependency.parts[unit - 1];
+ Source partSource = summaryResynthesizer.sourceFactory
+ .resolveUri(referencedLibrarySource, uri);
+ partUri = partSource.uri.toString();
+ } else {
+ partUri = referencedLibraryUri;
+ }
+ return <String>[referencedLibraryUri, partUri, name];
+ }
+
+ /**
+ * Populate a [CompilationUnitElement] by deserializing all the elements
+ * contained in it.
+ */
+ void populateUnit(_UnitResynthesizer unitResynthesized) {
+ // TODO(scheglov)
+ unitResynthesized.populateUnit();
+ String absoluteUri = unitResynthesized.unit.source.uri.toString();
+ resynthesizedUnits[absoluteUri] = unitResynthesized.unit;
+ resynthesizedElements[absoluteUri] = unitResynthesized.elementMap;
+ }
+}
+
+/**
+ * Data structure used during resynthesis to record all the information that is
+ * known about how to resynthesize a single entry in [LinkedUnit.references]
+ * (and its associated entry in [UnlinkedUnit.references], if it exists).
+ */
+class _ReferenceInfo {
+ /**
+ * The enclosing [_ReferenceInfo], or `null` for top-level elements.
+ */
+ final _ReferenceInfo enclosing;
+
+ /**
+ * The name of the entity referred to by this reference.
+ */
+ final String name;
+
+ /**
+ * The element referred to by this reference, or `null` if there is no
+ * associated element (e.g. because it is a reference to an undefined
+ * entity).
+ */
+ final Element element;
+
+ /**
+ * If this reference refers to a non-generic type, the type it refers to.
+ * Otherwise `null`.
+ */
+ DartType type;
+
+ /**
+ * The number of type parameters accepted by the entity referred to by this
+ * reference, or zero if it doesn't accept any type parameters.
+ */
+ final int numTypeParameters;
+
+ /**
+ * Create a new [_ReferenceInfo] object referring to an element called [name]
+ * via the element handle [element], and having [numTypeParameters] type
+ * parameters.
+ *
+ * For the special types `dynamic` and `void`, [specialType] should point to
+ * the type itself. Otherwise, pass `null` and the type will be computed
+ * when appropriate.
+ */
+ _ReferenceInfo(this.enclosing, this.name, this.element, DartType specialType,
+ this.numTypeParameters) {
+ if (specialType != null) {
+ type = specialType;
+ } else {
+ type = _buildType((_) => DynamicTypeImpl.instance, const []);
+ }
+ }
+
+ /**
+ * Build a [DartType] corresponding to the result of applying some type
+ * arguments to the entity referred to by this [_ReferenceInfo]. The type
+ * arguments are retrieved by calling [getTypeArgument].
+ *
+ * If [implicitFunctionTypeIndices] is not empty, a [DartType] should be
+ * created which refers to a function type implicitly defined by one of the
+ * element's parameters. [implicitFunctionTypeIndices] is interpreted as in
+ * [EntityRef.implicitFunctionTypeIndices].
+ *
+ * If the entity referred to by this [_ReferenceInfo] is not a type, `null`
+ * is returned.
+ */
+ DartType buildType(
+ DartType getTypeArgument(int i), List<int> implicitFunctionTypeIndices) {
+ DartType result =
+ (numTypeParameters == 0 && implicitFunctionTypeIndices.isEmpty)
+ ? type
+ : _buildType(getTypeArgument, implicitFunctionTypeIndices);
+ if (result == null) {
+ // TODO(paulberry): figure out how to handle this case (which should
+ // only occur in the event of erroneous code).
+ throw new UnimplementedError();
+ }
+ return result;
+ }
+
+ /**
+ * If this reference refers to a type, build a [DartType] which instantiates
+ * it with type arguments returned by [getTypeArgument]. Otherwise return
+ * `null`.
+ *
+ * If [implicitFunctionTypeIndices] is not null, a [DartType] should be
+ * created which refers to a function type implicitly defined by one of the
+ * element's parameters. [implicitFunctionTypeIndices] is interpreted as in
+ * [EntityRef.implicitFunctionTypeIndices].
+ */
+ DartType _buildType(
+ DartType getTypeArgument(int i), List<int> implicitFunctionTypeIndices) {
+ ElementHandle element = this.element; // To allow type promotion
+ if (element is ClassElementHandle) {
+ return new InterfaceTypeImpl.elementWithNameAndArgs(element, name,
+ _buildTypeArguments(numTypeParameters, getTypeArgument));
+ } else if (element is FunctionTypeAliasElementHandle) {
+ return new FunctionTypeImpl.elementWithNameAndArgs(
+ element,
+ name,
+ _buildTypeArguments(numTypeParameters, getTypeArgument),
+ numTypeParameters != 0);
+ } else if (element is FunctionTypedElement) {
+ int numTypeArguments;
+ FunctionTypedElementComputer computer;
+ if (implicitFunctionTypeIndices.isNotEmpty) {
+ numTypeArguments = numTypeParameters;
+ computer = () {
+ FunctionTypedElement element = this.element;
+ for (int index in implicitFunctionTypeIndices) {
+ element = element.parameters[index].type.element;
+ }
+ return element;
+ };
+ } else {
+ // For a type that refers to a generic executable, the type arguments are
+ // not supposed to include the arguments to the executable itself.
+ numTypeArguments = enclosing == null ? 0 : enclosing.numTypeParameters;
+ computer = () => this.element;
+ }
+ // TODO(paulberry): Is it a bug that we have to pass `false` for
+ // isInstantiated?
+ return new DeferredFunctionTypeImpl(computer, null,
+ _buildTypeArguments(numTypeArguments, getTypeArgument), false);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Build a list of type arguments having length [numTypeArguments] where each
+ * type argument is obtained by calling [getTypeArgument].
+ */
+ List<DartType> _buildTypeArguments(
+ int numTypeArguments, DartType getTypeArgument(int i)) {
+ List<DartType> typeArguments = const <DartType>[];
+ if (numTypeArguments != 0) {
+ typeArguments = <DartType>[];
+ for (int i = 0; i < numTypeArguments; i++) {
+ typeArguments.add(getTypeArgument(i));
+ }
+ }
+ return typeArguments;
+ }
+}
+
+/**
+ * An instance of [_UnitResynthesizer] is responsible for resynthesizing the
+ * elements in a single unit from that unit's summary.
*/
-class _LibraryResynthesizer {
- /**
- * The [SummaryResynthesizer] which is being used to obtain summaries.
- */
- final SummaryResynthesizer summaryResynthesizer;
-
- /**
- * Linked summary of the library to be resynthesized.
- */
- final LinkedLibrary linkedLibrary;
-
+class _UnitResynthesizer {
/**
- * Unlinked compilation units constituting the library to be resynthesized.
+ * The [_LibraryResynthesizer] which is being used to obtain summaries.
*/
- final List<UnlinkedUnit> unlinkedUnits;
+ final _LibraryResynthesizer libraryResynthesizer;
/**
- * [Source] object for the library to be resynthesized.
+ * The [UnlinkedUnit] from which elements are currently being resynthesized.
*/
- final Source librarySource;
+ final UnlinkedUnit unlinkedUnit;
/**
- * Indicates whether [librarySource] is the `dart:core` library.
+ * The [LinkedUnit] from which elements are currently being resynthesized.
*/
- bool isCoreLibrary;
+ final LinkedUnit linkedUnit;
/**
- * Classes which should have their supertype set to "object" once
- * resynthesis is complete. Only used if [isCoreLibrary] is `true`.
+ * The [CompilationUnitElementImpl] for the compilation unit currently being
+ * resynthesized.
*/
- List<ClassElementImpl> delayedObjectSubclasses = <ClassElementImpl>[];
+ final CompilationUnitElementImpl unit;
/**
* [ElementHolder] into which resynthesized elements should be placed. This
* object is recreated afresh for each unit in the library, and is used to
* populate the [CompilationUnitElement].
*/
- ElementHolder unitHolder;
-
- /**
- * The [LinkedUnit] from which elements are currently being resynthesized.
- */
- LinkedUnit linkedUnit;
+ final ElementHolder unitHolder = new ElementHolder();
/**
- * The [UnlinkedUnit] from which elements are currently being resynthesized.
+ * Map of top-level elements that have been resynthesized so far. The key is
+ * the name of the top level element.
*/
- UnlinkedUnit unlinkedUnit;
+ Map<String, Element> elementMap = <String, Element>{};
/**
* Map from slot id to the corresponding [EntityRef] object for linked types
* (i.e. propagated and inferred types).
*/
- Map<int, EntityRef> linkedTypeMap;
+ final Map<int, EntityRef> linkedTypeMap = <int, EntityRef>{};
/**
* Set of slot ids corresponding to const constructors that are part of
@@ -851,33 +1410,12 @@ class _LibraryResynthesizer {
Set<int> constCycles;
/**
- * The [CompilationUnitElementImpl] for the compilation unit currently being
- * resynthesized.
- */
- CompilationUnitElementImpl currentCompilationUnit;
-
- /**
* The [ConstructorElementImpl] for the constructor currently being
* resynthesized.
*/
ConstructorElementImpl currentConstructor;
/**
- * Map of compilation unit elements that have been resynthesized so far. The
- * key is the URI of the compilation unit.
- */
- final Map<String, CompilationUnitElement> resynthesizedUnits =
- <String, CompilationUnitElement>{};
-
- /**
- * Map of top level elements that have been resynthesized so far. The first
- * key is the URI of the compilation unit; the second is the name of the top
- * level element.
- */
- final Map<String, Map<String, Element>> resynthesizedElements =
- <String, Map<String, Element>>{};
-
- /**
* Type parameters for the generic class, typedef, or executable currently
* being resynthesized, if any. This is a list of lists; if multiple
* entities with type parameters are nested (e.g. a generic executable inside
@@ -910,12 +1448,22 @@ class _LibraryResynthesizer {
*/
List<_ReferenceInfo> referenceInfos;
- _LibraryResynthesizer(this.summaryResynthesizer, this.linkedLibrary,
- this.unlinkedUnits, this.librarySource) {
- isCoreLibrary = librarySource.uri.toString() == 'dart:core';
+ _UnitResynthesizer(this.libraryResynthesizer, this.unlinkedUnit,
+ this.linkedUnit, this.unit) {
+ for (EntityRef t in linkedUnit.types) {
+ linkedTypeMap[t.slot] = t;
+ }
+ constCycles = linkedUnit.constCycles.toSet();
+ populateReferenceInfos();
}
/**
+ * TODO(scheglov) inline?
Paul Berry 2016/03/24 19:40:14 AFAIK, the VM is smart about inlining methods like
+ */
+ SummaryResynthesizer get summaryResynthesizer =>
+ libraryResynthesizer.summaryResynthesizer;
+
+ /**
* Build the annotations for the given [element].
*/
void buildAnnotations(
@@ -923,7 +1471,7 @@ class _LibraryResynthesizer {
if (serializedAnnotations.isNotEmpty) {
element.metadata = serializedAnnotations.map((UnlinkedConst a) {
ElementAnnotationImpl elementAnnotation =
- new ElementAnnotationImpl(this.currentCompilationUnit);
+ new ElementAnnotationImpl(this.unit);
Expression constExpr = _buildConstExpression(a);
if (constExpr is Identifier) {
elementAnnotation.element = constExpr.staticElement;
@@ -953,6 +1501,23 @@ class _LibraryResynthesizer {
* Resynthesize a [ClassElement] and place it in [unitHolder].
*/
void buildClass(UnlinkedClass serializedClass) {
+ ClassElement classElement;
+ if (libraryResynthesizer.isCoreLibrary &&
+ serializedClass.supertype == null) {
+ classElement = buildClassImpl(serializedClass);
+ if (!serializedClass.hasNoSupertype) {
+ libraryResynthesizer.delayedObjectSubclasses.add(classElement);
+ }
+ } else {
+ classElement = new _DeferredClassElement(this, unit, serializedClass);
+ }
+ unitHolder.addType(classElement);
+ }
+
+ /**
+ * Resynthesize a [ClassElementImpl].
+ */
+ ClassElementImpl buildClassImpl(UnlinkedClass serializedClass) {
ClassElementImpl classElement =
new ClassElementImpl(serializedClass.name, serializedClass.nameOffset);
classElement.hasBeenInferred = summaryResynthesizer.strongMode;
@@ -963,12 +1528,8 @@ class _LibraryResynthesizer {
InterfaceTypeImpl correspondingType = new InterfaceTypeImpl(classElement);
if (serializedClass.supertype != null) {
classElement.supertype = buildType(serializedClass.supertype);
- } else if (!serializedClass.hasNoSupertype) {
- if (isCoreLibrary) {
- delayedObjectSubclasses.add(classElement);
- } else {
- classElement.supertype = summaryResynthesizer.typeProvider.objectType;
- }
+ } else if (!libraryResynthesizer.isCoreLibrary) {
+ classElement.supertype = summaryResynthesizer.typeProvider.objectType;
}
classElement.interfaces =
serializedClass.interfaces.map(buildType).toList();
@@ -1022,11 +1583,11 @@ class _LibraryResynthesizer {
buildAnnotations(classElement, serializedClass.annotations);
buildCodeRange(classElement, serializedClass.codeRange);
resolveConstructorInitializers(classElement);
- unitHolder.addType(classElement);
currentTypeParameters.removeLast();
assert(currentTypeParameters.isEmpty);
fields = null;
constructors = null;
+ return classElement;
}
void buildCodeRange(ElementImpl element, CodeRange codeRange) {
@@ -1116,8 +1677,7 @@ class _LibraryResynthesizer {
currentConstructor.redirectedConstructor = _createConstructorElement(
_createConstructorDefiningType(info, typeArguments), info);
} else {
- List<String> locationComponents =
- currentCompilationUnit.location.components.toList();
+ List<String> locationComponents = unit.location.components.toList();
locationComponents.add(classType.name);
locationComponents.add(serializedExecutable.redirectedConstructorName);
currentConstructor.redirectedConstructor =
@@ -1149,7 +1709,7 @@ class _LibraryResynthesizer {
* associated fields and implicit accessors.
*/
void buildEnum(UnlinkedEnum serializedEnum) {
- assert(!isCoreLibrary);
+ assert(!libraryResynthesizer.isCoreLibrary);
ClassElementImpl classElement =
new ClassElementImpl(serializedEnum.name, serializedEnum.nameOffset);
classElement.enum2 = true;
@@ -1332,7 +1892,8 @@ class _LibraryResynthesizer {
ExportElementImpl exportElement =
new ExportElementImpl(serializedExportNonPublic.offset);
String exportedLibraryUri = summaryResynthesizer.sourceFactory
- .resolveUri(librarySource, serializedExportPublic.uri)
+ .resolveUri(
+ libraryResynthesizer.librarySource, serializedExportPublic.uri)
.uri
.toString();
exportElement.exportedLibrary = new LibraryElementHandle(
@@ -1348,63 +1909,6 @@ class _LibraryResynthesizer {
}
/**
- * Build an [ElementHandle] referring to the entity referred to by the given
- * [exportName].
- */
- ElementHandle buildExportName(LinkedExportName exportName) {
- String name = exportName.name;
- if (exportName.kind == ReferenceKind.topLevelPropertyAccessor &&
- !name.endsWith('=')) {
- name += '?';
- }
- ElementLocationImpl location = new ElementLocationImpl.con3(
- getReferencedLocationComponents(
- exportName.dependency, exportName.unit, name));
- switch (exportName.kind) {
- case ReferenceKind.classOrEnum:
- return new ClassElementHandle(summaryResynthesizer, location);
- case ReferenceKind.typedef:
- return new FunctionTypeAliasElementHandle(
- summaryResynthesizer, location);
- case ReferenceKind.topLevelFunction:
- return new FunctionElementHandle(summaryResynthesizer, location);
- case ReferenceKind.topLevelPropertyAccessor:
- return new PropertyAccessorElementHandle(
- summaryResynthesizer, location);
- case ReferenceKind.constructor:
- case ReferenceKind.function:
- case ReferenceKind.propertyAccessor:
- case ReferenceKind.method:
- case ReferenceKind.length:
- case ReferenceKind.prefix:
- case ReferenceKind.unresolved:
- case ReferenceKind.variable:
- // Should never happen. Exported names never refer to import prefixes,
- // and they always refer to defined top-level entities.
- throw new StateError('Unexpected export name kind: ${exportName.kind}');
- }
- }
-
- /**
- * Build the export namespace for the library by aggregating together its
- * [publicNamespace] and [exportNames].
- */
- Namespace buildExportNamespace(
- Namespace publicNamespace, List<LinkedExportName> exportNames) {
- HashMap<String, Element> definedNames = new HashMap<String, Element>();
- // Start by populating all the public names from [publicNamespace].
- publicNamespace.definedNames.forEach((String name, Element element) {
- definedNames[name] = element;
- });
- // Add all the names from [exportNames].
- for (LinkedExportName exportName in exportNames) {
- definedNames.putIfAbsent(
- exportName.name, () => buildExportName(exportName));
- }
- return new Namespace(definedNames);
- }
-
- /**
* Build the implicit getter and setter associated with [element], and place
* them in [holder].
*/
@@ -1447,160 +1951,41 @@ class _LibraryResynthesizer {
* Build the implicit field associated with a getter or setter, and place it
* in [holder].
*/
- FieldElementImpl buildImplicitField(String name, DartType type,
- UnlinkedExecutableKind kind, ElementHolder holder) {
- FieldElementImpl field = holder.getField(name);
- if (field == null) {
- field = new FieldElementImpl(name, -1);
- field.synthetic = true;
- field.final2 = kind == UnlinkedExecutableKind.getter;
- field.type = type;
- holder.addField(field);
- return field;
- } else {
- // TODO(paulberry): what if the getter and setter have a type mismatch?
- field.final2 = false;
- return field;
- }
- }
-
- /**
- * Build the implicit top level variable associated with a getter or setter,
- * and place it in [holder].
- */
- PropertyInducingElementImpl buildImplicitTopLevelVariable(
- String name, UnlinkedExecutableKind kind, ElementHolder holder) {
- TopLevelVariableElementImpl variable = holder.getTopLevelVariable(name);
- if (variable == null) {
- variable = new TopLevelVariableElementImpl(name, -1);
- variable.synthetic = true;
- variable.final2 = kind == UnlinkedExecutableKind.getter;
- holder.addTopLevelVariable(variable);
- return variable;
- } else {
- // TODO(paulberry): what if the getter and setter have a type mismatch?
- variable.final2 = false;
- return variable;
- }
- }
-
- /**
- * Resynthesize an [ImportElement].
- */
- ImportElement buildImport(UnlinkedImport serializedImport, int dependency) {
- bool isSynthetic = serializedImport.isImplicit;
- ImportElementImpl importElement =
- new ImportElementImpl(isSynthetic ? -1 : serializedImport.offset);
- String absoluteUri = summaryResynthesizer.sourceFactory
- .resolveUri(librarySource, linkedLibrary.dependencies[dependency].uri)
- .uri
- .toString();
- importElement.importedLibrary = new LibraryElementHandle(
- summaryResynthesizer,
- new ElementLocationImpl.con3(<String>[absoluteUri]));
- if (isSynthetic) {
- importElement.synthetic = true;
- } else {
- importElement.uri = serializedImport.uri;
- importElement.uriOffset = serializedImport.uriOffset;
- importElement.uriEnd = serializedImport.uriEnd;
- importElement.deferred = serializedImport.isDeferred;
- buildAnnotations(importElement, serializedImport.annotations);
- }
- importElement.prefixOffset = serializedImport.prefixOffset;
- if (serializedImport.prefixReference != 0) {
- UnlinkedReference serializedPrefix =
- unlinkedUnits[0].references[serializedImport.prefixReference];
- importElement.prefix = new PrefixElementImpl(
- serializedPrefix.name, serializedImport.prefixOffset);
- }
- importElement.combinators =
- serializedImport.combinators.map(buildCombinator).toList();
- return importElement;
- }
-
- /**
- * Main entry point. Resynthesize the [LibraryElement] and return it.
- */
- LibraryElement buildLibrary() {
- CompilationUnitElementImpl definingCompilationUnit =
- new CompilationUnitElementImpl(librarySource.shortName);
- prepareUnit(definingCompilationUnit, 0);
- bool hasName = unlinkedUnits[0].libraryName.isNotEmpty;
- LibraryElementImpl library = new LibraryElementImpl(
- summaryResynthesizer.context,
- unlinkedUnits[0].libraryName,
- hasName ? unlinkedUnits[0].libraryNameOffset : -1,
- unlinkedUnits[0].libraryNameLength);
- buildDocumentation(library, unlinkedUnits[0].libraryDocumentationComment);
- buildAnnotations(library, unlinkedUnits[0].libraryAnnotations);
- library.definingCompilationUnit = definingCompilationUnit;
- definingCompilationUnit.source = librarySource;
- definingCompilationUnit.librarySource = librarySource;
- List<CompilationUnitElement> parts = <CompilationUnitElement>[];
- UnlinkedUnit unlinkedDefiningUnit = unlinkedUnits[0];
- assert(unlinkedDefiningUnit.publicNamespace.parts.length + 1 ==
- linkedLibrary.units.length);
- for (int i = 1; i < linkedLibrary.units.length; i++) {
- CompilationUnitElementImpl part = buildPart(
- unlinkedDefiningUnit.publicNamespace.parts[i - 1],
- unlinkedDefiningUnit.parts[i - 1],
- unlinkedUnits[i]);
- parts.add(part);
- }
- library.parts = parts;
- List<ImportElement> imports = <ImportElement>[];
- for (int i = 0; i < unlinkedDefiningUnit.imports.length; i++) {
- imports.add(buildImport(unlinkedDefiningUnit.imports[i],
- linkedLibrary.importDependencies[i]));
- }
- library.imports = imports;
- List<ExportElement> exports = <ExportElement>[];
- assert(unlinkedDefiningUnit.exports.length ==
- unlinkedDefiningUnit.publicNamespace.exports.length);
- for (int i = 0; i < unlinkedDefiningUnit.exports.length; i++) {
- exports.add(buildExport(unlinkedDefiningUnit.publicNamespace.exports[i],
- unlinkedDefiningUnit.exports[i]));
- }
- library.exports = exports;
- populateUnit(definingCompilationUnit, 0);
- finishUnit();
- for (int i = 0; i < parts.length; i++) {
- prepareUnit(parts[i], i + 1);
- populateUnit(parts[i], i + 1);
- finishUnit();
- }
- BuildLibraryElementUtils.patchTopLevelAccessors(library);
- // Update delayed Object class references.
- if (isCoreLibrary) {
- ClassElement objectElement = library.getType('Object');
- assert(objectElement != null);
- for (ClassElementImpl classElement in delayedObjectSubclasses) {
- classElement.supertype = objectElement.type;
- }
- }
- // Compute namespaces.
- library.publicNamespace =
- new NamespaceBuilder().createPublicNamespaceForLibrary(library);
- library.exportNamespace = buildExportNamespace(
- library.publicNamespace, linkedLibrary.exportNames);
- // Find the entry point. Note: we can't use element.isEntryPoint because
- // that will trigger resynthesis of exported libraries.
- Element entryPoint =
- library.exportNamespace.get(FunctionElement.MAIN_FUNCTION_NAME);
- if (entryPoint is FunctionElement) {
- library.entryPoint = entryPoint;
+ FieldElementImpl buildImplicitField(String name, DartType type,
+ UnlinkedExecutableKind kind, ElementHolder holder) {
+ FieldElementImpl field = holder.getField(name);
+ if (field == null) {
+ field = new FieldElementImpl(name, -1);
+ field.synthetic = true;
+ field.final2 = kind == UnlinkedExecutableKind.getter;
+ field.type = type;
+ holder.addField(field);
+ return field;
+ } else {
+ // TODO(paulberry): what if the getter and setter have a type mismatch?
+ field.final2 = false;
+ return field;
}
- // Create the synthetic element for `loadLibrary`.
- // Until the client received dart:core and dart:async, we cannot do this,
- // because the TypeProvider is not fully initialized. So, it is up to the
- // Dart SDK client to initialize TypeProvider and finish the dart:core and
- // dart:async libraries creation.
- if (library.name != 'dart.core' && library.name != 'dart.async') {
- library.createLoadLibraryFunction(summaryResynthesizer.typeProvider);
+ }
+
+ /**
+ * Build the implicit top level variable associated with a getter or setter,
+ * and place it in [holder].
+ */
+ PropertyInducingElementImpl buildImplicitTopLevelVariable(
+ String name, UnlinkedExecutableKind kind, ElementHolder holder) {
+ TopLevelVariableElementImpl variable = holder.getTopLevelVariable(name);
+ if (variable == null) {
+ variable = new TopLevelVariableElementImpl(name, -1);
+ variable.synthetic = true;
+ variable.final2 = kind == UnlinkedExecutableKind.getter;
+ holder.addTopLevelVariable(variable);
+ return variable;
+ } else {
+ // TODO(paulberry): what if the getter and setter have a type mismatch?
+ variable.final2 = false;
+ return variable;
}
- // Done.
- return library;
}
/**
@@ -1761,25 +2146,6 @@ class _LibraryResynthesizer {
}
/**
- * Create, but do not populate, the [CompilationUnitElement] for a part other
- * than the defining compilation unit.
- */
- CompilationUnitElementImpl buildPart(
- String uri, UnlinkedPart partDecl, UnlinkedUnit serializedPart) {
- Source unitSource =
- summaryResynthesizer.sourceFactory.resolveUri(librarySource, uri);
- CompilationUnitElementImpl partUnit =
- new CompilationUnitElementImpl(unitSource.shortName);
- partUnit.uriOffset = partDecl.uriOffset;
- partUnit.uriEnd = partDecl.uriEnd;
- partUnit.source = unitSource;
- partUnit.librarySource = librarySource;
- partUnit.uri = uri;
- buildAnnotations(partUnit, partDecl.annotations);
- return partUnit;
- }
-
- /**
* Handle the parts that are common to top level variables and fields.
*/
void buildPropertyIntroducingElementCommonParts(
@@ -1975,20 +2341,6 @@ class _LibraryResynthesizer {
}
/**
- * Tear down data structures used during deserialization of a compilation
- * unit.
- */
- void finishUnit() {
- unitHolder = null;
- linkedUnit = null;
- unlinkedUnit = null;
- linkedTypeMap = null;
- constCycles = null;
- referenceInfos = null;
- currentCompilationUnit = null;
- }
-
- /**
* Return a list of type arguments corresponding to [currentTypeParameters],
* skipping the innermost [skipLevels] nesting levels.
*
@@ -2008,42 +2360,6 @@ class _LibraryResynthesizer {
}
/**
- * Build the components of an [ElementLocationImpl] for the entity in the
- * given [unit] of the dependency located at [dependencyIndex], and having
- * the given [name].
- */
- List<String> getReferencedLocationComponents(
- int dependencyIndex, int unit, String name) {
- if (dependencyIndex == 0) {
- String referencedLibraryUri = librarySource.uri.toString();
- String partUri;
- if (unit != 0) {
- String uri = unlinkedUnits[0].publicNamespace.parts[unit - 1];
- Source partSource =
- summaryResynthesizer.sourceFactory.resolveUri(librarySource, uri);
- partUri = partSource.uri.toString();
- } else {
- partUri = referencedLibraryUri;
- }
- return <String>[referencedLibraryUri, partUri, name];
- }
- LinkedDependency dependency = linkedLibrary.dependencies[dependencyIndex];
- Source referencedLibrarySource = summaryResynthesizer.sourceFactory
- .resolveUri(librarySource, dependency.uri);
- String referencedLibraryUri = referencedLibrarySource.uri.toString();
- String partUri;
- if (unit != 0) {
- String uri = dependency.parts[unit - 1];
- Source partSource = summaryResynthesizer.sourceFactory
- .resolveUri(referencedLibrarySource, uri);
- partUri = partSource.uri.toString();
- } else {
- partUri = referencedLibraryUri;
- }
- return <String>[referencedLibraryUri, partUri, name];
- }
-
- /**
* Get the type parameter from the surrounding scope whose De Bruijn index is
* [index].
*/
@@ -2106,8 +2422,9 @@ class _LibraryResynthesizer {
locationComponents.add(identifier);
} else {
String identifier = _getElementIdentifier(name, linkedReference.kind);
- locationComponents = getReferencedLocationComponents(
- linkedReference.dependency, linkedReference.unit, identifier);
+ locationComponents =
+ libraryResynthesizer.getReferencedLocationComponents(
+ linkedReference.dependency, linkedReference.unit, identifier);
}
ElementLocation location =
new ElementLocationImpl.con3(locationComponents);
@@ -2183,13 +2500,12 @@ class _LibraryResynthesizer {
* Populate a [CompilationUnitElement] by deserializing all the elements
* contained in it.
*/
- void populateUnit(CompilationUnitElementImpl unit, int unitNum) {
+ void populateUnit() {
unlinkedUnit.classes.forEach(buildClass);
unlinkedUnit.enums.forEach(buildEnum);
unlinkedUnit.executables.forEach(buildExecutable);
unlinkedUnit.typedefs.forEach(buildTypedef);
unlinkedUnit.variables.forEach(buildVariable);
- String absoluteUri = unit.source.uri.toString();
unit.accessors = unitHolder.accessors;
unit.enums = unitHolder.enums;
unit.functions = unitHolder.functions;
@@ -2202,7 +2518,6 @@ class _LibraryResynthesizer {
unit.typeAliases = typeAliases.where((e) => !e.isSynthetic).toList();
unit.types = unitHolder.types;
unit.topLevelVariables = unitHolder.topLevelVariables;
- Map<String, Element> elementMap = <String, Element>{};
for (ClassElement cls in unit.types) {
elementMap[cls.name] = cls;
}
@@ -2219,28 +2534,10 @@ class _LibraryResynthesizer {
elementMap[accessor.identifier] = accessor;
}
buildCodeRange(unit, unlinkedUnit.codeRange);
- resynthesizedUnits[absoluteUri] = unit;
- resynthesizedElements[absoluteUri] = elementMap;
assert(currentTypeParameters.isEmpty);
}
/**
- * Set up data structures for deserializing a compilation unit.
- */
- void prepareUnit(CompilationUnitElementImpl unit, int unitNum) {
- linkedUnit = linkedLibrary.units[unitNum];
- unlinkedUnit = unlinkedUnits[unitNum];
- linkedTypeMap = <int, EntityRef>{};
- currentCompilationUnit = unit;
- for (EntityRef t in linkedUnit.types) {
- linkedTypeMap[t.slot] = t;
- }
- constCycles = linkedUnit.constCycles.toSet();
- populateReferenceInfos();
- unitHolder = new ElementHolder();
- }
-
- /**
* Constructor initializers can reference fields and other constructors of
* the same class, including forward references. So, we need to delay
* resolution until after class elements are built.
@@ -2333,149 +2630,3 @@ class _LibraryResynthesizer {
return name;
}
}
-
-/**
- * Data structure used during resynthesis to record all the information that is
- * known about how to resynthesize a single entry in [LinkedUnit.references]
- * (and its associated entry in [UnlinkedUnit.references], if it exists).
- */
-class _ReferenceInfo {
- /**
- * The enclosing [_ReferenceInfo], or `null` for top-level elements.
- */
- final _ReferenceInfo enclosing;
-
- /**
- * The name of the entity referred to by this reference.
- */
- final String name;
-
- /**
- * The element referred to by this reference, or `null` if there is no
- * associated element (e.g. because it is a reference to an undefined
- * entity).
- */
- final Element element;
-
- /**
- * If this reference refers to a non-generic type, the type it refers to.
- * Otherwise `null`.
- */
- DartType type;
-
- /**
- * The number of type parameters accepted by the entity referred to by this
- * reference, or zero if it doesn't accept any type parameters.
- */
- final int numTypeParameters;
-
- /**
- * Create a new [_ReferenceInfo] object referring to an element called [name]
- * via the element handle [element], and having [numTypeParameters] type
- * parameters.
- *
- * For the special types `dynamic` and `void`, [specialType] should point to
- * the type itself. Otherwise, pass `null` and the type will be computed
- * when appropriate.
- */
- _ReferenceInfo(this.enclosing, this.name, this.element, DartType specialType,
- this.numTypeParameters) {
- if (specialType != null) {
- type = specialType;
- } else {
- type = _buildType((_) => DynamicTypeImpl.instance, const []);
- }
- }
-
- /**
- * Build a [DartType] corresponding to the result of applying some type
- * arguments to the entity referred to by this [_ReferenceInfo]. The type
- * arguments are retrieved by calling [getTypeArgument].
- *
- * If [implicitFunctionTypeIndices] is not empty, a [DartType] should be
- * created which refers to a function type implicitly defined by one of the
- * element's parameters. [implicitFunctionTypeIndices] is interpreted as in
- * [EntityRef.implicitFunctionTypeIndices].
- *
- * If the entity referred to by this [_ReferenceInfo] is not a type, `null`
- * is returned.
- */
- DartType buildType(
- DartType getTypeArgument(int i), List<int> implicitFunctionTypeIndices) {
- DartType result =
- (numTypeParameters == 0 && implicitFunctionTypeIndices.isEmpty)
- ? type
- : _buildType(getTypeArgument, implicitFunctionTypeIndices);
- if (result == null) {
- // TODO(paulberry): figure out how to handle this case (which should
- // only occur in the event of erroneous code).
- throw new UnimplementedError();
- }
- return result;
- }
-
- /**
- * If this reference refers to a type, build a [DartType] which instantiates
- * it with type arguments returned by [getTypeArgument]. Otherwise return
- * `null`.
- *
- * If [implicitFunctionTypeIndices] is not null, a [DartType] should be
- * created which refers to a function type implicitly defined by one of the
- * element's parameters. [implicitFunctionTypeIndices] is interpreted as in
- * [EntityRef.implicitFunctionTypeIndices].
- */
- DartType _buildType(
- DartType getTypeArgument(int i), List<int> implicitFunctionTypeIndices) {
- ElementHandle element = this.element; // To allow type promotion
- if (element is ClassElementHandle) {
- return new InterfaceTypeImpl.elementWithNameAndArgs(element, name,
- _buildTypeArguments(numTypeParameters, getTypeArgument));
- } else if (element is FunctionTypeAliasElementHandle) {
- return new FunctionTypeImpl.elementWithNameAndArgs(
- element,
- name,
- _buildTypeArguments(numTypeParameters, getTypeArgument),
- numTypeParameters != 0);
- } else if (element is FunctionTypedElement) {
- int numTypeArguments;
- FunctionTypedElementComputer computer;
- if (implicitFunctionTypeIndices.isNotEmpty) {
- numTypeArguments = numTypeParameters;
- computer = () {
- FunctionTypedElement element = this.element;
- for (int index in implicitFunctionTypeIndices) {
- element = element.parameters[index].type.element;
- }
- return element;
- };
- } else {
- // For a type that refers to a generic executable, the type arguments are
- // not supposed to include the arguments to the executable itself.
- numTypeArguments = enclosing == null ? 0 : enclosing.numTypeParameters;
- computer = () => this.element;
- }
- // TODO(paulberry): Is it a bug that we have to pass `false` for
- // isInstantiated?
- return new DeferredFunctionTypeImpl(computer, null,
- _buildTypeArguments(numTypeArguments, getTypeArgument), false);
- } else {
- return null;
- }
- }
-
- /**
- * Build a list of type arguments having length [numTypeArguments] where each
- * type argument is obtained by calling [getTypeArgument].
- */
- List<DartType> _buildTypeArguments(
- int numTypeArguments, DartType getTypeArgument(int i)) {
- List<DartType> typeArguments = const <DartType>[];
- if (numTypeArguments != 0) {
- typeArguments = <DartType>[];
- for (int i = 0; i < numTypeArguments; i++) {
- typeArguments.add(getTypeArgument(i));
- }
- }
- return typeArguments;
- }
-}

Powered by Google App Engine
This is Rietveld 408576698