| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 import 'package:analyzer/dart/ast/ast.dart'; | 5 import 'package:analyzer/dart/ast/ast.dart'; |
| 6 import 'package:analyzer/dart/ast/token.dart'; | 6 import 'package:analyzer/dart/ast/token.dart'; |
| 7 import 'package:analyzer/dart/ast/visitor.dart'; | 7 import 'package:analyzer/dart/ast/visitor.dart'; |
| 8 import 'package:analyzer/dart/element/element.dart'; | 8 import 'package:analyzer/dart/element/element.dart'; |
| 9 import 'package:analyzer/dart/element/type.dart'; | 9 import 'package:analyzer/dart/element/type.dart'; |
| 10 import 'package:analyzer/src/dart/element/member.dart'; | 10 import 'package:analyzer/src/dart/element/member.dart'; |
| 11 import 'package:analyzer/src/generated/utilities_dart.dart'; | 11 import 'package:analyzer/src/generated/utilities_dart.dart'; |
| 12 import 'package:analyzer/src/summary/format.dart'; | 12 import 'package:analyzer/src/summary/format.dart'; |
| 13 import 'package:analyzer/src/summary/idl.dart'; | 13 import 'package:analyzer/src/summary/idl.dart'; |
| 14 | 14 |
| 15 /** | 15 /** |
| 16 * TODO(scheglov) add to the `meta` package. |
| 17 */ |
| 18 const visibleForTesting = const Object(); |
| 19 |
| 20 /** |
| 21 * Information about an element referenced in index. |
| 22 */ |
| 23 class ElementInfo { |
| 24 /** |
| 25 * The identifier of the [CompilationUnitElement] containing this element. |
| 26 */ |
| 27 final int unitId; |
| 28 |
| 29 /** |
| 30 * The name offset of the element. |
| 31 */ |
| 32 final int offset; |
| 33 |
| 34 /** |
| 35 * The kind of the element. |
| 36 */ |
| 37 final IndexSyntheticElementKind kind; |
| 38 |
| 39 /** |
| 40 * The unique id of the element. It is set after indexing of the whole |
| 41 * package is done and we are assembling the full package index. |
| 42 */ |
| 43 int id; |
| 44 |
| 45 ElementInfo(this.unitId, this.offset, this.kind) { |
| 46 assert(offset >= 0); |
| 47 } |
| 48 } |
| 49 |
| 50 /** |
| 16 * Object that gathers information about the whole package index and then uses | 51 * Object that gathers information about the whole package index and then uses |
| 17 * it to assemble a new [PackageIndexBuilder]. Call [index] on each compilation | 52 * it to assemble a new [PackageIndexBuilder]. Call [index] on each compilation |
| 18 * unit to be indexed, then call [assemble] to retrieve the complete index for | 53 * unit to be indexed, then call [assemble] to retrieve the complete index for |
| 19 * the package. | 54 * the package. |
| 20 */ | 55 */ |
| 21 class PackageIndexAssembler { | 56 class PackageIndexAssembler { |
| 22 /** | 57 /** |
| 23 * Map associating referenced elements with their [_ElementInfo]s. | 58 * Map associating referenced elements with their [ElementInfo]s. |
| 24 */ | 59 */ |
| 25 final Map<Element, _ElementInfo> _elementMap = <Element, _ElementInfo>{}; | 60 final Map<Element, ElementInfo> _elementMap = <Element, ElementInfo>{}; |
| 26 | 61 |
| 27 /** | 62 /** |
| 28 * Map associating [CompilationUnitElement]s with their identifiers, which | 63 * Map associating [CompilationUnitElement]s with their identifiers, which |
| 29 * are indices into [_unitLibraryUris] and [_unitUnitUris]. | 64 * are indices into [_unitLibraryUris] and [_unitUnitUris]. |
| 30 */ | 65 */ |
| 31 final Map<CompilationUnitElement, int> _unitMap = | 66 final Map<CompilationUnitElement, int> _unitMap = |
| 32 <CompilationUnitElement, int>{}; | 67 <CompilationUnitElement, int>{}; |
| 33 | 68 |
| 34 /** | 69 /** |
| 35 * Each item of this list corresponds to the library URI of a unique | 70 * Each item of this list corresponds to the library URI of a unique |
| (...skipping 24 matching lines...) Expand all Loading... |
| 60 PackageIndexBuilder assemble() { | 95 PackageIndexBuilder assemble() { |
| 61 // sort strings end set IDs | 96 // sort strings end set IDs |
| 62 List<_StringInfo> stringInfoList = _stringMap.values.toList(); | 97 List<_StringInfo> stringInfoList = _stringMap.values.toList(); |
| 63 stringInfoList.sort((a, b) { | 98 stringInfoList.sort((a, b) { |
| 64 return a.value.compareTo(b.value); | 99 return a.value.compareTo(b.value); |
| 65 }); | 100 }); |
| 66 for (int i = 0; i < stringInfoList.length; i++) { | 101 for (int i = 0; i < stringInfoList.length; i++) { |
| 67 stringInfoList[i].id = i; | 102 stringInfoList[i].id = i; |
| 68 } | 103 } |
| 69 // sort elements and set IDs | 104 // sort elements and set IDs |
| 70 List<_ElementInfo> elementInfoList = _elementMap.values.toList(); | 105 List<ElementInfo> elementInfoList = _elementMap.values.toList(); |
| 71 elementInfoList.sort((a, b) { | 106 elementInfoList.sort((a, b) { |
| 72 return a.offset - b.offset; | 107 return a.offset - b.offset; |
| 73 }); | 108 }); |
| 74 for (int i = 0; i < elementInfoList.length; i++) { | 109 for (int i = 0; i < elementInfoList.length; i++) { |
| 75 elementInfoList[i].id = i; | 110 elementInfoList[i].id = i; |
| 76 } | 111 } |
| 77 return new PackageIndexBuilder( | 112 return new PackageIndexBuilder( |
| 78 unitLibraryUris: _unitLibraryUris.map((s) => s.id).toList(), | 113 unitLibraryUris: _unitLibraryUris.map((s) => s.id).toList(), |
| 79 unitUnitUris: _unitUnitUris.map((s) => s.id).toList(), | 114 unitUnitUris: _unitUnitUris.map((s) => s.id).toList(), |
| 80 elementUnits: elementInfoList.map((e) => e.unitId).toList(), | 115 elementUnits: elementInfoList.map((e) => e.unitId).toList(), |
| 81 elementOffsets: elementInfoList.map((e) => e.offset).toList(), | 116 elementOffsets: elementInfoList.map((e) => e.offset).toList(), |
| 82 elementKinds: elementInfoList.map((e) => e.kind).toList(), | 117 elementKinds: elementInfoList.map((e) => e.kind).toList(), |
| 83 strings: stringInfoList.map((s) => s.value).toList(), | 118 strings: stringInfoList.map((s) => s.value).toList(), |
| 84 units: _units.map((unit) => unit.assemble()).toList()); | 119 units: _units.map((unit) => unit.assemble()).toList()); |
| 85 } | 120 } |
| 86 | 121 |
| 87 /** | 122 /** |
| 88 * Index the given fully resolved [unit]. | 123 * Index the given fully resolved [unit]. |
| 89 */ | 124 */ |
| 90 void index(CompilationUnit unit) { | 125 void index(CompilationUnit unit) { |
| 91 int unitId = _getUnitId(unit.element); | 126 int unitId = _getUnitId(unit.element); |
| 92 _UnitIndexAssembler assembler = new _UnitIndexAssembler(this, unitId); | 127 _UnitIndexAssembler assembler = new _UnitIndexAssembler(this, unitId); |
| 93 _units.add(assembler); | 128 _units.add(assembler); |
| 94 unit.accept(new _IndexContributor(assembler)); | 129 unit.accept(new _IndexContributor(assembler)); |
| 95 } | 130 } |
| 96 | 131 |
| 97 /** | 132 /** |
| 98 * Return the unique [_ElementInfo] corresponding the [element]. The field | 133 * Return the unique [ElementInfo] corresponding the [element]. The field |
| 99 * [_ElementInfo.id] is filled by [assemble] during final sorting. | 134 * [ElementInfo.id] is filled by [assemble] during final sorting. |
| 100 */ | 135 */ |
| 101 _ElementInfo _getElementInfo(Element element) { | 136 ElementInfo _getElementInfo(Element element) { |
| 102 if (element is Member) { | 137 if (element is Member) { |
| 103 element = (element as Member).baseElement; | 138 element = (element as Member).baseElement; |
| 104 } | 139 } |
| 105 return _elementMap.putIfAbsent(element, () { | 140 return _elementMap.putIfAbsent(element, () { |
| 106 CompilationUnitElement unitElement = getUnitElement(element); | 141 CompilationUnitElement unitElement = getUnitElement(element); |
| 107 int unitId = _getUnitId(unitElement); | 142 int unitId = _getUnitId(unitElement); |
| 108 int offset = element.nameOffset; | 143 return newElementInfo(unitId, element); |
| 109 if (element is LibraryElement || element is CompilationUnitElement) { | |
| 110 offset = 0; | |
| 111 } | |
| 112 IndexSyntheticElementKind kind = getIndexElementKind(element); | |
| 113 return new _ElementInfo(unitId, offset, kind); | |
| 114 }); | 144 }); |
| 115 } | 145 } |
| 116 | 146 |
| 117 /** | 147 /** |
| 118 * Return the unique [_StringInfo] corresponding the [str]. The field | 148 * Return the unique [_StringInfo] corresponding the [str]. The field |
| 119 * [_StringInfo.id] is filled by [assemble] during final sorting. | 149 * [_StringInfo.id] is filled by [assemble] during final sorting. |
| 120 */ | 150 */ |
| 121 _StringInfo _getStringInfo(String str) { | 151 _StringInfo _getStringInfo(String str) { |
| 122 return _stringMap.putIfAbsent(str, () { | 152 return _stringMap.putIfAbsent(str, () { |
| 123 return new _StringInfo(str); | 153 return new _StringInfo(str); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 142 /** | 172 /** |
| 143 * Return the unique [_StringInfo] corresponding [uri]. The field | 173 * Return the unique [_StringInfo] corresponding [uri]. The field |
| 144 * [_StringInfo.id] is filled by [assemble] during final sorting. | 174 * [_StringInfo.id] is filled by [assemble] during final sorting. |
| 145 */ | 175 */ |
| 146 _StringInfo _getUriInfo(Uri uri) { | 176 _StringInfo _getUriInfo(Uri uri) { |
| 147 String str = uri.toString(); | 177 String str = uri.toString(); |
| 148 return _getStringInfo(str); | 178 return _getStringInfo(str); |
| 149 } | 179 } |
| 150 | 180 |
| 151 /** | 181 /** |
| 152 * Return the kind of the given [element]. | |
| 153 */ | |
| 154 static IndexSyntheticElementKind getIndexElementKind(Element element) { | |
| 155 if (element.isSynthetic) { | |
| 156 if (element is ConstructorElement) { | |
| 157 return IndexSyntheticElementKind.constructor; | |
| 158 } | |
| 159 if (element is PropertyAccessorElement) { | |
| 160 return element.isGetter | |
| 161 ? IndexSyntheticElementKind.getter | |
| 162 : IndexSyntheticElementKind.setter; | |
| 163 } | |
| 164 } | |
| 165 return IndexSyntheticElementKind.notSynthetic; | |
| 166 } | |
| 167 | |
| 168 /** | |
| 169 * Return the [CompilationUnitElement] that should be used for [element]. | 182 * Return the [CompilationUnitElement] that should be used for [element]. |
| 170 * Throw [StateError] if the [element] is not linked into a unit. | 183 * Throw [StateError] if the [element] is not linked into a unit. |
| 171 */ | 184 */ |
| 172 static CompilationUnitElement getUnitElement(Element element) { | 185 static CompilationUnitElement getUnitElement(Element element) { |
| 173 for (Element e = element; e != null; e = e.enclosingElement) { | 186 for (Element e = element; e != null; e = e.enclosingElement) { |
| 174 if (e is CompilationUnitElement) { | 187 if (e is CompilationUnitElement) { |
| 175 return e; | 188 return e; |
| 176 } | 189 } |
| 177 if (e is LibraryElement) { | 190 if (e is LibraryElement) { |
| 178 return e.definingCompilationUnit; | 191 return e.definingCompilationUnit; |
| 179 } | 192 } |
| 180 } | 193 } |
| 181 throw new StateError(element.toString()); | 194 throw new StateError(element.toString()); |
| 182 } | 195 } |
| 196 |
| 197 /** |
| 198 * Return a new [ElementInfo] for the given [element] in the given [unitId]. |
| 199 * This method is static, so it cannot add any information to the index. |
| 200 */ |
| 201 static ElementInfo newElementInfo(int unitId, Element element) { |
| 202 IndexSyntheticElementKind kind = IndexSyntheticElementKind.notSynthetic; |
| 203 if (element.isSynthetic) { |
| 204 if (element is ConstructorElement) { |
| 205 kind = IndexSyntheticElementKind.constructor; |
| 206 element = element.enclosingElement; |
| 207 } else if (element is PropertyAccessorElement) { |
| 208 PropertyAccessorElement property = element; |
| 209 kind = property.isGetter |
| 210 ? IndexSyntheticElementKind.getter |
| 211 : IndexSyntheticElementKind.setter; |
| 212 element = element.enclosingElement; |
| 213 } else { |
| 214 throw new ArgumentError( |
| 215 'Unsupported synthetic element ${element.runtimeType}'); |
| 216 } |
| 217 } |
| 218 int offset = element.nameOffset; |
| 219 if (element is LibraryElement || element is CompilationUnitElement) { |
| 220 offset = 0; |
| 221 } |
| 222 return new ElementInfo(unitId, offset, kind); |
| 223 } |
| 183 } | 224 } |
| 184 | 225 |
| 185 /** | 226 /** |
| 186 * Information about a single defined name. Any [_DefinedNameInfo] is always | 227 * Information about a single defined name. Any [_DefinedNameInfo] is always |
| 187 * part of a [_UnitIndexAssembler], so [offset] should be understood within the | 228 * part of a [_UnitIndexAssembler], so [offset] should be understood within the |
| 188 * context of the compilation unit pointed to by the [_UnitIndexAssembler]. | 229 * context of the compilation unit pointed to by the [_UnitIndexAssembler]. |
| 189 */ | 230 */ |
| 190 class _DefinedNameInfo { | 231 class _DefinedNameInfo { |
| 191 /** | 232 /** |
| 192 * The information about the name returned from | 233 * The information about the name returned from |
| 193 * [PackageIndexAssembler._getStringInfo]. | 234 * [PackageIndexAssembler._getStringInfo]. |
| 194 */ | 235 */ |
| 195 final _StringInfo nameInfo; | 236 final _StringInfo nameInfo; |
| 196 | 237 |
| 197 /** | 238 /** |
| 198 * The coarse-grained kind of the defined name. | 239 * The coarse-grained kind of the defined name. |
| 199 */ | 240 */ |
| 200 final IndexNameKind kind; | 241 final IndexNameKind kind; |
| 201 | 242 |
| 202 /** | 243 /** |
| 203 * The name offset of the defined element. | 244 * The name offset of the defined element. |
| 204 */ | 245 */ |
| 205 final int offset; | 246 final int offset; |
| 206 | 247 |
| 207 _DefinedNameInfo(this.nameInfo, this.kind, this.offset); | 248 _DefinedNameInfo(this.nameInfo, this.kind, this.offset); |
| 208 } | 249 } |
| 209 | 250 |
| 210 /** | 251 /** |
| 211 * Information about an element referenced in index. | |
| 212 */ | |
| 213 class _ElementInfo { | |
| 214 /** | |
| 215 * The identifier of the [CompilationUnitElement] containing this element. | |
| 216 */ | |
| 217 final int unitId; | |
| 218 | |
| 219 /** | |
| 220 * The name offset of the element. | |
| 221 */ | |
| 222 final int offset; | |
| 223 | |
| 224 /** | |
| 225 * The kind of the element. | |
| 226 */ | |
| 227 final IndexSyntheticElementKind kind; | |
| 228 | |
| 229 /** | |
| 230 * The unique id of the element. It is set after indexing of the whole | |
| 231 * package is done and we are assembling the full package index. | |
| 232 */ | |
| 233 int id; | |
| 234 | |
| 235 _ElementInfo(this.unitId, this.offset, this.kind); | |
| 236 } | |
| 237 | |
| 238 /** | |
| 239 * Information about a string referenced in the index. | |
| 240 */ | |
| 241 class _StringInfo { | |
| 242 /** | |
| 243 * The value of the string. | |
| 244 */ | |
| 245 final String value; | |
| 246 | |
| 247 /** | |
| 248 * The unique id of the string. It is set after indexing of the whole | |
| 249 * package is done and we are assembling the full package index. | |
| 250 */ | |
| 251 int id; | |
| 252 | |
| 253 _StringInfo(this.value); | |
| 254 } | |
| 255 | |
| 256 /** | |
| 257 * Information about a single relation. Any [_ElementRelationInfo] is always | 252 * Information about a single relation. Any [_ElementRelationInfo] is always |
| 258 * part of a [_UnitIndexAssembler], so [offset] and [length] should be | 253 * part of a [_UnitIndexAssembler], so [offset] and [length] should be |
| 259 * understood within the context of the compilation unit pointed to by the | 254 * understood within the context of the compilation unit pointed to by the |
| 260 * [_UnitIndexAssembler]. | 255 * [_UnitIndexAssembler]. |
| 261 */ | 256 */ |
| 262 class _ElementRelationInfo { | 257 class _ElementRelationInfo { |
| 263 final _ElementInfo elementInfo; | 258 final ElementInfo elementInfo; |
| 264 final IndexRelationKind kind; | 259 final IndexRelationKind kind; |
| 265 final int offset; | 260 final int offset; |
| 266 final int length; | 261 final int length; |
| 267 final bool isQualified; | 262 final bool isQualified; |
| 268 | 263 |
| 269 _ElementRelationInfo( | 264 _ElementRelationInfo( |
| 270 this.elementInfo, this.kind, this.offset, this.length, this.isQualified); | 265 this.elementInfo, this.kind, this.offset, this.length, this.isQualified); |
| 271 } | 266 } |
| 272 | 267 |
| 273 /** | 268 /** |
| (...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 674 * [PackageIndexAssembler._getStringInfo]. | 669 * [PackageIndexAssembler._getStringInfo]. |
| 675 */ | 670 */ |
| 676 final _StringInfo nameInfo; | 671 final _StringInfo nameInfo; |
| 677 final IndexRelationKind kind; | 672 final IndexRelationKind kind; |
| 678 final int offset; | 673 final int offset; |
| 679 | 674 |
| 680 _NameRelationInfo(this.nameInfo, this.kind, this.offset); | 675 _NameRelationInfo(this.nameInfo, this.kind, this.offset); |
| 681 } | 676 } |
| 682 | 677 |
| 683 /** | 678 /** |
| 679 * Information about a string referenced in the index. |
| 680 */ |
| 681 class _StringInfo { |
| 682 /** |
| 683 * The value of the string. |
| 684 */ |
| 685 final String value; |
| 686 |
| 687 /** |
| 688 * The unique id of the string. It is set after indexing of the whole |
| 689 * package is done and we are assembling the full package index. |
| 690 */ |
| 691 int id; |
| 692 |
| 693 _StringInfo(this.value); |
| 694 } |
| 695 |
| 696 /** |
| 684 * Assembler of a single [CompilationUnit] index. The intended usage sequence: | 697 * Assembler of a single [CompilationUnit] index. The intended usage sequence: |
| 685 * | 698 * |
| 686 * - Call [defineName] for each name defined in the compilation unit. | 699 * - Call [defineName] for each name defined in the compilation unit. |
| 687 * - Call [addElementRelation] for each element relation found in the | 700 * - Call [addElementRelation] for each element relation found in the |
| 688 * compilation unit. | 701 * compilation unit. |
| 689 * - Call [addNameRelation] for each name relation found in the | 702 * - Call [addNameRelation] for each name relation found in the |
| 690 * compilation unit. | 703 * compilation unit. |
| 691 * - Assign ids to all the [_ElementInfo] objects reachable from | 704 * - Assign ids to all the [ElementInfo] objects reachable from |
| 692 * [elementRelations]. | 705 * [elementRelations]. |
| 693 * - Call [assemble] to produce the final unit index. | 706 * - Call [assemble] to produce the final unit index. |
| 694 */ | 707 */ |
| 695 class _UnitIndexAssembler { | 708 class _UnitIndexAssembler { |
| 696 final PackageIndexAssembler pkg; | 709 final PackageIndexAssembler pkg; |
| 697 final int unitId; | 710 final int unitId; |
| 698 final List<_DefinedNameInfo> definedNames = <_DefinedNameInfo>[]; | 711 final List<_DefinedNameInfo> definedNames = <_DefinedNameInfo>[]; |
| 699 final List<_ElementRelationInfo> elementRelations = <_ElementRelationInfo>[]; | 712 final List<_ElementRelationInfo> elementRelations = <_ElementRelationInfo>[]; |
| 700 final List<_NameRelationInfo> nameRelations = <_NameRelationInfo>[]; | 713 final List<_NameRelationInfo> nameRelations = <_NameRelationInfo>[]; |
| 701 | 714 |
| 702 _UnitIndexAssembler(this.pkg, this.unitId); | 715 _UnitIndexAssembler(this.pkg, this.unitId); |
| 703 | 716 |
| 704 void addElementRelation(Element element, IndexRelationKind kind, int offset, | 717 void addElementRelation(Element element, IndexRelationKind kind, int offset, |
| 705 int length, bool isQualified) { | 718 int length, bool isQualified) { |
| 706 try { | 719 try { |
| 707 _ElementInfo elementInfo = pkg._getElementInfo(element); | 720 ElementInfo elementInfo = pkg._getElementInfo(element); |
| 708 elementRelations.add(new _ElementRelationInfo( | 721 elementRelations.add(new _ElementRelationInfo( |
| 709 elementInfo, kind, offset, length, isQualified)); | 722 elementInfo, kind, offset, length, isQualified)); |
| 710 } on StateError {} | 723 } on StateError {} |
| 711 } | 724 } |
| 712 | 725 |
| 713 void addNameRelation(String name, IndexRelationKind kind, int offset) { | 726 void addNameRelation(String name, IndexRelationKind kind, int offset) { |
| 714 _StringInfo nameId = pkg._getStringInfo(name); | 727 _StringInfo nameId = pkg._getStringInfo(name); |
| 715 nameRelations.add(new _NameRelationInfo(nameId, kind, offset)); | 728 nameRelations.add(new _NameRelationInfo(nameId, kind, offset)); |
| 716 } | 729 } |
| 717 | 730 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 743 usedNames: nameRelations.map((r) => r.nameInfo.id).toList(), | 756 usedNames: nameRelations.map((r) => r.nameInfo.id).toList(), |
| 744 usedNameKinds: nameRelations.map((r) => r.kind).toList(), | 757 usedNameKinds: nameRelations.map((r) => r.kind).toList(), |
| 745 usedNameOffsets: nameRelations.map((r) => r.offset).toList()); | 758 usedNameOffsets: nameRelations.map((r) => r.offset).toList()); |
| 746 } | 759 } |
| 747 | 760 |
| 748 void defineName(String name, IndexNameKind kind, int offset) { | 761 void defineName(String name, IndexNameKind kind, int offset) { |
| 749 _StringInfo nameInfo = pkg._getStringInfo(name); | 762 _StringInfo nameInfo = pkg._getStringInfo(name); |
| 750 definedNames.add(new _DefinedNameInfo(nameInfo, kind, offset)); | 763 definedNames.add(new _DefinedNameInfo(nameInfo, kind, offset)); |
| 751 } | 764 } |
| 752 } | 765 } |
| OLD | NEW |