OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 library services.index; | 5 library services.index; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 | 8 |
| 9 import 'package:analysis_server/analysis/index/index_core.dart'; |
| 10 import 'package:analysis_server/src/services/index/indexable_element.dart'; |
9 import 'package:analyzer/src/generated/ast.dart'; | 11 import 'package:analyzer/src/generated/ast.dart'; |
10 import 'package:analyzer/src/generated/element.dart'; | 12 import 'package:analyzer/src/generated/element.dart'; |
11 import 'package:analyzer/src/generated/engine.dart'; | 13 import 'package:analyzer/src/generated/engine.dart'; |
12 import 'package:analyzer/src/generated/html.dart'; | 14 import 'package:analyzer/src/generated/html.dart'; |
13 import 'package:analyzer/src/generated/source.dart'; | 15 import 'package:analyzer/src/generated/source.dart'; |
14 | 16 |
15 /** | 17 /** |
16 * A filter for [Element] names. | 18 * A filter for [Element] names. |
17 */ | 19 */ |
18 typedef bool ElementNameFilter(String name); | 20 typedef bool ElementNameFilter(String name); |
19 | 21 |
20 /** | 22 /** |
21 * The interface [Index] defines the behavior of objects that maintain an index | 23 * The interface [Index] defines the behavior of objects that maintain an index |
22 * storing relations between [Element]s. | 24 * storing relations between indexable objects. |
23 * | 25 * |
24 * Any modification operations are executed before any read operation. | 26 * Any modification operations are executed before any read operation. |
25 * There is no guarantee about the order in which the [Future]s for read | 27 * There is no guarantee about the order in which the [Future]s for read |
26 * operations will complete. | 28 * operations will complete. |
27 */ | 29 */ |
28 abstract class Index { | 30 abstract class Index implements IndexStore { |
| 31 /** |
| 32 * Set the index contributors used by this index to the given list of |
| 33 * [contributors]. |
| 34 */ |
| 35 void set contributors(List<IndexContributor> contributors); |
| 36 |
29 /** | 37 /** |
30 * Answers index statistics. | 38 * Answers index statistics. |
31 */ | 39 */ |
32 String get statistics; | 40 String get statistics; |
33 | 41 |
34 /** | 42 /** |
35 * Removes from the index all the information. | |
36 */ | |
37 void clear(); | |
38 | |
39 /** | |
40 * Asynchronously returns a list containing all of the locations of the | |
41 * elements that have the given [relationship] with the given [element]. | |
42 * | |
43 * For example, if the element represents a function and the relationship is | |
44 * the `is-invoked-by` relationship, then the locations will be all of the | |
45 * places where the function is invoked. | |
46 * | |
47 * [element] - the element that has the relationship with the locations to be | |
48 * returned. | |
49 * | |
50 * [relationship] - the relationship between the given element and the | |
51 * locations to be returned. | |
52 */ | |
53 Future<List<LocationImpl>> getRelationships( | |
54 Element element, RelationshipImpl relationship); | |
55 | |
56 /** | |
57 * Returns top-level [Element]s whose names satisfy to [nameFilter]. | 43 * Returns top-level [Element]s whose names satisfy to [nameFilter]. |
58 */ | 44 */ |
59 List<Element> getTopLevelDeclarations(ElementNameFilter nameFilter); | 45 List<Element> getTopLevelDeclarations(ElementNameFilter nameFilter); |
60 | 46 |
61 /** | 47 /** |
62 * Processes the given [HtmlUnit] in order to record the relationships. | 48 * Processes the given [HtmlUnit] in order to record the relationships. |
63 * | 49 * |
64 * [context] - the [AnalysisContext] in which [HtmlUnit] was resolved. | 50 * [context] - the [AnalysisContext] in which [HtmlUnit] was resolved. |
65 * [unit] - the [HtmlUnit] being indexed. | 51 * [unit] - the [HtmlUnit] being indexed. |
66 */ | 52 */ |
67 void indexHtmlUnit(AnalysisContext context, HtmlUnit unit); | 53 void indexHtmlUnit(AnalysisContext context, HtmlUnit unit); |
68 | 54 |
69 /** | 55 /** |
70 * Processes the given [CompilationUnit] in order to record the relationships. | 56 * Processes the given [CompilationUnit] in order to record the relationships. |
71 * | 57 * |
72 * [context] - the [AnalysisContext] in which [CompilationUnit] was resolved. | 58 * [context] - the [AnalysisContext] in which [CompilationUnit] was resolved. |
73 * [unit] - the [CompilationUnit] being indexed. | 59 * [unit] - the [CompilationUnit] being indexed. |
74 */ | 60 */ |
75 void indexUnit(AnalysisContext context, CompilationUnit unit); | 61 void indexUnit(AnalysisContext context, CompilationUnit unit); |
76 | 62 |
77 /** | 63 /** |
78 * Removes from the index all of the information associated with [context]. | |
79 * | |
80 * This method should be invoked when [context] is disposed. | |
81 */ | |
82 void removeContext(AnalysisContext context); | |
83 | |
84 /** | |
85 * Removes from the index all of the information associated with elements or | |
86 * locations in [source]. This includes relationships between an element in | |
87 * [source] and any other locations, relationships between any other elements | |
88 * and a location within [source]. | |
89 * | |
90 * This method should be invoked when [source] is no longer part of the code | |
91 * base. | |
92 * | |
93 * [context] - the [AnalysisContext] in which [source] being removed | |
94 * [source] - the [Source] being removed | |
95 */ | |
96 void removeSource(AnalysisContext context, Source source); | |
97 | |
98 /** | |
99 * Removes from the index all of the information associated with elements or | |
100 * locations in the given sources. This includes relationships between an | |
101 * element in the given sources and any other locations, relationships between | |
102 * any other elements and a location within the given sources. | |
103 * | |
104 * This method should be invoked when multiple sources are no longer part of | |
105 * the code base. | |
106 * | |
107 * [context] - the [AnalysisContext] in which [Source]s being removed. | |
108 * [container] - the [SourceContainer] holding the sources being removed. | |
109 */ | |
110 void removeSources(AnalysisContext context, SourceContainer container); | |
111 | |
112 /** | |
113 * Starts the index. | 64 * Starts the index. |
114 * Should be called before any other method. | 65 * Should be called before any other method. |
115 */ | 66 */ |
116 void run(); | 67 void run(); |
117 | 68 |
118 /** | 69 /** |
119 * Stops the index. | 70 * Stops the index. |
120 * After calling this method operations may not be executed. | 71 * After calling this method operations may not be executed. |
121 */ | 72 */ |
122 void stop(); | 73 void stop(); |
123 } | 74 } |
124 | 75 |
125 /** | 76 /** |
| 77 * An [Element] which is used to index references to the name without specifying |
| 78 * a concrete kind of this name - field, method or something else. |
| 79 */ |
| 80 class IndexableName implements IndexableObject { |
| 81 // TODO(brianwilkerson) Replace NameElement with this class. This will require |
| 82 // generalizing the search engine to use IndexableObject rather than Element. |
| 83 /** |
| 84 * The name to be indexed. |
| 85 */ |
| 86 final String name; |
| 87 |
| 88 /** |
| 89 * Initialize a newly created indexable name to represent the given [name]. |
| 90 */ |
| 91 IndexableName(this.name); |
| 92 |
| 93 @override |
| 94 IndexableObjectKind get kind => IndexableNameKind.INSTANCE; |
| 95 |
| 96 @override |
| 97 int get length => 0; |
| 98 |
| 99 @override |
| 100 int get offset { |
| 101 return -1; |
| 102 } |
| 103 |
| 104 @override |
| 105 Source get source => null; |
| 106 |
| 107 @override |
| 108 String toString() => name; |
| 109 } |
| 110 |
| 111 /** |
| 112 * The kind of an indexable name. |
| 113 */ |
| 114 class IndexableNameKind implements IndexableObjectKind { |
| 115 /** |
| 116 * The unique instance of this class. |
| 117 */ |
| 118 static final IndexableNameKind INSTANCE = |
| 119 new IndexableNameKind._(IndexableObjectKind.nextIndex); |
| 120 |
| 121 /** |
| 122 * The index uniquely identifying this kind. |
| 123 */ |
| 124 final int index; |
| 125 |
| 126 /** |
| 127 * Initialize a newly created kind to have the given [index]. |
| 128 */ |
| 129 IndexableNameKind._(this.index) { |
| 130 IndexableObjectKind.register(this); |
| 131 } |
| 132 |
| 133 @override |
| 134 IndexableObject decode(AnalysisContext context, String filePath, int offset) { |
| 135 throw new UnsupportedError( |
| 136 'Indexable names cannot be decoded through their kind'); |
| 137 } |
| 138 } |
| 139 |
| 140 /** |
126 * Constants used when populating and accessing the index. | 141 * Constants used when populating and accessing the index. |
127 */ | 142 */ |
128 class IndexConstants { | 143 class IndexConstants { |
129 /** | 144 /** |
130 * Left: the Universe or a Library. | 145 * Left: the Universe or a Library. |
131 * Defines an Element. | 146 * Defines an Element. |
132 * Right: an Element declaration. | 147 * Right: an Element declaration. |
133 */ | 148 */ |
134 static final RelationshipImpl DEFINES = | 149 static final RelationshipImpl DEFINES = |
135 RelationshipImpl.getRelationship("defines"); | 150 RelationshipImpl.getRelationship("defines"); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 } | 225 } |
211 | 226 |
212 /** | 227 /** |
213 * Instances of the class [LocationImpl] represent a location related to an | 228 * Instances of the class [LocationImpl] represent a location related to an |
214 * element. | 229 * element. |
215 * | 230 * |
216 * The location is expressed as an offset and length, but the offset is relative | 231 * The location is expressed as an offset and length, but the offset is relative |
217 * to the resource containing the element rather than the start of the element | 232 * to the resource containing the element rather than the start of the element |
218 * within that resource. | 233 * within that resource. |
219 */ | 234 */ |
220 class LocationImpl { | 235 class LocationImpl implements Location { |
221 static const int _FLAG_QUALIFIED = 1 << 0; | 236 static const int _FLAG_QUALIFIED = 1 << 0; |
222 static const int _FLAG_RESOLVED = 1 << 1; | 237 static const int _FLAG_RESOLVED = 1 << 1; |
223 | 238 |
224 /** | 239 /** |
225 * An empty array of locations. | 240 * An empty array of locations. |
226 */ | 241 */ |
227 static const List<LocationImpl> EMPTY_LIST = const <LocationImpl>[]; | 242 static const List<LocationImpl> EMPTY_LIST = const <LocationImpl>[]; |
228 | 243 |
229 /** | 244 /** |
230 * The element containing this location. | 245 * The indexable object containing this location. |
231 */ | 246 */ |
232 final Element element; | 247 final IndexableObject indexable; |
233 | 248 |
234 /** | 249 /** |
235 * The offset of this location within the resource containing the element. | 250 * The offset of this location within the resource containing the element. |
236 */ | 251 */ |
237 final int offset; | 252 final int offset; |
238 | 253 |
239 /** | 254 /** |
240 * The length of this location. | 255 * The length of this location. |
241 */ | 256 */ |
242 final int length; | 257 final int length; |
243 | 258 |
244 /** | 259 /** |
245 * The flags of this location. | 260 * The flags of this location. |
246 */ | 261 */ |
247 int _flags; | 262 int _flags; |
248 | 263 |
249 /** | 264 /** |
250 * Initializes a newly created location to be relative to the given element at | 265 * Initializes a newly created location to be relative to the given |
251 * the given [offset] with the given [length]. | 266 * [indexable] object at the given [offset] with the given [length]. |
252 * | |
253 * [element] - the [Element] containing this location. | |
254 * [offset] - the offset within the resource containing [element]. | |
255 * [length] - the length of this location | |
256 */ | 267 */ |
257 LocationImpl(this.element, this.offset, this.length, | 268 LocationImpl(this.indexable, this.offset, this.length, |
258 {bool isQualified: false, bool isResolved: true}) { | 269 {bool isQualified: false, bool isResolved: true}) { |
259 if (element == null) { | 270 if (indexable == null) { |
260 throw new ArgumentError("element location cannot be null"); | 271 throw new ArgumentError("indexable object cannot be null"); |
261 } | 272 } |
262 _flags = 0; | 273 _flags = 0; |
263 if (isQualified) { | 274 if (isQualified) { |
264 _flags |= _FLAG_QUALIFIED; | 275 _flags |= _FLAG_QUALIFIED; |
265 } | 276 } |
266 if (isResolved) { | 277 if (isResolved) { |
267 _flags |= _FLAG_RESOLVED; | 278 _flags |= _FLAG_RESOLVED; |
268 } | 279 } |
269 } | 280 } |
270 | 281 |
271 /** | 282 /** |
272 * Returns `true` if this location is a qualified reference. | 283 * The element containing this location. |
273 */ | 284 */ |
| 285 @deprecated |
| 286 Element get element { |
| 287 if (indexable is IndexableElement) { |
| 288 return (indexable as IndexableElement).element; |
| 289 } |
| 290 return null; |
| 291 } |
| 292 |
| 293 @override |
274 bool get isQualified => (_flags & _FLAG_QUALIFIED) != 0; | 294 bool get isQualified => (_flags & _FLAG_QUALIFIED) != 0; |
275 | 295 |
276 /** | 296 @override |
277 * Returns `true` if this location is a resolved reference. | |
278 */ | |
279 bool get isResolved => (_flags & _FLAG_RESOLVED) != 0; | 297 bool get isResolved => (_flags & _FLAG_RESOLVED) != 0; |
280 | 298 |
281 @override | 299 @override |
282 String toString() { | 300 String toString() { |
283 String flagsStr = ''; | 301 String flagsStr = ''; |
284 if (isQualified) { | 302 if (isQualified) { |
285 flagsStr += ' qualified'; | 303 flagsStr += ' qualified'; |
286 } | 304 } |
287 if (isResolved) { | 305 if (isResolved) { |
288 flagsStr += ' resolved'; | 306 flagsStr += ' resolved'; |
289 } | 307 } |
290 return '[${offset} - ${(offset + length)}) $flagsStr in ${element}'; | 308 return '[${offset} - ${(offset + length)}) $flagsStr in ${indexable}'; |
291 } | 309 } |
292 } | 310 } |
293 | 311 |
294 /** | 312 /** |
295 * A [LocationImpl] with attached data. | 313 * A [LocationImpl] with attached data. |
296 */ | 314 */ |
297 class LocationWithData<D> extends LocationImpl { | 315 class LocationWithData<D> extends LocationImpl { |
298 final D data; | 316 final D data; |
299 | 317 |
300 LocationWithData(LocationImpl location, this.data) | 318 LocationWithData(LocationImpl location, this.data) |
301 : super(location.element, location.offset, location.length); | 319 : super(location.indexable, location.offset, location.length); |
302 } | 320 } |
303 | 321 |
304 /** | 322 /** |
305 * An [Element] which is used to index references to the name without specifying | 323 * An [Element] which is used to index references to the name without specifying |
306 * a concrete kind of this name - field, method or something else. | 324 * a concrete kind of this name - field, method or something else. |
307 */ | 325 */ |
308 class NameElement extends ElementImpl { | 326 class NameElement extends ElementImpl { |
309 NameElement(String name) : super(name, -1); | 327 NameElement(String name) : super(name, -1); |
310 | 328 |
311 @override | 329 @override |
312 ElementKind get kind => ElementKind.NAME; | 330 ElementKind get kind => ElementKind.NAME; |
313 | 331 |
314 @override | 332 @override |
315 accept(ElementVisitor visitor) => null; | 333 accept(ElementVisitor visitor) => null; |
316 } | 334 } |
317 | 335 |
318 /** | 336 /** |
319 * Relationship between an element and a location. Relationships are identified | 337 * Relationship between an element and a location. Relationships are identified |
320 * by a globally unique identifier. | 338 * by a globally unique identifier. |
321 */ | 339 */ |
322 class RelationshipImpl { | 340 class RelationshipImpl implements Relationship { |
323 /** | 341 /** |
324 * A table mapping relationship identifiers to relationships. | 342 * A table mapping relationship identifiers to relationships. |
325 */ | 343 */ |
326 static Map<String, RelationshipImpl> _RELATIONSHIP_MAP = {}; | 344 static Map<String, RelationshipImpl> _RELATIONSHIP_MAP = {}; |
327 | 345 |
328 /** | 346 /** |
329 * The next artificial hash code. | 347 * The next artificial hash code. |
330 */ | 348 */ |
331 static int _NEXT_HASH_CODE = 0; | 349 static int _NEXT_HASH_CODE = 0; |
332 | 350 |
(...skipping 23 matching lines...) Expand all Loading... |
356 */ | 374 */ |
357 static RelationshipImpl getRelationship(String identifier) { | 375 static RelationshipImpl getRelationship(String identifier) { |
358 RelationshipImpl relationship = _RELATIONSHIP_MAP[identifier]; | 376 RelationshipImpl relationship = _RELATIONSHIP_MAP[identifier]; |
359 if (relationship == null) { | 377 if (relationship == null) { |
360 relationship = new RelationshipImpl(identifier); | 378 relationship = new RelationshipImpl(identifier); |
361 _RELATIONSHIP_MAP[identifier] = relationship; | 379 _RELATIONSHIP_MAP[identifier] = relationship; |
362 } | 380 } |
363 return relationship; | 381 return relationship; |
364 } | 382 } |
365 } | 383 } |
OLD | NEW |