| 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 |