Chromium Code Reviews| 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; |
| - } |
| -} |