| Index: pkg/analyzer/lib/src/summary/summarize_elements.dart
|
| diff --git a/pkg/analyzer/lib/src/summary/summarize_elements.dart b/pkg/analyzer/lib/src/summary/summarize_elements.dart
|
| index 0662111707aa88523ff98891ecf84a9417dbef11..2af7bde3826bb4dbcb9a4a9f50fb8ad33096f14f 100644
|
| --- a/pkg/analyzer/lib/src/summary/summarize_elements.dart
|
| +++ b/pkg/analyzer/lib/src/summary/summarize_elements.dart
|
| @@ -6,113 +6,15 @@ library serialization.elements;
|
|
|
| import 'dart:convert';
|
|
|
| -import 'package:analyzer/dart/ast/ast.dart';
|
| -import 'package:analyzer/dart/element/element.dart';
|
| -import 'package:analyzer/dart/element/type.dart';
|
| -import 'package:analyzer/src/dart/element/element.dart';
|
| -import 'package:analyzer/src/dart/element/member.dart';
|
| -import 'package:analyzer/src/dart/element/type.dart';
|
| -import 'package:analyzer/src/generated/resolver.dart';
|
| import 'package:analyzer/src/generated/source.dart';
|
| -import 'package:analyzer/src/generated/utilities_dart.dart';
|
| import 'package:analyzer/src/summary/api_signature.dart';
|
| import 'package:analyzer/src/summary/format.dart';
|
| import 'package:analyzer/src/summary/idl.dart';
|
| -import 'package:analyzer/src/summary/name_filter.dart';
|
| import 'package:analyzer/src/summary/package_bundle_reader.dart';
|
| -import 'package:analyzer/src/summary/summarize_const_expr.dart';
|
| import 'package:convert/convert.dart';
|
| import 'package:crypto/crypto.dart';
|
|
|
| /**
|
| - * Serialize all the elements in [lib] to a summary using [ctx] as the context
|
| - * for building the summary, and using [typeProvider] to find built-in types.
|
| - */
|
| -LibrarySerializationResult serializeLibrary(
|
| - LibraryElement lib, TypeProvider typeProvider, bool strongMode) {
|
| - _LibrarySerializer serializer =
|
| - new _LibrarySerializer(lib, typeProvider, strongMode);
|
| - LinkedLibraryBuilder linked = serializer.serializeLibrary();
|
| - return new LibrarySerializationResult(linked, serializer.unlinkedUnits,
|
| - serializer.unitUris, serializer.unitSources);
|
| -}
|
| -
|
| -ReferenceKind _getReferenceKind(Element element) {
|
| - if (element == null ||
|
| - element is ClassElement ||
|
| - element is DynamicElementImpl) {
|
| - return ReferenceKind.classOrEnum;
|
| - } else if (element is ConstructorElement) {
|
| - return ReferenceKind.constructor;
|
| - } else if (element is FunctionElement) {
|
| - if (element.enclosingElement is CompilationUnitElement) {
|
| - return ReferenceKind.topLevelFunction;
|
| - }
|
| - return ReferenceKind.function;
|
| - } else if (element is FunctionTypeAliasElement) {
|
| - return ReferenceKind.typedef;
|
| - } else if (element is PropertyAccessorElement) {
|
| - if (element.enclosingElement is ClassElement) {
|
| - return ReferenceKind.propertyAccessor;
|
| - }
|
| - return ReferenceKind.topLevelPropertyAccessor;
|
| - } else if (element is MethodElement) {
|
| - return ReferenceKind.method;
|
| - } else if (element is TopLevelVariableElement) {
|
| - // Summaries don't need to distinguish between references to a variable and
|
| - // references to its getter.
|
| - return ReferenceKind.topLevelPropertyAccessor;
|
| - } else if (element is LocalVariableElement) {
|
| - return ReferenceKind.variable;
|
| - } else if (element is FieldElement) {
|
| - // Summaries don't need to distinguish between references to a field and
|
| - // references to its getter.
|
| - return ReferenceKind.propertyAccessor;
|
| - } else {
|
| - throw new Exception('Unexpected element kind: ${element.runtimeType}');
|
| - }
|
| -}
|
| -
|
| -/**
|
| - * Type of closures used by [_LibrarySerializer] to defer generation of
|
| - * [EntityRefBuilder] objects until the end of serialization of a
|
| - * compilation unit.
|
| - */
|
| -typedef EntityRefBuilder _SerializeTypeRef();
|
| -
|
| -/**
|
| - * Data structure holding the result of serializing a [LibraryElement].
|
| - */
|
| -class LibrarySerializationResult {
|
| - /**
|
| - * Linked information the given library.
|
| - */
|
| - final LinkedLibraryBuilder linked;
|
| -
|
| - /**
|
| - * Unlinked information for the compilation units constituting the library.
|
| - * The zeroth entry in the list is the defining compilation unit; the
|
| - * remaining entries are the parts, in the order listed in the defining
|
| - * compilation unit's part declarations.
|
| - */
|
| - final List<UnlinkedUnitBuilder> unlinkedUnits;
|
| -
|
| - /**
|
| - * Absolute URI of each compilation unit appearing in the library.
|
| - */
|
| - final List<String> unitUris;
|
| -
|
| - /**
|
| - * Source object corresponding to each compilation unit appearing in the
|
| - * library.
|
| - */
|
| - final List<Source> unitSources;
|
| -
|
| - LibrarySerializationResult(
|
| - this.linked, this.unlinkedUnits, this.unitUris, this.unitSources);
|
| -}
|
| -
|
| -/**
|
| * Object that gathers information uses it to assemble a new
|
| * [PackageBundleBuilder].
|
| */
|
| @@ -196,28 +98,6 @@ class PackageBundleAssembler {
|
| }
|
|
|
| /**
|
| - * Serialize the library with the given [element].
|
| - */
|
| - void serializeLibraryElement(LibraryElement element) {
|
| - String uri = element.source.uri.toString();
|
| - LibrarySerializationResult libraryResult = serializeLibrary(
|
| - element,
|
| - element.context.typeProvider,
|
| - element.context.analysisOptions.strongMode);
|
| - _linkedLibraryUris.add(uri);
|
| - _linkedLibraries.add(libraryResult.linked);
|
| - _unlinkedUnitUris.addAll(libraryResult.unitUris);
|
| - _unlinkedUnits.addAll(libraryResult.unlinkedUnits);
|
| - for (int i = 0; i < libraryResult.unitUris.length; i++) {
|
| - _unlinkedUnitMap[libraryResult.unitUris[i]] =
|
| - libraryResult.unlinkedUnits[i];
|
| - }
|
| - for (Source source in libraryResult.unitSources) {
|
| - _unlinkedUnitHashes?.add(_hash(source.contents.data));
|
| - }
|
| - }
|
| -
|
| - /**
|
| * Compute the API signature for this package bundle.
|
| */
|
| String _computeApiSignature() {
|
| @@ -236,1458 +116,3 @@ class PackageBundleAssembler {
|
| return hex.encode(md5.convert(UTF8.encode(contents)).bytes);
|
| }
|
| }
|
| -
|
| -/**
|
| - * Instances of this class keep track of intermediate state during
|
| - * serialization of a single compilation unit.
|
| - */
|
| -class _CompilationUnitSerializer {
|
| - /**
|
| - * The [_LibrarySerializer] which is serializing the library of which
|
| - * [compilationUnit] is a part.
|
| - */
|
| - final _LibrarySerializer librarySerializer;
|
| -
|
| - /**
|
| - * The [CompilationUnitElement] being serialized.
|
| - */
|
| - final CompilationUnitElement compilationUnit;
|
| -
|
| - /**
|
| - * The ordinal index of [compilationUnit] within the library, where 0
|
| - * represents the defining compilation unit.
|
| - */
|
| - final int unitNum;
|
| -
|
| - /**
|
| - * The final linked summary of the compilation unit.
|
| - */
|
| - final LinkedUnitBuilder linkedUnit = new LinkedUnitBuilder();
|
| -
|
| - /**
|
| - * The final unlinked summary of the compilation unit.
|
| - */
|
| - final UnlinkedUnitBuilder unlinkedUnit = new UnlinkedUnitBuilder();
|
| -
|
| - /**
|
| - * Absolute URI of the compilation unit.
|
| - */
|
| - String unitUri;
|
| -
|
| - /**
|
| - * Map from [Element] to the index of the entry in the "references table"
|
| - * that refers to it.
|
| - */
|
| - final Map<Element, int> referenceMap = <Element, int>{};
|
| -
|
| - /**
|
| - * The unlinked portion of the "references table". This is the list of
|
| - * objects which should be written to [UnlinkedUnit.references].
|
| - */
|
| - List<UnlinkedReferenceBuilder> unlinkedReferences;
|
| -
|
| - /**
|
| - * The linked portion of the "references table". This is the list of
|
| - * objects which should be written to [LinkedUnit.references].
|
| - */
|
| - List<LinkedReferenceBuilder> linkedReferences;
|
| -
|
| - /**
|
| - * The number of slot ids which have been assigned to this compilation unit.
|
| - */
|
| - int numSlots = 0;
|
| -
|
| - /**
|
| - * List of closures which should be invoked at the end of serialization of a
|
| - * compilation unit, to produce [LinkedUnit.types].
|
| - */
|
| - final List<_SerializeTypeRef> deferredLinkedTypes = <_SerializeTypeRef>[];
|
| -
|
| - /**
|
| - * List which should be stored in [LinkedUnit.constCycles].
|
| - */
|
| - final List<int> constCycles = <int>[];
|
| -
|
| - /**
|
| - * Index into the "references table" representing an unresolved reference, if
|
| - * such an index exists. `null` if no such entry has been made in the
|
| - * references table yet.
|
| - */
|
| - int unresolvedReferenceIndex = null;
|
| -
|
| - /**
|
| - * Index into the "references table" representing the "bottom" type, if such
|
| - * an index exists. `null` if no such entry has been made in the references
|
| - * table yet.
|
| - */
|
| - int bottomReferenceIndex = null;
|
| -
|
| - /**
|
| - * If `true`, we are currently generating linked references, so new
|
| - * references will be not stored in [unlinkedReferences].
|
| - */
|
| - bool buildingLinkedReferences = false;
|
| -
|
| - _CompilationUnitSerializer(
|
| - this.librarySerializer, this.compilationUnit, this.unitNum);
|
| -
|
| - /**
|
| - * Source object for the compilation unit.
|
| - */
|
| - Source get unitSource => compilationUnit.source;
|
| -
|
| - /**
|
| - * Add all classes, enums, typedefs, executables, and top level variables
|
| - * from the given compilation unit [element] to the compilation unit summary.
|
| - * [unitNum] indicates the ordinal position of this compilation unit in the
|
| - * library.
|
| - */
|
| - void addCompilationUnitElements() {
|
| - unlinkedReferences = <UnlinkedReferenceBuilder>[
|
| - new UnlinkedReferenceBuilder()
|
| - ];
|
| - linkedReferences = <LinkedReferenceBuilder>[
|
| - new LinkedReferenceBuilder(kind: ReferenceKind.unresolved)
|
| - ];
|
| - List<UnlinkedPublicNameBuilder> names = <UnlinkedPublicNameBuilder>[];
|
| - for (PropertyAccessorElement accessor in compilationUnit.accessors) {
|
| - if (accessor.isPublic) {
|
| - names.add(new UnlinkedPublicNameBuilder(
|
| - kind: ReferenceKind.topLevelPropertyAccessor,
|
| - name: accessor.name,
|
| - numTypeParameters: accessor.typeParameters.length));
|
| - }
|
| - }
|
| - for (ClassElement cls in compilationUnit.types) {
|
| - if (cls.isPublic) {
|
| - names.add(new UnlinkedPublicNameBuilder(
|
| - kind: ReferenceKind.classOrEnum,
|
| - name: cls.name,
|
| - numTypeParameters: cls.typeParameters.length,
|
| - members: serializeClassStaticMembers(cls)));
|
| - }
|
| - }
|
| - for (ClassElement enm in compilationUnit.enums) {
|
| - if (enm.isPublic) {
|
| - names.add(new UnlinkedPublicNameBuilder(
|
| - kind: ReferenceKind.classOrEnum,
|
| - name: enm.name,
|
| - members: serializeClassStaticMembers(enm)));
|
| - }
|
| - }
|
| - for (FunctionElement function in compilationUnit.functions) {
|
| - if (function.isPublic) {
|
| - names.add(new UnlinkedPublicNameBuilder(
|
| - kind: ReferenceKind.topLevelFunction,
|
| - name: function.name,
|
| - numTypeParameters: function.typeParameters.length));
|
| - }
|
| - }
|
| - for (FunctionTypeAliasElement typedef
|
| - in compilationUnit.functionTypeAliases) {
|
| - if (typedef.isPublic) {
|
| - names.add(new UnlinkedPublicNameBuilder(
|
| - kind: ReferenceKind.typedef,
|
| - name: typedef.name,
|
| - numTypeParameters: typedef.typeParameters.length));
|
| - }
|
| - }
|
| - if (unitNum == 0) {
|
| - LibraryElement libraryElement = librarySerializer.libraryElement;
|
| - if (libraryElement.name.isNotEmpty) {
|
| - LibraryElement libraryElement = librarySerializer.libraryElement;
|
| - unlinkedUnit.libraryName = libraryElement.name;
|
| - unlinkedUnit.libraryNameOffset = libraryElement.nameOffset;
|
| - unlinkedUnit.libraryNameLength = libraryElement.nameLength;
|
| - unlinkedUnit.libraryDocumentationComment =
|
| - serializeDocumentation(libraryElement);
|
| - unlinkedUnit.libraryAnnotations = serializeAnnotations(libraryElement);
|
| - }
|
| - unlinkedUnit.publicNamespace = new UnlinkedPublicNamespaceBuilder(
|
| - exports: libraryElement.exports.map(serializeExportPublic).toList(),
|
| - parts: libraryElement.parts
|
| - .map((CompilationUnitElement e) => e.uri)
|
| - .toList(),
|
| - names: names);
|
| - unlinkedUnit.exports =
|
| - libraryElement.exports.map(serializeExportNonPublic).toList();
|
| - unlinkedUnit.imports =
|
| - libraryElement.imports.map(serializeImport).toList();
|
| - unlinkedUnit.parts = libraryElement.parts
|
| - .map((CompilationUnitElement e) => new UnlinkedPartBuilder(
|
| - uriOffset: e.uriOffset,
|
| - uriEnd: e.uriEnd,
|
| - annotations: serializeAnnotations(e)))
|
| - .toList();
|
| - } else {
|
| - // TODO(paulberry): we need to figure out a way to record library, part,
|
| - // import, and export declarations that appear in non-defining
|
| - // compilation units (even though such declarations are prohibited by the
|
| - // language), so that if the user makes code changes that cause a
|
| - // non-defining compilation unit to become a defining compilation unit,
|
| - // we can create a correct summary by simply re-linking.
|
| - unlinkedUnit.publicNamespace =
|
| - new UnlinkedPublicNamespaceBuilder(names: names);
|
| - }
|
| - unlinkedUnit.codeRange = serializeCodeRange(compilationUnit);
|
| - unlinkedUnit.classes = compilationUnit.types.map(serializeClass).toList();
|
| - unlinkedUnit.enums = compilationUnit.enums.map(serializeEnum).toList();
|
| - unlinkedUnit.typedefs =
|
| - compilationUnit.functionTypeAliases.map(serializeTypedef).toList();
|
| - List<UnlinkedExecutableBuilder> executables =
|
| - compilationUnit.functions.map(serializeExecutable).toList();
|
| - for (PropertyAccessorElement accessor in compilationUnit.accessors) {
|
| - if (!accessor.isSynthetic) {
|
| - executables.add(serializeExecutable(accessor));
|
| - }
|
| - }
|
| - unlinkedUnit.executables = executables;
|
| - List<UnlinkedVariableBuilder> variables = <UnlinkedVariableBuilder>[];
|
| - for (PropertyAccessorElement accessor in compilationUnit.accessors) {
|
| - if (accessor.isSynthetic && accessor.isGetter) {
|
| - PropertyInducingElement variable = accessor.variable;
|
| - if (variable != null) {
|
| - assert(!variable.isSynthetic);
|
| - variables.add(serializeVariable(variable));
|
| - }
|
| - }
|
| - }
|
| - unlinkedUnit.variables = variables;
|
| - unlinkedUnit.references = unlinkedReferences;
|
| - unlinkedUnit.lineStarts =
|
| - compilationUnit.context?.computeLineInfo(unitSource)?.lineStarts;
|
| - linkedUnit.references = linkedReferences;
|
| - unitUri = compilationUnit.source.uri.toString();
|
| - }
|
| -
|
| - /**
|
| - * Create the [LinkedUnit.types] table based on deferred types that were
|
| - * found during [addCompilationUnitElements]. Also populate
|
| - * [LinkedUnit.constCycles].
|
| - */
|
| - void createLinkedInfo() {
|
| - buildingLinkedReferences = true;
|
| - linkedUnit.types = deferredLinkedTypes
|
| - .map((_SerializeTypeRef closure) => closure())
|
| - .toList();
|
| - linkedUnit.constCycles = constCycles;
|
| - buildingLinkedReferences = false;
|
| - }
|
| -
|
| - /**
|
| - * Compute the appropriate De Bruijn index to represent the given type
|
| - * parameter [type], or return `null` if the type parameter is not in scope.
|
| - */
|
| - int findTypeParameterIndex(TypeParameterType type, Element context) {
|
| - int index = 0;
|
| - while (context != null) {
|
| - List<TypeParameterElement> typeParameters;
|
| - if (context is ClassElement) {
|
| - typeParameters = context.typeParameters;
|
| - } else if (context is FunctionTypeAliasElement) {
|
| - typeParameters = context.typeParameters;
|
| - } else if (context is ExecutableElement) {
|
| - typeParameters = context.typeParameters;
|
| - }
|
| - if (typeParameters != null) {
|
| - for (int i = 0; i < typeParameters.length; i++) {
|
| - TypeParameterElement param = typeParameters[i];
|
| - if (param == type.element) {
|
| - return index + typeParameters.length - i;
|
| - }
|
| - }
|
| - index += typeParameters.length;
|
| - }
|
| - context = context.enclosingElement;
|
| - }
|
| - return null;
|
| - }
|
| -
|
| - /**
|
| - * Get the type arguments for the given [type], or `null` if the type has no
|
| - * type arguments.
|
| - *
|
| - * TODO(paulberry): consider adding an abstract getter to [DartType] to do
|
| - * this.
|
| - */
|
| - List<DartType> getTypeArguments(DartType type) {
|
| - if (type is InterfaceType) {
|
| - return type.typeArguments;
|
| - } else if (type is FunctionType) {
|
| - return type.typeArguments;
|
| - } else {
|
| - return null;
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Serialize annotations from the given [element]. If [element] has no
|
| - * annotations, the empty list is returned.
|
| - */
|
| - List<UnlinkedConstBuilder> serializeAnnotations(Element element) {
|
| - if (element.metadata.isEmpty) {
|
| - return const <UnlinkedConstBuilder>[];
|
| - }
|
| - return element.metadata.map((ElementAnnotation a) {
|
| - _ConstExprSerializer serializer =
|
| - new _ConstExprSerializer(this, element, null, null);
|
| - serializer
|
| - .serializeAnnotation((a as ElementAnnotationImpl).annotationAst);
|
| - return serializer.toBuilder();
|
| - }).toList();
|
| - }
|
| -
|
| - /**
|
| - * Return the index of the entry in the references table
|
| - * ([LinkedLibrary.references]) used for the "bottom" type. A new entry is
|
| - * added to the table if necessary to satisfy the request.
|
| - */
|
| - int serializeBottomReference() {
|
| - if (bottomReferenceIndex == null) {
|
| - // References to the "bottom" type are always implicit, since there is no
|
| - // way to explicitly refer to the "bottom" type. Therefore they should
|
| - // be stored only in the linked references table.
|
| - bottomReferenceIndex = linkedReferences.length;
|
| - linkedReferences.add(new LinkedReferenceBuilder(
|
| - name: '*bottom*', kind: ReferenceKind.classOrEnum));
|
| - }
|
| - return bottomReferenceIndex;
|
| - }
|
| -
|
| - /**
|
| - * Serialize the given [classElement], creating an [UnlinkedClass].
|
| - */
|
| - UnlinkedClassBuilder serializeClass(ClassElement classElement) {
|
| - UnlinkedClassBuilder b = new UnlinkedClassBuilder();
|
| - b.name = classElement.name;
|
| - b.nameOffset = classElement.nameOffset;
|
| - b.typeParameters =
|
| - classElement.typeParameters.map(serializeTypeParam).toList();
|
| - if (classElement.supertype == null) {
|
| - b.hasNoSupertype = true;
|
| - } else if (!classElement.supertype.isObject) {
|
| - b.supertype = serializeTypeRef(classElement.supertype, classElement);
|
| - }
|
| - b.mixins = classElement.mixins
|
| - .map((InterfaceType t) => serializeTypeRef(t, classElement))
|
| - .toList();
|
| - b.interfaces = classElement.interfaces
|
| - .map((InterfaceType t) => serializeTypeRef(t, classElement))
|
| - .toList();
|
| - List<UnlinkedVariableBuilder> fields = <UnlinkedVariableBuilder>[];
|
| - List<UnlinkedExecutableBuilder> executables = <UnlinkedExecutableBuilder>[];
|
| - for (ConstructorElement executable in classElement.constructors) {
|
| - if (!executable.isSynthetic) {
|
| - executables.add(serializeExecutable(executable));
|
| - }
|
| - }
|
| - for (MethodElement executable in classElement.methods) {
|
| - executables.add(serializeExecutable(executable));
|
| - }
|
| - for (PropertyAccessorElement accessor in classElement.accessors) {
|
| - if (!accessor.isSynthetic) {
|
| - executables.add(serializeExecutable(accessor));
|
| - } else if (accessor.isGetter) {
|
| - PropertyInducingElement field = accessor.variable;
|
| - if (field != null && !field.isSynthetic) {
|
| - fields.add(serializeVariable(field));
|
| - }
|
| - }
|
| - }
|
| - b.fields = fields;
|
| - b.executables = executables;
|
| - b.isAbstract = classElement.isAbstract;
|
| - b.isMixinApplication = classElement.isMixinApplication;
|
| - b.documentationComment = serializeDocumentation(classElement);
|
| - b.annotations = serializeAnnotations(classElement);
|
| - b.codeRange = serializeCodeRange(classElement);
|
| - return b;
|
| - }
|
| -
|
| - /**
|
| - * If [cls] is a class, return the list of its static members - static
|
| - * constant fields, static methods and constructors. Otherwise return `null`.
|
| - */
|
| - List<UnlinkedPublicNameBuilder> serializeClassStaticMembers(
|
| - ClassElement cls) {
|
| - if (cls.isMixinApplication) {
|
| - // Mixin application members can't be determined directly from the AST so
|
| - // we can't store them in UnlinkedPublicName.
|
| - // TODO(paulberry): find somewhere else to store them.
|
| - return null;
|
| - }
|
| - if (cls.kind == ElementKind.CLASS) {
|
| - List<UnlinkedPublicNameBuilder> bs = <UnlinkedPublicNameBuilder>[];
|
| - for (MethodElement method in cls.methods) {
|
| - if (method.isStatic && method.isPublic) {
|
| - // TODO(paulberry): should numTypeParameters include class params?
|
| - bs.add(new UnlinkedPublicNameBuilder(
|
| - name: method.name,
|
| - kind: ReferenceKind.method,
|
| - numTypeParameters: method.typeParameters.length));
|
| - }
|
| - }
|
| - for (PropertyAccessorElement accessor in cls.accessors) {
|
| - if (accessor.isStatic && accessor.isGetter && accessor.isPublic) {
|
| - // TODO(paulberry): should numTypeParameters include class params?
|
| - bs.add(new UnlinkedPublicNameBuilder(
|
| - name: accessor.name, kind: ReferenceKind.propertyAccessor));
|
| - }
|
| - }
|
| - for (ConstructorElement constructor in cls.constructors) {
|
| - if (constructor.isPublic && constructor.name.isNotEmpty) {
|
| - // TODO(paulberry): should numTypeParameters include class params?
|
| - bs.add(new UnlinkedPublicNameBuilder(
|
| - name: constructor.name,
|
| - kind: ReferenceKind.constructor,
|
| - numTypeParameters: 0));
|
| - }
|
| - }
|
| - return bs;
|
| - }
|
| - return null;
|
| - }
|
| -
|
| - CodeRangeBuilder serializeCodeRange(Element element) {
|
| - if (element is ElementImpl && element.codeOffset != null) {
|
| - return new CodeRangeBuilder(
|
| - offset: element.codeOffset, length: element.codeLength);
|
| - }
|
| - return null;
|
| - }
|
| -
|
| - /**
|
| - * Serialize the given [combinator] into an [UnlinkedCombinator].
|
| - */
|
| - UnlinkedCombinatorBuilder serializeCombinator(
|
| - NamespaceCombinator combinator) {
|
| - UnlinkedCombinatorBuilder b = new UnlinkedCombinatorBuilder();
|
| - if (combinator is ShowElementCombinator) {
|
| - b.shows = combinator.shownNames;
|
| - b.offset = combinator.offset;
|
| - b.end = combinator.end;
|
| - } else if (combinator is HideElementCombinator) {
|
| - b.hides = combinator.hiddenNames;
|
| - }
|
| - return b;
|
| - }
|
| -
|
| - /**
|
| - * Serialize the given [expression], creating an [UnlinkedConstBuilder].
|
| - */
|
| - UnlinkedConstBuilder serializeConstExpr(Element context,
|
| - ExecutableElement executableContext, Expression expression,
|
| - [Set<String> constructorParameterNames]) {
|
| - _ConstExprSerializer serializer = new _ConstExprSerializer(
|
| - this, context, executableContext, constructorParameterNames);
|
| - serializer.serialize(expression);
|
| - return serializer.toBuilder();
|
| - }
|
| -
|
| - /**
|
| - * Serialize documentation from the given [element], creating an
|
| - * [UnlinkedDocumentationComment].
|
| - *
|
| - * If [element] has no documentation, `null` is returned.
|
| - */
|
| - UnlinkedDocumentationCommentBuilder serializeDocumentation(Element element) {
|
| - if (element.documentationComment == null) {
|
| - return null;
|
| - }
|
| - return new UnlinkedDocumentationCommentBuilder(
|
| - text: element.documentationComment);
|
| - }
|
| -
|
| - /**
|
| - * Serialize the given [enumElement], creating an [UnlinkedEnum].
|
| - */
|
| - UnlinkedEnumBuilder serializeEnum(ClassElement enumElement) {
|
| - UnlinkedEnumBuilder b = new UnlinkedEnumBuilder();
|
| - b.name = enumElement.name;
|
| - b.nameOffset = enumElement.nameOffset;
|
| - List<UnlinkedEnumValueBuilder> values = <UnlinkedEnumValueBuilder>[];
|
| - for (FieldElement field in enumElement.fields) {
|
| - if (field.isConst && field.type.element == enumElement) {
|
| - values.add(new UnlinkedEnumValueBuilder(
|
| - name: field.name,
|
| - nameOffset: field.nameOffset,
|
| - documentationComment: serializeDocumentation(field)));
|
| - }
|
| - }
|
| - b.values = values;
|
| - b.documentationComment = serializeDocumentation(enumElement);
|
| - b.annotations = serializeAnnotations(enumElement);
|
| - b.codeRange = serializeCodeRange(enumElement);
|
| - return b;
|
| - }
|
| -
|
| - /**
|
| - * Serialize the given [executableElement], creating an [UnlinkedExecutable].
|
| - */
|
| - UnlinkedExecutableBuilder serializeExecutable(
|
| - ExecutableElement executableElement) {
|
| - UnlinkedExecutableBuilder b = new UnlinkedExecutableBuilder();
|
| - b.name = executableElement.name;
|
| - b.nameOffset = executableElement.nameOffset;
|
| - if (executableElement is ConstructorElement) {
|
| - if (executableElement.name.isNotEmpty) {
|
| - b.nameEnd = executableElement.nameEnd;
|
| - b.periodOffset = executableElement.periodOffset;
|
| - }
|
| - } else {
|
| - if (!executableElement.hasImplicitReturnType) {
|
| - b.returnType = serializeTypeRef(
|
| - executableElement.type.returnType, executableElement);
|
| - } else if (!executableElement.isStatic) {
|
| - b.inferredReturnTypeSlot =
|
| - storeInferredType(executableElement.returnType, executableElement);
|
| - }
|
| - }
|
| - b.typeParameters =
|
| - executableElement.typeParameters.map(serializeTypeParam).toList();
|
| - b.parameters =
|
| - executableElement.type.parameters.map(serializeParam).toList();
|
| - if (executableElement is PropertyAccessorElement) {
|
| - if (executableElement.isGetter) {
|
| - b.kind = UnlinkedExecutableKind.getter;
|
| - } else {
|
| - b.kind = UnlinkedExecutableKind.setter;
|
| - }
|
| - } else if (executableElement is ConstructorElementImpl) {
|
| - b.kind = UnlinkedExecutableKind.constructor;
|
| - b.isConst = executableElement.isConst;
|
| - b.isFactory = executableElement.isFactory;
|
| - ConstructorElement redirectedConstructor =
|
| - executableElement.redirectedConstructor;
|
| - if (redirectedConstructor != null) {
|
| - b.isRedirectedConstructor = true;
|
| - if (executableElement.isFactory) {
|
| - InterfaceType returnType = redirectedConstructor is ConstructorMember
|
| - ? redirectedConstructor.definingType
|
| - : redirectedConstructor.enclosingElement.type;
|
| - EntityRefBuilder typeRef =
|
| - serializeTypeRef(returnType, executableElement);
|
| - if (redirectedConstructor.name.isNotEmpty) {
|
| - String name = redirectedConstructor.name;
|
| - int typeId = typeRef.reference;
|
| - LinkedReference typeLinkedRef = linkedReferences[typeId];
|
| - int refId = serializeUnlinkedReference(
|
| - name, ReferenceKind.constructor,
|
| - unit: typeLinkedRef.unit, prefixReference: typeId);
|
| - b.redirectedConstructor = new EntityRefBuilder(
|
| - reference: refId, typeArguments: typeRef.typeArguments);
|
| - } else {
|
| - b.redirectedConstructor = typeRef;
|
| - }
|
| - } else {
|
| - b.redirectedConstructorName = redirectedConstructor.name;
|
| - }
|
| - }
|
| - if (executableElement.isConst) {
|
| - b.constCycleSlot = storeConstCycle(!executableElement.isCycleFree);
|
| - if (executableElement.constantInitializers != null) {
|
| - Set<String> constructorParameterNames =
|
| - executableElement.parameters.map((p) => p.name).toSet();
|
| - b.constantInitializers = executableElement.constantInitializers
|
| - .map((ConstructorInitializer initializer) =>
|
| - serializeConstructorInitializer(
|
| - initializer,
|
| - (expr) => serializeConstExpr(executableElement,
|
| - executableElement, expr, constructorParameterNames)))
|
| - .toList();
|
| - }
|
| - }
|
| - } else {
|
| - b.kind = UnlinkedExecutableKind.functionOrMethod;
|
| - }
|
| - b.isAbstract = executableElement.isAbstract;
|
| - b.isAsynchronous = executableElement.isAsynchronous;
|
| - b.isGenerator = executableElement.isGenerator;
|
| - b.isStatic = executableElement.isStatic &&
|
| - executableElement.enclosingElement is ClassElement;
|
| - b.isExternal = executableElement.isExternal;
|
| - b.documentationComment = serializeDocumentation(executableElement);
|
| - b.annotations = serializeAnnotations(executableElement);
|
| - b.codeRange = serializeCodeRange(executableElement);
|
| - if (executableElement is FunctionElement) {
|
| - SourceRange visibleRange = executableElement.visibleRange;
|
| - if (visibleRange != null) {
|
| - b.visibleOffset = visibleRange.offset;
|
| - b.visibleLength = visibleRange.length;
|
| - }
|
| - }
|
| - b.localFunctions =
|
| - executableElement.functions.map(serializeExecutable).toList();
|
| - b.localLabels = executableElement.labels.map(serializeLabel).toList();
|
| - b.localVariables =
|
| - executableElement.localVariables.map(serializeVariable).toList();
|
| - return b;
|
| - }
|
| -
|
| - /**
|
| - * Serialize the given [exportElement] into an [UnlinkedExportNonPublic].
|
| - */
|
| - UnlinkedExportNonPublicBuilder serializeExportNonPublic(
|
| - ExportElement exportElement) {
|
| - UnlinkedExportNonPublicBuilder b = new UnlinkedExportNonPublicBuilder();
|
| - b.offset = exportElement.nameOffset;
|
| - b.uriOffset = exportElement.uriOffset;
|
| - b.uriEnd = exportElement.uriEnd;
|
| - b.annotations = serializeAnnotations(exportElement);
|
| - return b;
|
| - }
|
| -
|
| - /**
|
| - * Serialize the given [exportElement] into an [UnlinkedExportPublic].
|
| - */
|
| - UnlinkedExportPublicBuilder serializeExportPublic(
|
| - ExportElement exportElement) {
|
| - UnlinkedExportPublicBuilder b = new UnlinkedExportPublicBuilder();
|
| - b.uri = exportElement.uri;
|
| - b.combinators = exportElement.combinators.map(serializeCombinator).toList();
|
| - return b;
|
| - }
|
| -
|
| - /**
|
| - * Serialize the given [importElement] yielding an [UnlinkedImportBuilder].
|
| - * Also, add linked information about it to the [linkedImports] list.
|
| - */
|
| - UnlinkedImportBuilder serializeImport(ImportElement importElement) {
|
| - UnlinkedImportBuilder b = new UnlinkedImportBuilder();
|
| - b.annotations = serializeAnnotations(importElement);
|
| - b.isDeferred = importElement.isDeferred;
|
| - b.combinators = importElement.combinators.map(serializeCombinator).toList();
|
| - if (importElement.prefix != null) {
|
| - b.prefixReference = serializePrefix(importElement.prefix);
|
| - b.prefixOffset = importElement.prefix.nameOffset;
|
| - }
|
| - if (importElement.isSynthetic) {
|
| - b.isImplicit = true;
|
| - } else {
|
| - b.offset = importElement.nameOffset;
|
| - b.uri = importElement.uri;
|
| - b.uriOffset = importElement.uriOffset;
|
| - b.uriEnd = importElement.uriEnd;
|
| - }
|
| - return b;
|
| - }
|
| -
|
| - /**
|
| - * Serialize the given [label], creating an [UnlinkedLabelBuilder].
|
| - */
|
| - UnlinkedLabelBuilder serializeLabel(LabelElement label) {
|
| - LabelElementImpl labelImpl = label as LabelElementImpl;
|
| - UnlinkedLabelBuilder b = new UnlinkedLabelBuilder();
|
| - b.name = labelImpl.name;
|
| - b.nameOffset = labelImpl.nameOffset;
|
| - b.isOnSwitchMember = labelImpl.isOnSwitchMember;
|
| - b.isOnSwitchStatement = labelImpl.isOnSwitchStatement;
|
| - return b;
|
| - }
|
| -
|
| - /**
|
| - * Serialize the given [parameter] into an [UnlinkedParam].
|
| - */
|
| - UnlinkedParamBuilder serializeParam(ParameterElement parameter,
|
| - [Element context]) {
|
| - context ??= parameter;
|
| - UnlinkedParamBuilder b = new UnlinkedParamBuilder();
|
| - b.name = parameter.name;
|
| - b.nameOffset = parameter.nameOffset >= 0 ? parameter.nameOffset : 0;
|
| - switch (parameter.parameterKind) {
|
| - case ParameterKind.REQUIRED:
|
| - b.kind = UnlinkedParamKind.required;
|
| - break;
|
| - case ParameterKind.POSITIONAL:
|
| - b.kind = UnlinkedParamKind.positional;
|
| - break;
|
| - case ParameterKind.NAMED:
|
| - b.kind = UnlinkedParamKind.named;
|
| - break;
|
| - }
|
| - b.annotations = serializeAnnotations(parameter);
|
| - b.codeRange = serializeCodeRange(parameter);
|
| - b.isInitializingFormal = parameter.isInitializingFormal;
|
| - DartType type = parameter.type;
|
| - if (parameter.hasImplicitType) {
|
| - Element contextParent = context.enclosingElement;
|
| - if (!parameter.isInitializingFormal &&
|
| - contextParent is ExecutableElement &&
|
| - !contextParent.isStatic &&
|
| - contextParent is! ConstructorElement) {
|
| - b.inferredTypeSlot = storeInferredType(type, context);
|
| - }
|
| - } else {
|
| - if (type is FunctionType && type.element.isSynthetic) {
|
| - b.isFunctionTyped = true;
|
| - b.type = serializeTypeRef(type.returnType, parameter);
|
| - b.parameters = type.parameters
|
| - .map((parameter) => serializeParam(parameter, context))
|
| - .toList();
|
| - } else {
|
| - b.type = serializeTypeRef(type, context);
|
| - }
|
| - }
|
| - // TODO(scheglov) VariableMember.initializer is not implemented
|
| - if (parameter is! VariableMember && parameter.initializer != null) {
|
| - b.initializer = serializeExecutable(parameter.initializer);
|
| - }
|
| - if (parameter is ConstVariableElement) {
|
| - ConstVariableElement constParameter = parameter as ConstVariableElement;
|
| - Expression initializer = constParameter.constantInitializer;
|
| - if (initializer != null) {
|
| - b.initializer?.bodyExpr = serializeConstExpr(
|
| - parameter,
|
| - parameter.getAncestor((Element e) => e is ExecutableElement),
|
| - initializer);
|
| - b.defaultValueCode = parameter.defaultValueCode;
|
| - }
|
| - }
|
| - {
|
| - SourceRange visibleRange = parameter.visibleRange;
|
| - if (visibleRange != null) {
|
| - b.visibleOffset = visibleRange.offset;
|
| - b.visibleLength = visibleRange.length;
|
| - }
|
| - }
|
| - return b;
|
| - }
|
| -
|
| - /**
|
| - * Serialize the given [prefix] into an index into the references table.
|
| - */
|
| - int serializePrefix(PrefixElement element) {
|
| - return referenceMap.putIfAbsent(element,
|
| - () => serializeUnlinkedReference(element.name, ReferenceKind.prefix));
|
| - }
|
| -
|
| - /**
|
| - * Compute the reference index which should be stored in a [EntityRef].
|
| - */
|
| - int serializeReferenceForType(DartType type) {
|
| - Element element = type.element;
|
| - LibraryElement dependentLibrary = element?.library;
|
| - if (dependentLibrary == null) {
|
| - if (type.isBottom) {
|
| - // References to the "bottom" type are always implicit, since there is
|
| - // no way to explicitly refer to the "bottom" type. Therefore they
|
| - // should always be linked.
|
| - assert(buildingLinkedReferences);
|
| - return serializeBottomReference();
|
| - }
|
| - assert(type.isDynamic || type.isVoid);
|
| - if (type is UndefinedTypeImpl) {
|
| - return serializeUnresolvedReference();
|
| - }
|
| - // Note: for a type which is truly `dynamic` or `void`, fall through to
|
| - // use [_getElementReferenceId].
|
| - }
|
| - return _getElementReferenceId(element);
|
| - }
|
| -
|
| - /**
|
| - * Serialize the given [typedefElement], creating an [UnlinkedTypedef].
|
| - */
|
| - UnlinkedTypedefBuilder serializeTypedef(
|
| - FunctionTypeAliasElement typedefElement) {
|
| - UnlinkedTypedefBuilder b = new UnlinkedTypedefBuilder();
|
| - b.name = typedefElement.name;
|
| - b.nameOffset = typedefElement.nameOffset;
|
| - b.typeParameters =
|
| - typedefElement.typeParameters.map(serializeTypeParam).toList();
|
| - b.returnType = serializeTypeRef(typedefElement.returnType, typedefElement);
|
| - b.parameters = typedefElement.parameters.map(serializeParam).toList();
|
| - b.documentationComment = serializeDocumentation(typedefElement);
|
| - b.annotations = serializeAnnotations(typedefElement);
|
| - b.codeRange = serializeCodeRange(typedefElement);
|
| - return b;
|
| - }
|
| -
|
| - /**
|
| - * Serialize the given [typeParameter] into an [UnlinkedTypeParam].
|
| - */
|
| - UnlinkedTypeParamBuilder serializeTypeParam(
|
| - TypeParameterElement typeParameter) {
|
| - UnlinkedTypeParamBuilder b = new UnlinkedTypeParamBuilder();
|
| - b.name = typeParameter.name;
|
| - b.nameOffset = typeParameter.nameOffset;
|
| - if (typeParameter.bound != null) {
|
| - b.bound = serializeTypeRef(typeParameter.bound, typeParameter);
|
| - }
|
| - b.annotations = serializeAnnotations(typeParameter);
|
| - b.codeRange = serializeCodeRange(typeParameter);
|
| - return b;
|
| - }
|
| -
|
| - /**
|
| - * Serialize the given [type] into a [EntityRef]. If [slot] is provided,
|
| - * it should be included in the [EntityRef].
|
| - *
|
| - * [context] is the element within which the [EntityRef] will be
|
| - * interpreted; this is used to serialize type parameters.
|
| - */
|
| - EntityRefBuilder serializeTypeRef(DartType type, Element context,
|
| - {int slot}) {
|
| - if (slot != null) {
|
| - assert(buildingLinkedReferences);
|
| - }
|
| - EntityRefBuilder b = new EntityRefBuilder(slot: slot);
|
| - Element typeElement = type.element;
|
| - if (type is TypeParameterType) {
|
| - int typeParameterIndex = findTypeParameterIndex(type, context);
|
| - if (typeParameterIndex != null) {
|
| - b.paramReference = typeParameterIndex;
|
| - } else {
|
| - // Out-of-scope type parameters only occur in circumstances where they
|
| - // are irrelevant (i.e. when a type parameter is unused). So we can
|
| - // safely convert them to `dynamic`.
|
| - b.reference = serializeReferenceForType(DynamicTypeImpl.instance);
|
| - }
|
| - } else if (type is FunctionType &&
|
| - typeElement is FunctionElement &&
|
| - typeElement.enclosingElement == null) {
|
| - b.syntheticReturnType =
|
| - serializeTypeRef(typeElement.returnType, typeElement);
|
| - b.syntheticParams = typeElement.parameters
|
| - .map((ParameterElement param) => serializeParam(param, context))
|
| - .toList();
|
| - } else {
|
| - if (type is FunctionType &&
|
| - typeElement.enclosingElement is ParameterElement) {
|
| - // Code cannot refer to function types implicitly defined by parameters
|
| - // directly, so if we get here, we must be serializing a linked
|
| - // reference from type inference.
|
| - assert(buildingLinkedReferences);
|
| - ParameterElement parameterElement = typeElement.enclosingElement;
|
| - while (true) {
|
| - Element parent = parameterElement.enclosingElement;
|
| - if (parent is ParameterElement) {
|
| - // Function-typed parameter inside a function-typed parameter.
|
| - b.implicitFunctionTypeIndices
|
| - .insert(0, parent.parameters.indexOf(parameterElement));
|
| - parameterElement = parent;
|
| - continue;
|
| - } else if (parent is FunctionTypedElement) {
|
| - b.implicitFunctionTypeIndices
|
| - .insert(0, parent.parameters.indexOf(parameterElement));
|
| - // Function-typed parameter inside a top level function, method, or
|
| - // typedef.
|
| - b.reference = _getElementReferenceId(parent);
|
| - break;
|
| - } else {
|
| - throw new StateError(
|
| - 'Unexpected element enclosing parameter: ${parent.runtimeType}');
|
| - }
|
| - }
|
| - } else {
|
| - b.reference = serializeReferenceForType(type);
|
| - }
|
| - List<DartType> typeArguments = getTypeArguments(type);
|
| - if (typeArguments != null) {
|
| - b.typeArguments = typeArguments
|
| - .map((typeArgument) => serializeTypeRef(typeArgument, context))
|
| - .toList();
|
| - }
|
| - }
|
| - return b;
|
| - }
|
| -
|
| - /**
|
| - * Create a new entry in the references table ([UnlinkedUnit.references]
|
| - * and [LinkedUnit.references]) representing an entity having the given
|
| - * [name] and [kind]. If [unit] is given, it is the index of the compilation
|
| - * unit containing the entity being referred to. If [prefixReference] is
|
| - * given, it indicates the entry in the references table for the prefix.
|
| - */
|
| - int serializeUnlinkedReference(String name, ReferenceKind kind,
|
| - {int unit: 0, int prefixReference: 0}) {
|
| - assert(unlinkedReferences.length == linkedReferences.length);
|
| - int index = unlinkedReferences.length;
|
| - unlinkedReferences.add(new UnlinkedReferenceBuilder(
|
| - name: name, prefixReference: prefixReference));
|
| - linkedReferences.add(new LinkedReferenceBuilder(kind: kind, unit: unit));
|
| - return index;
|
| - }
|
| -
|
| - /**
|
| - * Return the index of the entry in the references table
|
| - * ([UnlinkedLibrary.references] and [LinkedLibrary.references]) used for
|
| - * unresolved references. A new entry is added to the table if necessary to
|
| - * satisfy the request.
|
| - */
|
| - int serializeUnresolvedReference() {
|
| - // TODO(paulberry): in order for relinking to work, we need to record the
|
| - // name and prefix of the unresolved symbol. This is not (yet) encoded in
|
| - // the element model. For the moment we use a name that can't possibly
|
| - // ever exist.
|
| - if (unresolvedReferenceIndex == null) {
|
| - unresolvedReferenceIndex =
|
| - serializeUnlinkedReference('*unresolved*', ReferenceKind.unresolved);
|
| - }
|
| - return unresolvedReferenceIndex;
|
| - }
|
| -
|
| - /**
|
| - * Serialize the given [variable], creating an [UnlinkedVariable].
|
| - */
|
| - UnlinkedVariableBuilder serializeVariable(VariableElement variable) {
|
| - UnlinkedVariableBuilder b = new UnlinkedVariableBuilder();
|
| - b.name = variable.name;
|
| - b.nameOffset = variable.nameOffset;
|
| - if (!variable.hasImplicitType) {
|
| - b.type = serializeTypeRef(variable.type, variable);
|
| - }
|
| - b.isStatic = variable.isStatic && variable.enclosingElement is ClassElement;
|
| - b.isFinal = variable.isFinal;
|
| - b.isConst = variable.isConst;
|
| - b.documentationComment = serializeDocumentation(variable);
|
| - b.annotations = serializeAnnotations(variable);
|
| - // TODO(scheglov) VariableMember.initializer is not implemented
|
| - if (variable is! VariableMember && variable.initializer != null) {
|
| - b.initializer = serializeExecutable(variable.initializer);
|
| - }
|
| - if (variable is ConstVariableElement) {
|
| - ConstVariableElement constVariable = variable as ConstVariableElement;
|
| - Expression initializer = constVariable.constantInitializer;
|
| - if (initializer != null) {
|
| - b.initializer?.bodyExpr =
|
| - serializeConstExpr(variable, variable.initializer, initializer);
|
| - }
|
| - }
|
| - if (variable is PropertyInducingElement) {
|
| - if (b.isFinal || b.isConst) {
|
| - b.propagatedTypeSlot =
|
| - storeLinkedType(variable.propagatedType, variable);
|
| - } else {
|
| - // Variable is not propagable.
|
| - assert(variable.propagatedType == null);
|
| - }
|
| - }
|
| - if (variable.hasImplicitType &&
|
| - (variable.initializer != null || !variable.isStatic)) {
|
| - b.inferredTypeSlot = storeInferredType(variable.type, variable);
|
| - }
|
| - b.codeRange = serializeCodeRange(variable);
|
| - if (variable is LocalVariableElement) {
|
| - SourceRange visibleRange = variable.visibleRange;
|
| - if (visibleRange != null) {
|
| - b.visibleOffset = visibleRange.offset;
|
| - b.visibleLength = visibleRange.length;
|
| - }
|
| - }
|
| - return b;
|
| - }
|
| -
|
| - /**
|
| - * Create a new slot id and return it. If [hasCycle] is `true`, arrange for
|
| - * the slot id to be included in [LinkedUnit.constCycles].
|
| - */
|
| - int storeConstCycle(bool hasCycle) {
|
| - int slot = ++numSlots;
|
| - if (hasCycle) {
|
| - constCycles.add(slot);
|
| - }
|
| - return slot;
|
| - }
|
| -
|
| - /**
|
| - * Create a slot id for the given [type] (which is an inferred type). If
|
| - * [type] is not `dynamic`, it is stored in [linkedTypes] so that once the
|
| - * compilation unit has been fully visited, it will be serialized into
|
| - * [LinkedUnit.types].
|
| - *
|
| - * [context] is the element within which the slot id will appear; this is
|
| - * used to serialize type parameters.
|
| - */
|
| - int storeInferredType(DartType type, Element context) {
|
| - return storeLinkedType(type.isDynamic ? null : type, context);
|
| - }
|
| -
|
| - /**
|
| - * Create a slot id for the given [type] (which may be either a propagated
|
| - * type or an inferred type). If [type] is not `null`, it is stored in
|
| - * [linkedTypes] so that once the compilation unit has been fully visited,
|
| - * it will be serialized to [LinkedUnit.types].
|
| - *
|
| - * [context] is the element within which the slot id will appear; this is
|
| - * used to serialize type parameters.
|
| - */
|
| - int storeLinkedType(DartType type, Element context) {
|
| - int slot = ++numSlots;
|
| - if (type != null) {
|
| - deferredLinkedTypes
|
| - .add(() => serializeTypeRef(type, context, slot: slot));
|
| - }
|
| - return slot;
|
| - }
|
| -
|
| - int _getElementReferenceId(Element element) {
|
| - return referenceMap.putIfAbsent(element, () {
|
| - LibraryElement dependentLibrary = librarySerializer.libraryElement;
|
| - int unit = 0;
|
| - Element enclosingElement;
|
| - if (element != null) {
|
| - enclosingElement = element.enclosingElement;
|
| - if (enclosingElement is CompilationUnitElement) {
|
| - dependentLibrary = enclosingElement.library;
|
| - unit = dependentLibrary.units.indexOf(enclosingElement);
|
| - assert(unit != -1);
|
| - }
|
| - }
|
| - ReferenceKind kind = _getReferenceKind(element);
|
| - String name = element == null ? 'void' : element.name;
|
| - int index;
|
| - LinkedReferenceBuilder linkedReference;
|
| - if (buildingLinkedReferences) {
|
| - linkedReference =
|
| - new LinkedReferenceBuilder(kind: kind, unit: unit, name: name);
|
| - if (enclosingElement != null &&
|
| - enclosingElement is! CompilationUnitElement) {
|
| - linkedReference.containingReference =
|
| - _getElementReferenceId(enclosingElement);
|
| - if (enclosingElement is ClassElement) {
|
| - // Nothing to do.
|
| - } else if (enclosingElement is ExecutableElement) {
|
| - if (element is FunctionElement) {
|
| - assert(enclosingElement.functions.contains(element));
|
| - linkedReference.localIndex =
|
| - enclosingElement.functions.indexOf(element);
|
| - } else if (element is LocalVariableElement) {
|
| - assert(enclosingElement.localVariables.contains(element));
|
| - linkedReference.localIndex =
|
| - enclosingElement.localVariables.indexOf(element);
|
| - } else {
|
| - throw new StateError(
|
| - 'Unexpected enclosed element type: ${element.runtimeType}');
|
| - }
|
| - } else if (enclosingElement is VariableElement) {
|
| - assert(identical(enclosingElement.initializer, element));
|
| - } else {
|
| - throw new StateError(
|
| - 'Unexpected enclosing element type: ${enclosingElement.runtimeType}');
|
| - }
|
| - }
|
| - index = linkedReferences.length;
|
| - linkedReferences.add(linkedReference);
|
| - } else {
|
| - assert(unlinkedReferences.length == linkedReferences.length);
|
| - int prefixReference = 0;
|
| - Element enclosing = element?.enclosingElement;
|
| - if (enclosing == null || enclosing is CompilationUnitElement) {
|
| - // Figure out a prefix that may be used to refer to the given element.
|
| - // TODO(paulberry): to avoid subtle relinking inconsistencies we
|
| - // should use the actual prefix from the AST (a given type may be
|
| - // reachable via multiple prefixes), but sadly, this information is
|
| - // not recorded in the element model.
|
| - PrefixElement prefix = librarySerializer.prefixMap[element];
|
| - if (prefix != null) {
|
| - prefixReference = serializePrefix(prefix);
|
| - }
|
| - } else {
|
| - prefixReference = _getElementReferenceId(enclosing);
|
| - }
|
| - index = serializeUnlinkedReference(name, kind,
|
| - prefixReference: prefixReference, unit: unit);
|
| - linkedReference = linkedReferences[index];
|
| - }
|
| - linkedReference.dependency =
|
| - librarySerializer.serializeDependency(dependentLibrary);
|
| - if (element is TypeParameterizedElement) {
|
| - linkedReference.numTypeParameters += element.typeParameters.length;
|
| - }
|
| - return index;
|
| - });
|
| - }
|
| -}
|
| -
|
| -/**
|
| - * Instances of this class keep track of intermediate state during
|
| - * serialization of a single constant [Expression].
|
| - */
|
| -class _ConstExprSerializer extends AbstractConstExprSerializer {
|
| - final _CompilationUnitSerializer serializer;
|
| - final Element context;
|
| - final ExecutableElement executableContext;
|
| -
|
| - /**
|
| - * If a constructor initializer expression is being serialized, the names of
|
| - * the constructor parameters. Otherwise `null`.
|
| - */
|
| - final Set<String> constructorParameterNames;
|
| -
|
| - _ConstExprSerializer(this.serializer, this.context, this.executableContext,
|
| - this.constructorParameterNames);
|
| -
|
| - @override
|
| - bool isParameterName(String name) {
|
| - return constructorParameterNames?.contains(name) ?? false;
|
| - }
|
| -
|
| - @override
|
| - void serializeAnnotation(Annotation annotation) {
|
| - if (annotation.arguments == null) {
|
| - assert(annotation.constructorName == null);
|
| - serialize(annotation.name);
|
| - } else {
|
| - Identifier name = annotation.name;
|
| - Element nameElement = name.staticElement;
|
| - EntityRefBuilder constructor;
|
| - if (nameElement is ConstructorElement && name is PrefixedIdentifier) {
|
| - assert(annotation.constructorName == null);
|
| - constructor = serializeConstructorRef(
|
| - nameElement.returnType, name.prefix, null, name.identifier);
|
| - } else if (nameElement is TypeDefiningElement) {
|
| - constructor = serializeConstructorRef(nameElement.type, annotation.name,
|
| - null, annotation.constructorName);
|
| - } else if (nameElement == null) {
|
| - // Unresolved annotation.
|
| - if (name is PrefixedIdentifier && annotation.constructorName == null) {
|
| - constructor =
|
| - serializeConstructorRef(null, name.prefix, null, name.identifier);
|
| - } else {
|
| - constructor = serializeConstructorRef(
|
| - null, annotation.name, null, annotation.constructorName);
|
| - }
|
| - } else {
|
| - throw new StateError('Unexpected annotation nameElement type:'
|
| - ' ${nameElement.runtimeType}');
|
| - }
|
| - serializeInstanceCreation(constructor, annotation.arguments);
|
| - }
|
| - }
|
| -
|
| - @override
|
| - EntityRefBuilder serializeConstructorRef(DartType type, Identifier typeName,
|
| - TypeArgumentList typeArguments, SimpleIdentifier name) {
|
| - EntityRefBuilder typeRef = serializeType(type, typeName, typeArguments);
|
| - if (name == null) {
|
| - return typeRef;
|
| - } else {
|
| - LinkedReference typeLinkedRef =
|
| - serializer.linkedReferences[typeRef.reference];
|
| - int refId = serializer.serializeUnlinkedReference(
|
| - name.name,
|
| - name.staticElement != null
|
| - ? ReferenceKind.constructor
|
| - : ReferenceKind.unresolved,
|
| - prefixReference: typeRef.reference,
|
| - unit: typeLinkedRef.unit);
|
| - return new EntityRefBuilder(
|
| - reference: refId, typeArguments: typeRef.typeArguments);
|
| - }
|
| - }
|
| -
|
| - @override
|
| - List<int> serializeFunctionExpression(FunctionExpression functionExpression) {
|
| - if (executableContext == null) {
|
| - return null;
|
| - }
|
| - ExecutableElement functionElement = functionExpression.element;
|
| - // TOOD(paulberry): handle the situation where [functionExpression] is not
|
| - // an immediate child of [executableContext].
|
| - assert(functionElement.enclosingElement == executableContext);
|
| - int popCount = 0;
|
| - int localIndex = executableContext.functions.indexOf(functionElement);
|
| - assert(localIndex != -1);
|
| - return <int>[popCount, localIndex];
|
| - }
|
| -
|
| - EntityRefBuilder serializeIdentifier(Identifier identifier,
|
| - {int prefixReference: 0}) {
|
| - if (identifier is SimpleIdentifier) {
|
| - Element element = identifier.staticElement;
|
| - if (element is TypeParameterElement) {
|
| - int typeParameterIndex =
|
| - serializer.findTypeParameterIndex(element.type, context);
|
| - return new EntityRefBuilder(paramReference: typeParameterIndex);
|
| - } else if (_isPrelinkResolvableElement(element)) {
|
| - int ref = serializer._getElementReferenceId(element);
|
| - return new EntityRefBuilder(reference: ref);
|
| - } else {
|
| - int ref = serializer.serializeUnlinkedReference(
|
| - identifier.name, ReferenceKind.unresolved);
|
| - return new EntityRefBuilder(reference: ref);
|
| - }
|
| - } else if (identifier is PrefixedIdentifier) {
|
| - Element element = identifier.staticElement;
|
| - if (_isPrelinkResolvableElement(element)) {
|
| - int ref = serializer._getElementReferenceId(element);
|
| - return new EntityRefBuilder(reference: ref);
|
| - } else {
|
| - int prefixRef = serializeIdentifier(identifier.prefix).reference;
|
| - int ref = serializer.serializeUnlinkedReference(
|
| - identifier.identifier.name, ReferenceKind.unresolved,
|
| - prefixReference: prefixRef);
|
| - return new EntityRefBuilder(reference: ref);
|
| - }
|
| - } else {
|
| - throw new StateError(
|
| - 'Unexpected identifier type: ${identifier.runtimeType}');
|
| - }
|
| - }
|
| -
|
| - @override
|
| - EntityRefBuilder serializeIdentifierSequence(Expression expr) {
|
| - if (expr is Identifier) {
|
| - return serializeIdentifier(expr);
|
| - }
|
| - if (expr is PropertyAccess) {
|
| - Element element = expr.propertyName.staticElement;
|
| - if (_isPrelinkResolvableElement(element)) {
|
| - int ref = serializer._getElementReferenceId(element);
|
| - return new EntityRefBuilder(reference: ref);
|
| - } else {
|
| - int targetRef = serializeIdentifierSequence(expr.target).reference;
|
| - int ref = serializer.serializeUnlinkedReference(
|
| - expr.propertyName.name, ReferenceKind.unresolved,
|
| - prefixReference: targetRef);
|
| - return new EntityRefBuilder(reference: ref);
|
| - }
|
| - } else {
|
| - throw new StateError('Unexpected node type: ${expr.runtimeType}');
|
| - }
|
| - }
|
| -
|
| - @override
|
| - EntityRefBuilder serializeType(
|
| - DartType type, Identifier name, TypeArgumentList arguments) {
|
| - if (name != null) {
|
| - if (type == null || type.isUndefined) {
|
| - return serializeIdentifier(name);
|
| - }
|
| - }
|
| - DartType typeOrDynamic = type ?? DynamicTypeImpl.instance;
|
| - return serializer.serializeTypeRef(typeOrDynamic, context);
|
| - }
|
| -
|
| - /**
|
| - * Return `true` if the given [element] can be resolved at prelink step.
|
| - */
|
| - static bool _isPrelinkResolvableElement(Element element) {
|
| - if (element == null) {
|
| - return false;
|
| - }
|
| - if (element == DynamicTypeImpl.instance.element) {
|
| - return true;
|
| - }
|
| - if (element is PrefixElement) {
|
| - return true;
|
| - }
|
| - Element enclosingElement = element.enclosingElement;
|
| - if (enclosingElement is CompilationUnitElement) {
|
| - return true;
|
| - }
|
| - if (enclosingElement is ClassElement) {
|
| - return element is ConstructorElement ||
|
| - element is ClassMemberElement && element.isStatic ||
|
| - element is PropertyAccessorElement && element.isStatic;
|
| - }
|
| - return false;
|
| - }
|
| -}
|
| -
|
| -/**
|
| - * Instances of this class keep track of intermediate state during
|
| - * serialization of a single library.
|
| - */
|
| -class _LibrarySerializer {
|
| - /**
|
| - * The library to be serialized.
|
| - */
|
| - final LibraryElement libraryElement;
|
| -
|
| - /**
|
| - * The type provider. This is used to locate the library for `dart:core`.
|
| - */
|
| - final TypeProvider typeProvider;
|
| -
|
| - /**
|
| - * Indicates whether the element model being serialized was analyzed using
|
| - * strong mode.
|
| - */
|
| - final bool strongMode;
|
| -
|
| - /**
|
| - * Map from [LibraryElement] to the index of the entry in the "dependency
|
| - * table" that refers to it.
|
| - */
|
| - final Map<LibraryElement, int> dependencyMap = <LibraryElement, int>{};
|
| -
|
| - /**
|
| - * The "dependency table". This is the list of objects which should be
|
| - * written to [LinkedLibrary.dependencies].
|
| - */
|
| - final List<LinkedDependencyBuilder> dependencies =
|
| - <LinkedDependencyBuilder>[];
|
| -
|
| - /**
|
| - * The linked portion of the "imports table". This is the list of ints
|
| - * which should be written to [LinkedLibrary.imports].
|
| - */
|
| - final List<int> linkedImports = <int>[];
|
| -
|
| - /**
|
| - * The linked portion of the "exports table". This is the list of ints
|
| - * which should be written to [LinkedLibrary.exports].
|
| - */
|
| - final List<int> linkedExports = <int>[];
|
| -
|
| - /**
|
| - * Set of libraries which have been seen so far while visiting the transitive
|
| - * closure of exports.
|
| - */
|
| - final Set<LibraryElement> librariesAddedToTransitiveExportClosure =
|
| - new Set<LibraryElement>();
|
| -
|
| - /**
|
| - * Map from imported element to the prefix which may be used to refer to that
|
| - * element; elements for which no prefix is needed are absent from this map.
|
| - */
|
| - final Map<Element, PrefixElement> prefixMap = <Element, PrefixElement>{};
|
| -
|
| - /**
|
| - * List of serializers for the compilation units constituting this library.
|
| - */
|
| - final List<_CompilationUnitSerializer> compilationUnitSerializers =
|
| - <_CompilationUnitSerializer>[];
|
| -
|
| - _LibrarySerializer(this.libraryElement, this.typeProvider, this.strongMode) {
|
| - dependencies.add(new LinkedDependencyBuilder());
|
| - dependencyMap[libraryElement] = 0;
|
| - }
|
| -
|
| - /**
|
| - * Retrieve a list of the Sources for the compilation units in the library.
|
| - */
|
| - List<Source> get unitSources => compilationUnitSerializers
|
| - .map((_CompilationUnitSerializer s) => s.unitSource)
|
| - .toList();
|
| -
|
| - /**
|
| - * Retrieve a list of the URIs for the compilation units in the library.
|
| - */
|
| - List<String> get unitUris => compilationUnitSerializers
|
| - .map((_CompilationUnitSerializer s) => s.unitUri)
|
| - .toList();
|
| -
|
| - /**
|
| - * Retrieve a list of the [UnlinkedUnitBuilder]s for the compilation units in
|
| - * the library.
|
| - */
|
| - List<UnlinkedUnitBuilder> get unlinkedUnits => compilationUnitSerializers
|
| - .map((_CompilationUnitSerializer s) => s.unlinkedUnit)
|
| - .toList();
|
| -
|
| - /**
|
| - * Add [exportedLibrary] (and the transitive closure of all libraries it
|
| - * exports) to the dependency table ([LinkedLibrary.dependencies]).
|
| - */
|
| - void addTransitiveExportClosure(LibraryElement exportedLibrary) {
|
| - if (librariesAddedToTransitiveExportClosure.add(exportedLibrary)) {
|
| - serializeDependency(exportedLibrary);
|
| - for (LibraryElement transitiveExport
|
| - in exportedLibrary.exportedLibraries) {
|
| - addTransitiveExportClosure(transitiveExport);
|
| - }
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Fill in [prefixMap] using information from [libraryElement.imports].
|
| - */
|
| - void computePrefixMap() {
|
| - for (ImportElement import in libraryElement.imports) {
|
| - if (import.prefix == null) {
|
| - continue;
|
| - }
|
| - import.importedLibrary.exportNamespace.definedNames
|
| - .forEach((String name, Element e) {
|
| - if (new NameFilter.forNamespaceCombinators(import.combinators)
|
| - .accepts(name)) {
|
| - prefixMap[e] = import.prefix;
|
| - }
|
| - });
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Return the index of the entry in the dependency table
|
| - * ([LinkedLibrary.dependencies]) for the given [dependentLibrary]. A new
|
| - * entry is added to the table if necessary to satisfy the request.
|
| - */
|
| - int serializeDependency(LibraryElement dependentLibrary) {
|
| - return dependencyMap.putIfAbsent(dependentLibrary, () {
|
| - int index = dependencies.length;
|
| - List<String> parts = dependentLibrary.parts
|
| - .map((CompilationUnitElement e) => e.source.uri.toString())
|
| - .toList();
|
| - dependencies.add(new LinkedDependencyBuilder(
|
| - uri: dependentLibrary.source.uri.toString(), parts: parts));
|
| - return index;
|
| - });
|
| - }
|
| -
|
| - /**
|
| - * Serialize the whole library element into a [LinkedLibrary]. Should be
|
| - * called exactly once for each instance of [_LibrarySerializer].
|
| - *
|
| - * The unlinked compilation units are stored in [unlinkedUnits], and their
|
| - * absolute URIs are stored in [unitUris].
|
| - */
|
| - LinkedLibraryBuilder serializeLibrary() {
|
| - computePrefixMap();
|
| - LinkedLibraryBuilder pb = new LinkedLibraryBuilder();
|
| - for (ExportElement exportElement in libraryElement.exports) {
|
| - addTransitiveExportClosure(exportElement.exportedLibrary);
|
| - linkedExports.add(serializeDependency(exportElement.exportedLibrary));
|
| - }
|
| - for (ImportElement importElement in libraryElement.imports) {
|
| - addTransitiveExportClosure(importElement.importedLibrary);
|
| - linkedImports.add(serializeDependency(importElement.importedLibrary));
|
| - }
|
| - compilationUnitSerializers.add(new _CompilationUnitSerializer(
|
| - this, libraryElement.definingCompilationUnit, 0));
|
| - for (int i = 0; i < libraryElement.parts.length; i++) {
|
| - compilationUnitSerializers.add(
|
| - new _CompilationUnitSerializer(this, libraryElement.parts[i], i + 1));
|
| - }
|
| - for (_CompilationUnitSerializer compilationUnitSerializer
|
| - in compilationUnitSerializers) {
|
| - compilationUnitSerializer.addCompilationUnitElements();
|
| - }
|
| - pb.units = compilationUnitSerializers
|
| - .map((_CompilationUnitSerializer s) => s.linkedUnit)
|
| - .toList();
|
| - pb.dependencies = dependencies;
|
| - pb.numPrelinkedDependencies = dependencies.length;
|
| - for (_CompilationUnitSerializer compilationUnitSerializer
|
| - in compilationUnitSerializers) {
|
| - compilationUnitSerializer.createLinkedInfo();
|
| - }
|
| - pb.importDependencies = linkedImports;
|
| - pb.exportDependencies = linkedExports;
|
| - List<String> exportedNames =
|
| - libraryElement.exportNamespace.definedNames.keys.toList();
|
| - exportedNames.sort();
|
| - List<LinkedExportNameBuilder> exportNames = <LinkedExportNameBuilder>[];
|
| - for (String name in exportedNames) {
|
| - if (libraryElement.publicNamespace.definedNames.containsKey(name)) {
|
| - continue;
|
| - }
|
| - Element element = libraryElement.exportNamespace.get(name);
|
| - LibraryElement dependentLibrary = element.library;
|
| - CompilationUnitElement unitElement =
|
| - element.getAncestor((Element e) => e is CompilationUnitElement);
|
| - int unit = dependentLibrary.units.indexOf(unitElement);
|
| - assert(unit != -1);
|
| - ReferenceKind kind = _getReferenceKind(element);
|
| - exportNames.add(new LinkedExportNameBuilder(
|
| - name: name,
|
| - dependency: serializeDependency(dependentLibrary),
|
| - unit: unit,
|
| - kind: kind));
|
| - }
|
| - pb.exportNames = exportNames;
|
| - return pb;
|
| - }
|
| -}
|
|
|