| Index: pkg/analyzer/lib/src/summary/index_unit.dart
|
| diff --git a/pkg/analyzer/lib/src/summary/index_unit.dart b/pkg/analyzer/lib/src/summary/index_unit.dart
|
| index bc09ee345e6d6729afd049f7d1e51ac9e337d4c2..c1bbae530e9b5549611a956d616053fd21b2a403 100644
|
| --- a/pkg/analyzer/lib/src/summary/index_unit.dart
|
| +++ b/pkg/analyzer/lib/src/summary/index_unit.dart
|
| @@ -13,46 +13,78 @@ import 'package:analyzer/src/summary/format.dart';
|
| import 'package:analyzer/src/summary/idl.dart';
|
|
|
| /**
|
| - * Information about an element referenced in index.
|
| + * Information about an element that is actually put into index for some other
|
| + * related element. For example for a synthetic getter this is the corresponding
|
| + * non-synthetic field and [IndexSyntheticElementKind.getter] as the [kind].
|
| */
|
| -class ElementInfo {
|
| - /**
|
| - * The identifier of the [CompilationUnitElement] containing this element.
|
| - */
|
| - final int unitId;
|
| -
|
| - /**
|
| - * The name offset of the element.
|
| - */
|
| - final int offset;
|
| -
|
| - /**
|
| - * The kind of the element.
|
| - */
|
| +class IndexElementInfo {
|
| + final Element element;
|
| final IndexSyntheticElementKind kind;
|
|
|
| - /**
|
| - * The unique id of the element. It is set after indexing of the whole
|
| - * package is done and we are assembling the full package index.
|
| - */
|
| - int id;
|
| -
|
| - ElementInfo(this.unitId, this.offset, this.kind) {
|
| - assert(offset >= 0);
|
| + factory IndexElementInfo(Element element) {
|
| + IndexSyntheticElementKind kind = IndexSyntheticElementKind.notSynthetic;
|
| + if (element.isSynthetic) {
|
| + if (element is ConstructorElement) {
|
| + kind = IndexSyntheticElementKind.constructor;
|
| + element = element.enclosingElement;
|
| + } else if (element is FunctionElement && element.name == 'loadLibrary') {
|
| + kind = IndexSyntheticElementKind.loadLibrary;
|
| + element = element.library;
|
| + } else if (element is FieldElement) {
|
| + FieldElement field = element;
|
| + kind = IndexSyntheticElementKind.field;
|
| + element = field.getter;
|
| + element ??= field.setter;
|
| + } else if (element is PropertyAccessorElement) {
|
| + PropertyAccessorElement accessor = element;
|
| + Element enclosing = element.enclosingElement;
|
| + bool isEnumGetter = enclosing is ClassElement && enclosing.isEnum;
|
| + if (isEnumGetter && accessor.name == 'index') {
|
| + kind = IndexSyntheticElementKind.enumIndex;
|
| + element = enclosing;
|
| + } else if (isEnumGetter && accessor.name == 'values') {
|
| + kind = IndexSyntheticElementKind.enumValues;
|
| + element = enclosing;
|
| + } else {
|
| + kind = accessor.isGetter
|
| + ? IndexSyntheticElementKind.getter
|
| + : IndexSyntheticElementKind.setter;
|
| + element = accessor.variable;
|
| + }
|
| + } else if (element is TopLevelVariableElement) {
|
| + TopLevelVariableElement property = element;
|
| + kind = IndexSyntheticElementKind.topLevelVariable;
|
| + element = property.getter;
|
| + element ??= property.setter;
|
| + } else {
|
| + throw new ArgumentError(
|
| + 'Unsupported synthetic element ${element.runtimeType}');
|
| + }
|
| + } else if (element is LibraryElement || element is CompilationUnitElement) {
|
| + kind = IndexSyntheticElementKind.unit;
|
| + }
|
| + return new IndexElementInfo._(element, kind);
|
| }
|
| +
|
| + IndexElementInfo._(this.element, this.kind);
|
| }
|
|
|
| /**
|
| * Object that gathers information about the whole package index and then uses
|
| - * it to assemble a new [PackageIndexBuilder]. Call [index] on each compilation
|
| - * unit to be indexed, then call [assemble] to retrieve the complete index for
|
| - * the package.
|
| + * it to assemble a new [PackageIndexBuilder]. Call [indexUnit] on each
|
| + * compilation unit to be indexed, then call [assemble] to retrieve the
|
| + * complete index for the package.
|
| */
|
| class PackageIndexAssembler {
|
| /**
|
| - * Map associating referenced elements with their [ElementInfo]s.
|
| + * The string to use place of the `null` string.
|
| + */
|
| + static const NULL_STRING = '--nullString--';
|
| +
|
| + /**
|
| + * Map associating referenced elements with their [_ElementInfo]s.
|
| */
|
| - final Map<Element, ElementInfo> _elementMap = <Element, ElementInfo>{};
|
| + final Map<Element, _ElementInfo> _elementMap = <Element, _ElementInfo>{};
|
|
|
| /**
|
| * Map associating [CompilationUnitElement]s with their identifiers, which
|
| @@ -84,6 +116,15 @@ class PackageIndexAssembler {
|
| final List<_UnitIndexAssembler> _units = <_UnitIndexAssembler>[];
|
|
|
| /**
|
| + * The [_StringInfo] to use for `null` strings.
|
| + */
|
| + _StringInfo _nullString;
|
| +
|
| + PackageIndexAssembler() {
|
| + _nullString = _getStringInfo(NULL_STRING);
|
| + }
|
| +
|
| + /**
|
| * Assemble a new [PackageIndexBuilder] using the information gathered by
|
| * [indexDeclarations] or [indexUnit].
|
| */
|
| @@ -97,9 +138,18 @@ class PackageIndexAssembler {
|
| stringInfoList[i].id = i;
|
| }
|
| // sort elements and set IDs
|
| - List<ElementInfo> elementInfoList = _elementMap.values.toList();
|
| + List<_ElementInfo> elementInfoList = _elementMap.values.toList();
|
| elementInfoList.sort((a, b) {
|
| - return a.offset - b.offset;
|
| + int delta;
|
| + delta = a.nameIdUnitMember.id - b.nameIdUnitMember.id;
|
| + if (delta != null) {
|
| + return delta;
|
| + }
|
| + delta = a.nameIdClassMember.id - b.nameIdClassMember.id;
|
| + if (delta != null) {
|
| + return delta;
|
| + }
|
| + return a.nameIdParameter.id - b.nameIdParameter.id;
|
| });
|
| for (int i = 0; i < elementInfoList.length; i++) {
|
| elementInfoList[i].id = i;
|
| @@ -108,7 +158,12 @@ class PackageIndexAssembler {
|
| unitLibraryUris: _unitLibraryUris.map((s) => s.id).toList(),
|
| unitUnitUris: _unitUnitUris.map((s) => s.id).toList(),
|
| elementUnits: elementInfoList.map((e) => e.unitId).toList(),
|
| - elementOffsets: elementInfoList.map((e) => e.offset).toList(),
|
| + elementNameUnitMemberIds:
|
| + elementInfoList.map((e) => e.nameIdUnitMember.id).toList(),
|
| + elementNameClassMemberIds:
|
| + elementInfoList.map((e) => e.nameIdClassMember.id).toList(),
|
| + elementNameParameterIds:
|
| + elementInfoList.map((e) => e.nameIdParameter.id).toList(),
|
| elementKinds: elementInfoList.map((e) => e.kind).toList(),
|
| strings: stringInfoList.map((s) => s.value).toList(),
|
| units: _units.map((unit) => unit.assemble()).toList());
|
| @@ -135,17 +190,17 @@ class PackageIndexAssembler {
|
| }
|
|
|
| /**
|
| - * Return the unique [ElementInfo] corresponding the [element]. The field
|
| - * [ElementInfo.id] is filled by [assemble] during final sorting.
|
| + * Return the unique [_ElementInfo] corresponding the [element]. The field
|
| + * [_ElementInfo.id] is filled by [assemble] during final sorting.
|
| */
|
| - ElementInfo _getElementInfo(Element element) {
|
| + _ElementInfo _getElementInfo(Element element) {
|
| if (element is Member) {
|
| element = (element as Member).baseElement;
|
| }
|
| return _elementMap.putIfAbsent(element, () {
|
| CompilationUnitElement unitElement = getUnitElement(element);
|
| int unitId = _getUnitId(unitElement);
|
| - return newElementInfo(unitId, element);
|
| + return _newElementInfo(unitId, element);
|
| });
|
| }
|
|
|
| @@ -184,6 +239,32 @@ class PackageIndexAssembler {
|
| }
|
|
|
| /**
|
| + * Return a new [_ElementInfo] for the given [element] in the given [unitId].
|
| + * This method is static, so it cannot add any information to the index.
|
| + */
|
| + _ElementInfo _newElementInfo(int unitId, Element element) {
|
| + IndexElementInfo info = new IndexElementInfo(element);
|
| + element = info.element;
|
| + // Prepare name identifiers.
|
| + _StringInfo nameIdParameter = _nullString;
|
| + _StringInfo nameIdClassMember = _nullString;
|
| + _StringInfo nameIdUnitMember = _nullString;
|
| + if (element is ParameterElement) {
|
| + nameIdParameter = _getStringInfo(element.name);
|
| + element = element.enclosingElement;
|
| + }
|
| + if (element?.enclosingElement is ClassElement) {
|
| + nameIdClassMember = _getStringInfo(element.name);
|
| + element = element.enclosingElement;
|
| + }
|
| + if (element?.enclosingElement is CompilationUnitElement) {
|
| + nameIdUnitMember = _getStringInfo(element.name);
|
| + }
|
| + return new _ElementInfo(unitId, nameIdUnitMember, nameIdClassMember,
|
| + nameIdParameter, info.kind);
|
| + }
|
| +
|
| + /**
|
| * Return the [CompilationUnitElement] that should be used for [element].
|
| * Throw [StateError] if the [element] is not linked into a unit.
|
| */
|
| @@ -198,58 +279,6 @@ class PackageIndexAssembler {
|
| }
|
| throw new StateError(element.toString());
|
| }
|
| -
|
| - /**
|
| - * Return a new [ElementInfo] for the given [element] in the given [unitId].
|
| - * This method is static, so it cannot add any information to the index.
|
| - */
|
| - static ElementInfo newElementInfo(int unitId, Element element) {
|
| - int offset = null;
|
| - IndexSyntheticElementKind kind = IndexSyntheticElementKind.notSynthetic;
|
| - if (element.isSynthetic) {
|
| - if (element is ConstructorElement) {
|
| - kind = IndexSyntheticElementKind.constructor;
|
| - element = element.enclosingElement;
|
| - } else if (element is FunctionElement && element.name == 'loadLibrary') {
|
| - kind = IndexSyntheticElementKind.loadLibrary;
|
| - element = element.library;
|
| - } else if (element is FieldElement) {
|
| - FieldElement field = element;
|
| - kind = IndexSyntheticElementKind.field;
|
| - element = field.getter;
|
| - element ??= field.setter;
|
| - } else if (element is PropertyAccessorElement) {
|
| - PropertyAccessorElement accessor = element;
|
| - Element enclosing = element.enclosingElement;
|
| - bool isEnumGetter = enclosing is ClassElement && enclosing.isEnum;
|
| - if (isEnumGetter && accessor.name == 'index') {
|
| - kind = IndexSyntheticElementKind.enumIndex;
|
| - element = enclosing;
|
| - } else if (isEnumGetter && accessor.name == 'values') {
|
| - kind = IndexSyntheticElementKind.enumValues;
|
| - element = enclosing;
|
| - } else {
|
| - kind = accessor.isGetter
|
| - ? IndexSyntheticElementKind.getter
|
| - : IndexSyntheticElementKind.setter;
|
| - element = accessor.variable;
|
| - }
|
| - } else if (element is TopLevelVariableElement) {
|
| - TopLevelVariableElement property = element;
|
| - kind = IndexSyntheticElementKind.topLevelVariable;
|
| - element = property.getter;
|
| - element ??= property.setter;
|
| - } else {
|
| - throw new ArgumentError(
|
| - 'Unsupported synthetic element ${element.runtimeType}');
|
| - }
|
| - } else if (element is LibraryElement || element is CompilationUnitElement) {
|
| - kind = IndexSyntheticElementKind.unit;
|
| - offset = 0;
|
| - }
|
| - offset ??= element.nameOffset;
|
| - return new ElementInfo(unitId, offset, kind);
|
| - }
|
| }
|
|
|
| /**
|
| @@ -278,13 +307,55 @@ class _DefinedNameInfo {
|
| }
|
|
|
| /**
|
| + * Information about an element referenced in index.
|
| + */
|
| +class _ElementInfo {
|
| + /**
|
| + * The identifier of the [CompilationUnitElement] containing this element.
|
| + */
|
| + final int unitId;
|
| +
|
| + /**
|
| + * The identifier of the top-level name, or `null` if the element is a
|
| + * reference to the unit.
|
| + */
|
| + final _StringInfo nameIdUnitMember;
|
| +
|
| + /**
|
| + * The identifier of the class member name, or `null` if the element is not a
|
| + * class member or a named parameter of a class member.
|
| + */
|
| + final _StringInfo nameIdClassMember;
|
| +
|
| + /**
|
| + * The identifier of the named parameter name, or `null` if the element is not
|
| + * a named parameter.
|
| + */
|
| + final _StringInfo nameIdParameter;
|
| +
|
| + /**
|
| + * The kind of the element.
|
| + */
|
| + final IndexSyntheticElementKind kind;
|
| +
|
| + /**
|
| + * The unique id of the element. It is set after indexing of the whole
|
| + * package is done and we are assembling the full package index.
|
| + */
|
| + int id;
|
| +
|
| + _ElementInfo(this.unitId, this.nameIdUnitMember, this.nameIdClassMember,
|
| + this.nameIdParameter, this.kind);
|
| +}
|
| +
|
| +/**
|
| * Information about a single relation. Any [_ElementRelationInfo] is always
|
| * part of a [_UnitIndexAssembler], so [offset] and [length] should be
|
| * understood within the context of the compilation unit pointed to by the
|
| * [_UnitIndexAssembler].
|
| */
|
| class _ElementRelationInfo {
|
| - final ElementInfo elementInfo;
|
| + final _ElementInfo elementInfo;
|
| final IndexRelationKind kind;
|
| final int offset;
|
| final int length;
|
| @@ -770,7 +841,7 @@ class _StringInfo {
|
| * compilation unit.
|
| * - Call [addNameRelation] for each name relation found in the
|
| * compilation unit.
|
| - * - Assign ids to all the [ElementInfo] objects reachable from
|
| + * - Assign ids to all the [_ElementInfo] objects reachable from
|
| * [elementRelations].
|
| * - Call [assemble] to produce the final unit index.
|
| */
|
| @@ -786,7 +857,7 @@ class _UnitIndexAssembler {
|
| void addElementRelation(Element element, IndexRelationKind kind, int offset,
|
| int length, bool isQualified) {
|
| try {
|
| - ElementInfo elementInfo = pkg._getElementInfo(element);
|
| + _ElementInfo elementInfo = pkg._getElementInfo(element);
|
| elementRelations.add(new _ElementRelationInfo(
|
| elementInfo, kind, offset, length, isQualified));
|
| } on StateError {}
|
|
|