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 'dart:async'; | 5 import 'dart:async'; |
6 | 6 |
7 import 'package:analyzer/dart/ast/ast.dart'; | 7 import 'package:analyzer/dart/ast/ast.dart'; |
8 import 'package:analyzer/dart/element/element.dart'; | 8 import 'package:analyzer/dart/element/element.dart'; |
| 9 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext; |
9 import 'package:analyzer/src/generated/source.dart'; | 10 import 'package:analyzer/src/generated/source.dart'; |
10 import 'package:analyzer/src/summary/format.dart'; | 11 import 'package:analyzer/src/summary/format.dart'; |
11 import 'package:analyzer/src/summary/idl.dart'; | 12 import 'package:analyzer/src/summary/idl.dart'; |
12 import 'package:analyzer/src/summary/index_unit.dart'; | 13 import 'package:analyzer/src/summary/index_unit.dart'; |
13 import 'package:collection/collection.dart'; | 14 import 'package:collection/collection.dart'; |
14 | 15 |
15 /** | 16 /** |
16 * Return a new [Index2] instance that keeps information in memory. | 17 * Return a new [Index2] instance that keeps information in memory. |
17 */ | 18 */ |
18 Index2 createMemoryIndex2() { | 19 Index2 createMemoryIndex2() { |
19 _MemoryPackageIndexStore store = new _MemoryPackageIndexStore(); | 20 return new Index2._(); |
20 return new Index2(store); | |
21 } | 21 } |
22 | 22 |
23 /** | 23 /** |
24 * Return the index of the first occurrence of the [value] in the [sortedList], | 24 * Return the index of the first occurrence of the [value] in the [sortedList], |
25 * or `-1` if the [value] is not in the list. | 25 * or `-1` if the [value] is not in the list. |
26 */ | 26 */ |
27 int _findFirstOccurrence(List<int> sortedList, int value) { | 27 int _findFirstOccurrence(List<int> sortedList, int value) { |
28 // Find an occurrence. | 28 // Find an occurrence. |
29 int i = binarySearch(sortedList, value); | 29 int i = binarySearch(sortedList, value); |
30 if (i == -1) { | 30 if (i == -1) { |
31 return -1; | 31 return -1; |
32 } | 32 } |
33 // Find the first occurrence. | 33 // Find the first occurrence. |
34 while (i > 0 && sortedList[i - 1] == value) { | 34 while (i > 0 && sortedList[i - 1] == value) { |
35 i--; | 35 i--; |
36 } | 36 } |
37 return i; | 37 return i; |
38 } | 38 } |
39 | 39 |
40 /** | 40 /** |
41 * Interface for storing and requesting relations. | 41 * Interface for storing and requesting relations. |
42 */ | 42 */ |
43 class Index2 { | 43 class Index2 { |
44 final PackageIndexStore _store; | 44 final Map<AnalysisContext, _ContextIndex> _contextIndexMap = |
| 45 <AnalysisContext, _ContextIndex>{}; |
45 | 46 |
46 Index2(this._store); | 47 Index2._(); |
47 | 48 |
48 /** | 49 /** |
49 * Complete with a list of locations where elements of the given [kind] with | 50 * Complete with a list of locations where elements of the given [kind] with |
50 * names satisfying the given [regExp] are defined. | 51 * names satisfying the given [regExp] are defined. |
51 */ | 52 */ |
52 Future<List<Location>> getDefinedNames( | 53 Future<List<Location>> getDefinedNames(RegExp regExp, IndexNameKind kind) { |
53 RegExp regExp, IndexNameKind kind) async { | 54 return _mergeLocations((_ContextIndex index) { |
54 List<Location> locations = <Location>[]; | 55 return index.getDefinedNames(regExp, kind); |
55 Iterable<PackageIndexId> ids = await _store.getIds(); | 56 }); |
56 for (PackageIndexId id in ids) { | |
57 PackageIndex index = await _store.getIndex(id); | |
58 _PackageIndexRequester requester = new _PackageIndexRequester(index); | |
59 List<Location> packageLocations = requester.getDefinedNames(regExp, kind); | |
60 locations.addAll(packageLocations); | |
61 } | |
62 return locations; | |
63 } | 57 } |
64 | 58 |
65 /** | 59 /** |
66 * Complete with a list of locations where the given [element] has relation | 60 * Complete with a list of locations where the given [element] has relation |
67 * of the given [kind]. | 61 * of the given [kind]. |
68 */ | 62 */ |
69 Future<List<Location>> getRelations( | 63 Future<List<Location>> getRelations(Element element, IndexRelationKind kind) { |
70 Element element, IndexRelationKind kind) async { | 64 return _mergeLocations((_ContextIndex index) { |
71 List<Location> locations = <Location>[]; | 65 return index.getRelations(element, kind); |
72 Iterable<PackageIndexId> ids = await _store.getIds(); | 66 }); |
73 for (PackageIndexId id in ids) { | |
74 PackageIndex index = await _store.getIndex(id); | |
75 _PackageIndexRequester requester = new _PackageIndexRequester(index); | |
76 List<Location> packageLocations = requester.getRelations(element, kind); | |
77 locations.addAll(packageLocations); | |
78 } | |
79 return locations; | |
80 } | 67 } |
81 | 68 |
82 /** | 69 /** |
83 * Complete with a list of locations where a class members with the given | 70 * Complete with a list of locations where a class members with the given |
84 * [name] is referenced with a qualifier, but is not resolved. | 71 * [name] is referenced with a qualifier, but is not resolved. |
85 */ | 72 */ |
86 Future<List<Location>> getUnresolvedMemberReferences(String name) async { | 73 Future<List<Location>> getUnresolvedMemberReferences(String name) { |
87 List<Location> locations = <Location>[]; | 74 return _mergeLocations((_ContextIndex index) { |
88 Iterable<PackageIndexId> ids = await _store.getIds(); | 75 return index.getUnresolvedMemberReferences(name); |
89 for (PackageIndexId id in ids) { | 76 }); |
90 PackageIndex index = await _store.getIndex(id); | |
91 _PackageIndexRequester requester = new _PackageIndexRequester(index); | |
92 List<Location> packageLocations = | |
93 requester.getUnresolvedMemberReferences(name); | |
94 locations.addAll(packageLocations); | |
95 } | |
96 return locations; | |
97 } | 77 } |
98 | 78 |
99 /** | 79 /** |
100 * Index the given fully resolved [unit]. | 80 * Index the given fully resolved [unit]. |
101 */ | 81 */ |
102 void indexUnit(CompilationUnit unit) { | 82 void indexUnit(CompilationUnit unit) { |
103 PackageIndexAssembler assembler = new PackageIndexAssembler(); | 83 if (unit == null || unit.element == null) { |
104 assembler.index(unit); | 84 return; |
105 PackageIndexBuilder indexBuilder = assembler.assemble(); | 85 } |
106 String unitLibraryUri = unit.element.library.source.uri.toString(); | 86 AnalysisContext context = unit.element.context; |
107 String unitUnitUri = unit.element.source.uri.toString(); | 87 _getContextIndex(context).indexUnit(unit); |
108 _store.putIndex(unitLibraryUri, unitUnitUri, indexBuilder); | 88 } |
| 89 |
| 90 /** |
| 91 * Remove all index information for the given [context]. |
| 92 */ |
| 93 void removeContext(AnalysisContext context) { |
| 94 _contextIndexMap.remove(context); |
| 95 } |
| 96 |
| 97 /** |
| 98 * Return the [_ContextIndex] instance for the given [context]. |
| 99 */ |
| 100 _ContextIndex _getContextIndex(AnalysisContext context) { |
| 101 return _contextIndexMap.putIfAbsent(context, () { |
| 102 return new _ContextIndex(context); |
| 103 }); |
| 104 } |
| 105 |
| 106 /** |
| 107 * Complete with a list of all results returned by the [callback] for every |
| 108 * context specific index. |
| 109 */ |
| 110 Future<List<Location>> _mergeLocations( |
| 111 Future<List<Location>> callback(_ContextIndex index)) async { |
| 112 List<Location> locations = <Location>[]; |
| 113 for (_ContextIndex index in _contextIndexMap.values) { |
| 114 List<Location> contextLocations = await callback(index); |
| 115 locations.addAll(contextLocations); |
| 116 } |
| 117 return locations; |
109 } | 118 } |
110 } | 119 } |
111 | 120 |
112 /** | 121 /** |
113 * Information about location of a single relation in the index. | 122 * Information about location of a single relation in the index. |
114 * | 123 * |
115 * The location is expressed as a library specific unit containing the index | 124 * The location is expressed as a library specific unit containing the index |
116 * relation, offset within this [Source] and length. | 125 * relation, offset within this [Source] and length. |
117 * | 126 * |
118 * Clients may not extend, implement or mix-in this class. | 127 * Clients may not extend, implement or mix-in this class. |
119 */ | 128 */ |
120 class Location { | 129 class Location { |
121 /** | 130 /** |
| 131 * The [AnalysisContext] containing this location. |
| 132 */ |
| 133 final AnalysisContext context; |
| 134 |
| 135 /** |
122 * The URI of the source of the library containing this location. | 136 * The URI of the source of the library containing this location. |
123 */ | 137 */ |
124 final String libraryUri; | 138 final String libraryUri; |
125 | 139 |
126 /** | 140 /** |
127 * The URI of the source of the unit containing this location. | 141 * The URI of the source of the unit containing this location. |
128 */ | 142 */ |
129 final String unitUri; | 143 final String unitUri; |
130 | 144 |
131 /** | 145 /** |
132 * The offset of this location within the [unitUri]. | 146 * The offset of this location within the [unitUri]. |
133 */ | 147 */ |
134 final int offset; | 148 final int offset; |
135 | 149 |
136 /** | 150 /** |
137 * The length of this location. | 151 * The length of this location. |
138 */ | 152 */ |
139 final int length; | 153 final int length; |
140 | 154 |
141 /** | 155 /** |
142 * Is `true` if this location is qualified. | 156 * Is `true` if this location is qualified. |
143 */ | 157 */ |
144 final bool isQualified; | 158 final bool isQualified; |
145 | 159 |
146 Location(this.libraryUri, this.unitUri, this.offset, this.length, | 160 Location(this.context, this.libraryUri, this.unitUri, this.offset, |
147 this.isQualified); | 161 this.length, this.isQualified); |
148 | 162 |
149 @override | 163 @override |
150 String toString() => 'Location{librarySourceUri: $libraryUri, ' | 164 String toString() => 'Location{librarySourceUri: $libraryUri, ' |
151 'unitSourceUri: $unitUri, offset: $offset, length: $length, ' | 165 'unitSourceUri: $unitUri, offset: $offset, length: $length, ' |
152 'isQualified: $isQualified}'; | 166 'isQualified: $isQualified}'; |
153 } | 167 } |
154 | 168 |
155 /** | 169 /** |
156 * Opaque identifier of a [PackageIndex]. | 170 * Opaque identifier of a [PackageIndex]. |
157 */ | 171 */ |
(...skipping 14 matching lines...) Expand all Loading... |
172 Future<PackageIndex> getIndex(PackageIndexId id); | 186 Future<PackageIndex> getIndex(PackageIndexId id); |
173 | 187 |
174 /** | 188 /** |
175 * Put the given [indexBuilder] into the store. | 189 * Put the given [indexBuilder] into the store. |
176 */ | 190 */ |
177 void putIndex(String unitLibraryUri, String unitUnitUri, | 191 void putIndex(String unitLibraryUri, String unitUnitUri, |
178 PackageIndexBuilder indexBuilder); | 192 PackageIndexBuilder indexBuilder); |
179 } | 193 } |
180 | 194 |
181 /** | 195 /** |
182 * A [PackageIndexId] for [_MemoryPackageIndexStore]. | 196 * The [AnalysisContext] specific index. |
183 */ | 197 */ |
184 class _MemoryPackageIndexId implements PackageIndexId { | 198 class _ContextIndex { |
185 final String key; | 199 final AnalysisContext context; |
186 | |
187 _MemoryPackageIndexId(this.key); | |
188 } | |
189 | |
190 /** | |
191 * A [PackageIndexStore] that keeps objects in memory; | |
192 */ | |
193 class _MemoryPackageIndexStore implements PackageIndexStore { | |
194 final Map<String, PackageIndex> indexMap = <String, PackageIndex>{}; | 200 final Map<String, PackageIndex> indexMap = <String, PackageIndex>{}; |
195 | 201 |
196 @override | 202 _ContextIndex(this.context); |
197 Future<Iterable<PackageIndexId>> getIds() async { | 203 |
198 return indexMap.keys.map((key) => new _MemoryPackageIndexId(key)); | 204 /** |
| 205 * Complete with a list of locations where elements of the given [kind] with |
| 206 * names satisfying the given [regExp] are defined. |
| 207 */ |
| 208 Future<List<Location>> getDefinedNames( |
| 209 RegExp regExp, IndexNameKind kind) async { |
| 210 return _mergeLocations((PackageIndex index) { |
| 211 _PackageIndexRequester requester = new _PackageIndexRequester(index); |
| 212 return requester.getDefinedNames(context, regExp, kind); |
| 213 }); |
199 } | 214 } |
200 | 215 |
201 @override | 216 /** |
202 Future<PackageIndex> getIndex(PackageIndexId id) async { | 217 * Complete with a list of locations where the given [element] has relation |
203 return indexMap[(id as _MemoryPackageIndexId).key]; | 218 * of the given [kind]. |
| 219 */ |
| 220 Future<List<Location>> getRelations(Element element, IndexRelationKind kind) { |
| 221 return _mergeLocations((PackageIndex index) { |
| 222 _PackageIndexRequester requester = new _PackageIndexRequester(index); |
| 223 return requester.getRelations(context, element, kind); |
| 224 }); |
204 } | 225 } |
205 | 226 |
206 @override | 227 /** |
207 putIndex(String unitLibraryUri, String unitUnitUri, | 228 * Complete with a list of locations where a class members with the given |
208 PackageIndexBuilder indexBuilder) { | 229 * [name] is referenced with a qualifier, but is not resolved. |
| 230 */ |
| 231 Future<List<Location>> getUnresolvedMemberReferences(String name) async { |
| 232 return _mergeLocations((PackageIndex index) { |
| 233 _PackageIndexRequester requester = new _PackageIndexRequester(index); |
| 234 return requester.getUnresolvedMemberReferences(context, name); |
| 235 }); |
| 236 } |
| 237 |
| 238 /** |
| 239 * Index the given fully resolved [unit]. |
| 240 */ |
| 241 void indexUnit(CompilationUnit unit) { |
| 242 // Index the unit. |
| 243 PackageIndexAssembler assembler = new PackageIndexAssembler(); |
| 244 assembler.index(unit); |
| 245 PackageIndexBuilder indexBuilder = assembler.assemble(); |
| 246 // Put the index into the map. |
209 List<int> indexBytes = indexBuilder.toBuffer(); | 247 List<int> indexBytes = indexBuilder.toBuffer(); |
210 PackageIndex index = new PackageIndex.fromBuffer(indexBytes); | 248 PackageIndex index = new PackageIndex.fromBuffer(indexBytes); |
211 String key = '$unitLibraryUri;$unitUnitUri'; | 249 String key = _getUnitKeyForElement(unit.element); |
212 indexMap[key] = index; | 250 indexMap[key] = index; |
213 } | 251 } |
| 252 |
| 253 String _getUnitKeyForElement(CompilationUnitElement unitElement) { |
| 254 Source librarySource = unitElement.library.source; |
| 255 Source unitSource = unitElement.source; |
| 256 return _getUnitKeyForSource(librarySource, unitSource); |
| 257 } |
| 258 |
| 259 String _getUnitKeyForSource(Source librarySource, Source unitSource) { |
| 260 String unitLibraryUri = librarySource.uri.toString(); |
| 261 String unitUnitUri = unitSource.uri.toString(); |
| 262 return '$unitLibraryUri;$unitUnitUri'; |
| 263 } |
| 264 |
| 265 Future<List<Location>> _mergeLocations( |
| 266 List<Location> callback(PackageIndex index)) async { |
| 267 List<Location> locations = <Location>[]; |
| 268 for (PackageIndex index in indexMap.values) { |
| 269 List<Location> indexLocations = callback(index); |
| 270 locations.addAll(indexLocations); |
| 271 } |
| 272 return locations; |
| 273 } |
214 } | 274 } |
215 | 275 |
216 /** | 276 /** |
217 * Helper for requesting information from a single [PackageIndex]. | 277 * Helper for requesting information from a single [PackageIndex]. |
218 */ | 278 */ |
219 class _PackageIndexRequester { | 279 class _PackageIndexRequester { |
220 final PackageIndex index; | 280 final PackageIndex index; |
221 | 281 |
222 _PackageIndexRequester(this.index); | 282 _PackageIndexRequester(this.index); |
223 | 283 |
(...skipping 29 matching lines...) Expand all Loading... |
253 return elementId; | 313 return elementId; |
254 } | 314 } |
255 } | 315 } |
256 return -1; | 316 return -1; |
257 } | 317 } |
258 | 318 |
259 /** | 319 /** |
260 * Complete with a list of locations where elements of the given [kind] with | 320 * Complete with a list of locations where elements of the given [kind] with |
261 * names satisfying the given [regExp] are defined. | 321 * names satisfying the given [regExp] are defined. |
262 */ | 322 */ |
263 List<Location> getDefinedNames(RegExp regExp, IndexNameKind kind) { | 323 List<Location> getDefinedNames( |
| 324 AnalysisContext context, RegExp regExp, IndexNameKind kind) { |
264 List<Location> locations = <Location>[]; | 325 List<Location> locations = <Location>[]; |
265 for (UnitIndex unitIndex in index.units) { | 326 for (UnitIndex unitIndex in index.units) { |
266 _UnitIndexRequester requester = new _UnitIndexRequester(this, unitIndex); | 327 _UnitIndexRequester requester = new _UnitIndexRequester(this, unitIndex); |
267 List<Location> unitLocations = requester.getDefinedNames(regExp, kind); | 328 List<Location> unitLocations = |
| 329 requester.getDefinedNames(context, regExp, kind); |
268 locations.addAll(unitLocations); | 330 locations.addAll(unitLocations); |
269 } | 331 } |
270 return locations; | 332 return locations; |
271 } | 333 } |
272 | 334 |
273 /** | 335 /** |
274 * Complete with a list of locations where the given [element] has relation | 336 * Complete with a list of locations where the given [element] has relation |
275 * of the given [kind]. | 337 * of the given [kind]. |
276 */ | 338 */ |
277 List<Location> getRelations(Element element, IndexRelationKind kind) { | 339 List<Location> getRelations( |
| 340 AnalysisContext context, Element element, IndexRelationKind kind) { |
278 int elementId = findElementId(element); | 341 int elementId = findElementId(element); |
279 if (elementId == -1) { | 342 if (elementId == -1) { |
280 return const <Location>[]; | 343 return const <Location>[]; |
281 } | 344 } |
282 List<Location> locations = <Location>[]; | 345 List<Location> locations = <Location>[]; |
283 for (UnitIndex unitIndex in index.units) { | 346 for (UnitIndex unitIndex in index.units) { |
284 _UnitIndexRequester requester = new _UnitIndexRequester(this, unitIndex); | 347 _UnitIndexRequester requester = new _UnitIndexRequester(this, unitIndex); |
285 List<Location> unitLocations = requester.getRelations(elementId, kind); | 348 List<Location> unitLocations = |
| 349 requester.getRelations(context, elementId, kind); |
286 locations.addAll(unitLocations); | 350 locations.addAll(unitLocations); |
287 } | 351 } |
288 return locations; | 352 return locations; |
289 } | 353 } |
290 | 354 |
291 /** | 355 /** |
292 * Return the identifier of [str] in the [index] or `-1` if [str] is not used | 356 * Return the identifier of [str] in the [index] or `-1` if [str] is not used |
293 * in the [index]. | 357 * in the [index]. |
294 */ | 358 */ |
295 int getStringId(String str) { | 359 int getStringId(String str) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
333 */ | 397 */ |
334 String getUnitUnitUri(int unit) { | 398 String getUnitUnitUri(int unit) { |
335 int id = index.unitUnitUris[unit]; | 399 int id = index.unitUnitUris[unit]; |
336 return index.strings[id]; | 400 return index.strings[id]; |
337 } | 401 } |
338 | 402 |
339 /** | 403 /** |
340 * Complete with a list of locations where a class members with the given | 404 * Complete with a list of locations where a class members with the given |
341 * [name] is referenced with a qualifier, but is not resolved. | 405 * [name] is referenced with a qualifier, but is not resolved. |
342 */ | 406 */ |
343 List<Location> getUnresolvedMemberReferences(String name) { | 407 List<Location> getUnresolvedMemberReferences( |
| 408 AnalysisContext context, String name) { |
344 List<Location> locations = <Location>[]; | 409 List<Location> locations = <Location>[]; |
345 for (UnitIndex unitIndex in index.units) { | 410 for (UnitIndex unitIndex in index.units) { |
346 _UnitIndexRequester requester = new _UnitIndexRequester(this, unitIndex); | 411 _UnitIndexRequester requester = new _UnitIndexRequester(this, unitIndex); |
347 List<Location> unitLocations = | 412 List<Location> unitLocations = |
348 requester.getUnresolvedMemberReferences(name); | 413 requester.getUnresolvedMemberReferences(context, name); |
349 locations.addAll(unitLocations); | 414 locations.addAll(unitLocations); |
350 } | 415 } |
351 return locations; | 416 return locations; |
352 } | 417 } |
353 | 418 |
354 /** | 419 /** |
355 * Return the identifier of the [uri] in the [index] or `-1` if the [uri] is | 420 * Return the identifier of the [uri] in the [index] or `-1` if the [uri] is |
356 * not used in the [index]. | 421 * not used in the [index]. |
357 */ | 422 */ |
358 int getUriId(Uri uri) { | 423 int getUriId(Uri uri) { |
359 String str = uri.toString(); | 424 String str = uri.toString(); |
360 return getStringId(str); | 425 return getStringId(str); |
361 } | 426 } |
362 } | 427 } |
363 | 428 |
364 /** | 429 /** |
365 * Helper for requesting information from a single [UnitIndex]. | 430 * Helper for requesting information from a single [UnitIndex]. |
366 */ | 431 */ |
367 class _UnitIndexRequester { | 432 class _UnitIndexRequester { |
368 final _PackageIndexRequester packageRequester; | 433 final _PackageIndexRequester packageRequester; |
369 final UnitIndex unitIndex; | 434 final UnitIndex unitIndex; |
370 | 435 |
371 _UnitIndexRequester(this.packageRequester, this.unitIndex); | 436 _UnitIndexRequester(this.packageRequester, this.unitIndex); |
372 | 437 |
373 /** | 438 /** |
374 * Complete with a list of locations where elements of the given [kind] with | 439 * Complete with a list of locations where elements of the given [kind] with |
375 * names satisfying the given [regExp] are defined. | 440 * names satisfying the given [regExp] are defined. |
376 */ | 441 */ |
377 List<Location> getDefinedNames(RegExp regExp, IndexNameKind kind) { | 442 List<Location> getDefinedNames( |
| 443 AnalysisContext context, RegExp regExp, IndexNameKind kind) { |
378 List<Location> locations = <Location>[]; | 444 List<Location> locations = <Location>[]; |
379 String unitLibraryUri = null; | 445 String unitLibraryUri = null; |
380 String unitUnitUri = null; | 446 String unitUnitUri = null; |
381 for (int i = 0; i < unitIndex.definedNames.length; i++) { | 447 for (int i = 0; i < unitIndex.definedNames.length; i++) { |
382 if (unitIndex.definedNameKinds[i] == kind) { | 448 if (unitIndex.definedNameKinds[i] == kind) { |
383 int nameIndex = unitIndex.definedNames[i]; | 449 int nameIndex = unitIndex.definedNames[i]; |
384 String name = packageRequester.index.strings[nameIndex]; | 450 String name = packageRequester.index.strings[nameIndex]; |
385 if (regExp.matchAsPrefix(name) != null) { | 451 if (regExp.matchAsPrefix(name) != null) { |
386 unitLibraryUri ??= packageRequester.getUnitLibraryUri(unitIndex.unit); | 452 unitLibraryUri ??= packageRequester.getUnitLibraryUri(unitIndex.unit); |
387 unitUnitUri ??= packageRequester.getUnitUnitUri(unitIndex.unit); | 453 unitUnitUri ??= packageRequester.getUnitUnitUri(unitIndex.unit); |
388 locations.add(new Location(unitLibraryUri, unitUnitUri, | 454 locations.add(new Location(context, unitLibraryUri, unitUnitUri, |
389 unitIndex.definedNameOffsets[i], name.length, false)); | 455 unitIndex.definedNameOffsets[i], name.length, false)); |
390 } | 456 } |
391 } | 457 } |
392 } | 458 } |
393 return locations; | 459 return locations; |
394 } | 460 } |
395 | 461 |
396 /** | 462 /** |
397 * Return a list of locations where an element with the given [elementId] has | 463 * Return a list of locations where an element with the given [elementId] has |
398 * relation of the given [kind]. | 464 * relation of the given [kind]. |
399 */ | 465 */ |
400 List<Location> getRelations(int elementId, IndexRelationKind kind) { | 466 List<Location> getRelations( |
| 467 AnalysisContext context, int elementId, IndexRelationKind kind) { |
401 // Find the first usage of the element. | 468 // Find the first usage of the element. |
402 int i = _findFirstOccurrence(unitIndex.usedElements, elementId); | 469 int i = _findFirstOccurrence(unitIndex.usedElements, elementId); |
403 if (i == -1) { | 470 if (i == -1) { |
404 return const <Location>[]; | 471 return const <Location>[]; |
405 } | 472 } |
406 // Create locations for every usage of the element. | 473 // Create locations for every usage of the element. |
407 List<Location> locations = <Location>[]; | 474 List<Location> locations = <Location>[]; |
408 String unitLibraryUri = null; | 475 String unitLibraryUri = null; |
409 String unitUnitUri = null; | 476 String unitUnitUri = null; |
410 for (; | 477 for (; |
411 i < unitIndex.usedElements.length && | 478 i < unitIndex.usedElements.length && |
412 unitIndex.usedElements[i] == elementId; | 479 unitIndex.usedElements[i] == elementId; |
413 i++) { | 480 i++) { |
414 if (unitIndex.usedElementKinds[i] == kind) { | 481 if (unitIndex.usedElementKinds[i] == kind) { |
415 unitLibraryUri ??= packageRequester.getUnitLibraryUri(unitIndex.unit); | 482 unitLibraryUri ??= packageRequester.getUnitLibraryUri(unitIndex.unit); |
416 unitUnitUri ??= packageRequester.getUnitUnitUri(unitIndex.unit); | 483 unitUnitUri ??= packageRequester.getUnitUnitUri(unitIndex.unit); |
417 locations.add(new Location( | 484 locations.add(new Location( |
| 485 context, |
418 unitLibraryUri, | 486 unitLibraryUri, |
419 unitUnitUri, | 487 unitUnitUri, |
420 unitIndex.usedElementOffsets[i], | 488 unitIndex.usedElementOffsets[i], |
421 unitIndex.usedElementLengths[i], | 489 unitIndex.usedElementLengths[i], |
422 unitIndex.usedElementIsQualifiedFlags[i])); | 490 unitIndex.usedElementIsQualifiedFlags[i])); |
423 } | 491 } |
424 } | 492 } |
425 return locations; | 493 return locations; |
426 } | 494 } |
427 | 495 |
428 /** | 496 /** |
429 * Complete with a list of locations where a class members with the given | 497 * Complete with a list of locations where a class members with the given |
430 * [name] is referenced with a qualifier, but is not resolved. | 498 * [name] is referenced with a qualifier, but is not resolved. |
431 */ | 499 */ |
432 List<Location> getUnresolvedMemberReferences(String name) { | 500 List<Location> getUnresolvedMemberReferences( |
| 501 AnalysisContext context, String name) { |
433 // Find the name ID in the package index. | 502 // Find the name ID in the package index. |
434 int nameId = packageRequester.getStringId(name); | 503 int nameId = packageRequester.getStringId(name); |
435 if (nameId == -1) { | 504 if (nameId == -1) { |
436 return const <Location>[]; | 505 return const <Location>[]; |
437 } | 506 } |
438 // Find the first usage of the name. | 507 // Find the first usage of the name. |
439 int i =_findFirstOccurrence(unitIndex.usedNames, nameId); | 508 int i = _findFirstOccurrence(unitIndex.usedNames, nameId); |
440 if (i == -1) { | 509 if (i == -1) { |
441 return const <Location>[]; | 510 return const <Location>[]; |
442 } | 511 } |
443 // Create locations for every usage of the name. | 512 // Create locations for every usage of the name. |
444 List<Location> locations = <Location>[]; | 513 List<Location> locations = <Location>[]; |
445 String unitLibraryUri = null; | 514 String unitLibraryUri = null; |
446 String unitUnitUri = null; | 515 String unitUnitUri = null; |
447 for (; i < unitIndex.usedNames.length && | 516 for (; |
448 unitIndex.usedNames[i] == nameId; i++) { | 517 i < unitIndex.usedNames.length && unitIndex.usedNames[i] == nameId; |
| 518 i++) { |
449 unitLibraryUri ??= packageRequester.getUnitLibraryUri(unitIndex.unit); | 519 unitLibraryUri ??= packageRequester.getUnitLibraryUri(unitIndex.unit); |
450 unitUnitUri ??= packageRequester.getUnitUnitUri(unitIndex.unit); | 520 unitUnitUri ??= packageRequester.getUnitUnitUri(unitIndex.unit); |
451 locations.add(new Location(unitLibraryUri, unitUnitUri, | 521 locations.add(new Location(context, unitLibraryUri, unitUnitUri, |
452 unitIndex.usedNameOffsets[i], name.length, true)); | 522 unitIndex.usedNameOffsets[i], name.length, true)); |
453 } | 523 } |
454 return locations; | 524 return locations; |
455 } | 525 } |
456 } | 526 } |
OLD | NEW |