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