| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | |
| 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. | |
| 4 | |
| 5 library analysis_server.analysis.index.index_core; | |
| 6 | |
| 7 import 'dart:async'; | |
| 8 import 'dart:collection'; | |
| 9 | |
| 10 import 'package:analysis_server/src/services/index/index.dart'; | |
| 11 import 'package:analyzer/src/generated/engine.dart'; | |
| 12 import 'package:analyzer/src/generated/source.dart'; | |
| 13 | |
| 14 /** | |
| 15 * An object that can have a [Relationship] with various [Location]s in a code | |
| 16 * base. The object is abstractly represented by a [kind] and an [offset] within | |
| 17 * a [source]. | |
| 18 * | |
| 19 * Clients must ensure that two distinct objects in the same source cannot have | |
| 20 * the same kind and offset. Failure to do so will make it impossible for | |
| 21 * clients to identify the model element corresponding to the indexable object. | |
| 22 * | |
| 23 * Clients are expected to subtype this class when implementing plugins. | |
| 24 */ | |
| 25 abstract class IndexableObject { | |
| 26 /** | |
| 27 * Return the kind of this object. | |
| 28 */ | |
| 29 IndexableObjectKind get kind; | |
| 30 | |
| 31 /** | |
| 32 * Return the length of the indexable object within its source. | |
| 33 */ | |
| 34 int get length; | |
| 35 | |
| 36 /** | |
| 37 * Return the name of this element. | |
| 38 */ | |
| 39 // TODO(brianwilkerson) Remove the need for this getter. | |
| 40 String get name; | |
| 41 | |
| 42 /** | |
| 43 * Return the offset of the indexable object within its source. | |
| 44 */ | |
| 45 int get offset; | |
| 46 | |
| 47 /** | |
| 48 * Return the source containing the indexable object. | |
| 49 */ | |
| 50 Source get source; | |
| 51 } | |
| 52 | |
| 53 /** | |
| 54 * The kind associated with an [IndexableObject]. | |
| 55 * | |
| 56 * Clients are expected to implement this class when implementing plugins. | |
| 57 */ | |
| 58 abstract class IndexableObjectKind { | |
| 59 /** | |
| 60 * The next available index for a newly created kind of indexable object. | |
| 61 */ | |
| 62 static int _nextIndex = 0; | |
| 63 | |
| 64 /** | |
| 65 * A table mapping indexes to object kinds. | |
| 66 */ | |
| 67 static Map<int, IndexableObjectKind> _registry = | |
| 68 new HashMap<int, IndexableObjectKind>(); | |
| 69 | |
| 70 /** | |
| 71 * Return the next available index for a newly created kind of indexable | |
| 72 * object. | |
| 73 */ | |
| 74 static int get nextIndex => _nextIndex++; | |
| 75 | |
| 76 /** | |
| 77 * Return the unique index for this kind of indexable object. Implementations | |
| 78 * should invoke [nextIndex] to allocate an index that cannot be used by any | |
| 79 * other object kind. | |
| 80 */ | |
| 81 int get index; | |
| 82 | |
| 83 /** | |
| 84 * Return the indexable object of this kind that exists in the given | |
| 85 * [context], in the source with the given [filePath], and at the given | |
| 86 * [offset]. | |
| 87 */ | |
| 88 IndexableObject decode(AnalysisContext context, String filePath, int offset); | |
| 89 | |
| 90 /** | |
| 91 * Return the object kind with the given [index]. | |
| 92 */ | |
| 93 static IndexableObjectKind getKind(int index) { | |
| 94 return _registry[index]; | |
| 95 } | |
| 96 | |
| 97 /** | |
| 98 * Register the given object [kind] so that it can be found by it's unique | |
| 99 * index. The index of the [kind] must not be changed after it is passed to | |
| 100 * this method. | |
| 101 */ | |
| 102 static void register(IndexableObjectKind kind) { | |
| 103 int index = kind.index; | |
| 104 if (_registry.containsKey(index)) { | |
| 105 throw new ArgumentError('duplicate index for kind: $index'); | |
| 106 } | |
| 107 _registry[index] = kind; | |
| 108 } | |
| 109 } | |
| 110 | |
| 111 /** | |
| 112 * An object used to add relationships to the index. | |
| 113 * | |
| 114 * Clients are expected to subtype this class when implementing plugins. | |
| 115 */ | |
| 116 abstract class IndexContributor { | |
| 117 /** | |
| 118 * Contribute relationships to the given index [store] as a result of | |
| 119 * analyzing the given [source] in the given [context]. | |
| 120 */ | |
| 121 void contributeTo(IndexStore store, AnalysisContext context, Source source); | |
| 122 } | |
| 123 | |
| 124 // A sketch of what the driver routine might look like: | |
| 125 // | |
| 126 //void buildIndexForSource(AnalysisContext context, Source source) { | |
| 127 // IndexStoreImpl store; | |
| 128 // store.aboutToIndex(context, source); | |
| 129 // try { | |
| 130 // for (IndexContributor contributor in contributors) { | |
| 131 // contributor.contributeTo(store, context, source); | |
| 132 // } | |
| 133 // } finally { | |
| 134 // store.doneIndexing(); | |
| 135 // } | |
| 136 //} | |
| 137 | |
| 138 /** | |
| 139 * An object that stores information about the relationships between locations | |
| 140 * in a code base. | |
| 141 * | |
| 142 * Clients are not expected to subtype this class. | |
| 143 */ | |
| 144 abstract class IndexStore { | |
| 145 /** | |
| 146 * Remove all of the information from the index. | |
| 147 */ | |
| 148 void clear(); | |
| 149 | |
| 150 /** | |
| 151 * Return a future that completes with the locations that have the given | |
| 152 * [relationship] with the given [indexable] object. | |
| 153 * | |
| 154 * For example, if the [indexable] object represents a function and the | |
| 155 * relationship is the `is-invoked-by` relationship, then the returned | |
| 156 * locations will be all of the places where the function is invoked. | |
| 157 */ | |
| 158 Future<List<Location>> getRelationships( | |
| 159 IndexableObject indexable, Relationship relationship); | |
| 160 | |
| 161 /** | |
| 162 * Record that the given [indexable] object and [location] have the given | |
| 163 * [relationship]. | |
| 164 * | |
| 165 * For example, if the [relationship] is the `is-invoked-by` relationship, | |
| 166 * then the [indexable] object would be the function being invoked and | |
| 167 * [location] would be the point at which it is invoked. Each indexable object | |
| 168 * can have the same relationship with multiple locations. In other words, if | |
| 169 * the following code were executed | |
| 170 * | |
| 171 * recordRelationship(indexable, isReferencedBy, location1); | |
| 172 * recordRelationship(indexable, isReferencedBy, location2); | |
| 173 * | |
| 174 * (where `location1 != location2`) then both relationships would be | |
| 175 * maintained in the index and the result of executing | |
| 176 * | |
| 177 * getRelationship(indexable, isReferencedBy); | |
| 178 * | |
| 179 * would be a list containing both `location1` and `location2`. | |
| 180 */ | |
| 181 void recordRelationship( | |
| 182 IndexableObject indexable, Relationship relationship, Location location); | |
| 183 | |
| 184 /** | |
| 185 * Remove from the index all of the information associated with the given | |
| 186 * [context]. | |
| 187 * | |
| 188 * This method should be invoked when the [context] is disposed. | |
| 189 */ | |
| 190 void removeContext(AnalysisContext context); | |
| 191 | |
| 192 /** | |
| 193 * Remove from the index all of the information associated with indexable | |
| 194 * objects or locations in the given [source]. This includes relationships | |
| 195 * between an indexable object in [source] and any other locations, as well as | |
| 196 * relationships between any other indexable objects and locations within | |
| 197 * the [source]. | |
| 198 * | |
| 199 * This method should be invoked when [source] is no longer part of the given | |
| 200 * [context]. | |
| 201 */ | |
| 202 void removeSource(AnalysisContext context, Source source); | |
| 203 | |
| 204 /** | |
| 205 * Remove from the index all of the information associated with indexable | |
| 206 * objects or locations in the given sources. This includes relationships | |
| 207 * between an indexable object in the given sources and any other locations, | |
| 208 * as well as relationships between any other indexable objects and a location | |
| 209 * within the given sources. | |
| 210 * | |
| 211 * This method should be invoked when the sources described by the given | |
| 212 * [container] are no longer part of the given [context]. | |
| 213 */ | |
| 214 void removeSources(AnalysisContext context, SourceContainer container); | |
| 215 } | |
| 216 | |
| 217 /** | |
| 218 * Instances of the class [Location] represent a location related to an | |
| 219 * indexable object. | |
| 220 * | |
| 221 * The location is expressed as an offset and length, but the offset is relative | |
| 222 * to the source containing the indexable object rather than the start of the | |
| 223 * indexable object within that source. | |
| 224 * | |
| 225 * Clients are not expected to subtype this class. | |
| 226 */ | |
| 227 abstract class Location { | |
| 228 /** | |
| 229 * An empty list of locations. | |
| 230 */ | |
| 231 static const List<Location> EMPTY_LIST = const <Location>[]; | |
| 232 | |
| 233 /** | |
| 234 * Return the indexable object containing this location. | |
| 235 */ | |
| 236 IndexableObject get indexable; | |
| 237 | |
| 238 /** | |
| 239 * Return `true` if this location is a qualified reference. | |
| 240 */ | |
| 241 bool get isQualified; | |
| 242 | |
| 243 /** | |
| 244 * Return `true` if this location is a resolved reference. | |
| 245 */ | |
| 246 bool get isResolved; | |
| 247 | |
| 248 /** | |
| 249 * Return the length of this location. | |
| 250 */ | |
| 251 int get length; | |
| 252 | |
| 253 /** | |
| 254 * Return the offset of this location within the source containing the | |
| 255 * indexable object. | |
| 256 */ | |
| 257 int get offset; | |
| 258 } | |
| 259 | |
| 260 /** | |
| 261 * A relationship between an indexable object and a location. Relationships are | |
| 262 * identified by a globally unique identifier. | |
| 263 * | |
| 264 * Clients are not expected to subtype this class. | |
| 265 */ | |
| 266 abstract class Relationship { | |
| 267 /** | |
| 268 * Return a relationship that has the given [identifier]. If the relationship | |
| 269 * has already been created, then it will be returned, otherwise a new | |
| 270 * relationship will be created | |
| 271 */ | |
| 272 factory Relationship(String identifier) => | |
| 273 RelationshipImpl.getRelationship(identifier); | |
| 274 } | |
| OLD | NEW |