OLD | NEW |
| (Empty) |
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 | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 library services.src.search.search_engine; | |
6 | |
7 import 'dart:async'; | |
8 | |
9 import 'package:analysis_services/index/index.dart'; | |
10 import 'package:analysis_services/search/search_engine.dart'; | |
11 import 'package:analyzer/src/generated/element.dart'; | |
12 import 'package:analyzer/src/generated/source.dart'; | |
13 | |
14 | |
15 /** | |
16 * A [SearchEngine] implementation. | |
17 */ | |
18 class SearchEngineImpl implements SearchEngine { | |
19 final Index _index; | |
20 | |
21 SearchEngineImpl(this._index); | |
22 | |
23 @override | |
24 Future<List<SearchMatch>> searchElementDeclarations(String name) { | |
25 NameElement element = new NameElement(name); | |
26 _Requestor requestor = new _Requestor(_index); | |
27 requestor.add( | |
28 element, | |
29 IndexConstants.NAME_IS_DEFINED_BY, | |
30 MatchKind.DECLARATION); | |
31 return requestor.merge(); | |
32 } | |
33 | |
34 @override | |
35 Future<List<SearchMatch>> searchMemberDeclarations(String name) { | |
36 return searchElementDeclarations(name).then((matches) { | |
37 return matches.where((match) { | |
38 return match.element.enclosingElement is ClassElement; | |
39 }).toList(); | |
40 }); | |
41 } | |
42 | |
43 @override | |
44 Future<List<SearchMatch>> searchMemberReferences(String name) { | |
45 NameElement element = new NameElement(name); | |
46 _Requestor requestor = new _Requestor(_index); | |
47 requestor.add(element, IndexConstants.IS_INVOKED_BY, MatchKind.INVOCATION); | |
48 requestor.add(element, IndexConstants.IS_READ_BY, MatchKind.READ); | |
49 requestor.add( | |
50 element, | |
51 IndexConstants.IS_READ_WRITTEN_BY, | |
52 MatchKind.READ_WRITE); | |
53 requestor.add(element, IndexConstants.IS_WRITTEN_BY, MatchKind.WRITE); | |
54 return requestor.merge(); | |
55 } | |
56 | |
57 @override | |
58 Future<List<SearchMatch>> searchReferences(Element element) { | |
59 if (element.kind == ElementKind.ANGULAR_COMPONENT || | |
60 element.kind == ElementKind.ANGULAR_CONTROLLER || | |
61 element.kind == ElementKind.ANGULAR_FORMATTER || | |
62 element.kind == ElementKind.ANGULAR_PROPERTY || | |
63 element.kind == ElementKind.ANGULAR_SCOPE_PROPERTY || | |
64 element.kind == ElementKind.ANGULAR_SELECTOR) { | |
65 return _searchReferences_Angular(element as AngularElement); | |
66 } else if (element.kind == ElementKind.CLASS) { | |
67 return _searchReferences_Class(element as ClassElement); | |
68 } else if (element.kind == ElementKind.COMPILATION_UNIT) { | |
69 return _searchReferences_CompilationUnit( | |
70 element as CompilationUnitElement); | |
71 } else if (element.kind == ElementKind.CONSTRUCTOR) { | |
72 return _searchReferences_Constructor(element as ConstructorElement); | |
73 } else if (element.kind == ElementKind.FIELD || | |
74 element.kind == ElementKind.TOP_LEVEL_VARIABLE) { | |
75 return _searchReferences_Field(element as PropertyInducingElement); | |
76 } else if (element.kind == ElementKind.FUNCTION) { | |
77 return _searchReferences_Function(element as FunctionElement); | |
78 } else if (element.kind == ElementKind.GETTER || | |
79 element.kind == ElementKind.SETTER) { | |
80 return _searchReferences_PropertyAccessor( | |
81 element as PropertyAccessorElement); | |
82 } else if (element.kind == ElementKind.IMPORT) { | |
83 return _searchReferences_Import(element as ImportElement); | |
84 } else if (element.kind == ElementKind.LIBRARY) { | |
85 return _searchReferences_Library(element as LibraryElement); | |
86 } else if (element.kind == ElementKind.LOCAL_VARIABLE) { | |
87 return _searchReferences_LocalVariable(element as LocalVariableElement); | |
88 } else if (element.kind == ElementKind.METHOD) { | |
89 return _searchReferences_Method(element as MethodElement); | |
90 } else if (element.kind == ElementKind.PARAMETER) { | |
91 return _searchReferences_Parameter(element as ParameterElement); | |
92 } else if (element.kind == ElementKind.FUNCTION_TYPE_ALIAS) { | |
93 return _searchReferences_FunctionTypeAlias( | |
94 element as FunctionTypeAliasElement); | |
95 } else if (element.kind == ElementKind.TYPE_PARAMETER) { | |
96 return _searchReferences_TypeParameter(element as TypeParameterElement); | |
97 } | |
98 return new Future.value(<SearchMatch>[]); | |
99 } | |
100 | |
101 @override | |
102 Future<List<SearchMatch>> searchSubtypes(ClassElement type) { | |
103 _Requestor requestor = new _Requestor(_index); | |
104 requestor.add(type, IndexConstants.IS_EXTENDED_BY, MatchKind.REFERENCE); | |
105 requestor.add(type, IndexConstants.IS_MIXED_IN_BY, MatchKind.REFERENCE); | |
106 requestor.add(type, IndexConstants.IS_IMPLEMENTED_BY, MatchKind.REFERENCE); | |
107 return requestor.merge(); | |
108 } | |
109 | |
110 @override | |
111 Future<List<SearchMatch>> searchTopLevelDeclarations(String pattern) { | |
112 UniverseElement universe = UniverseElement.INSTANCE; | |
113 _Requestor requestor = new _Requestor(_index); | |
114 requestor.add(universe, IndexConstants.DEFINES, MatchKind.DECLARATION); | |
115 RegExp regExp = new RegExp(pattern); | |
116 return requestor.merge().then((List<SearchMatch> matches) { | |
117 return matches.where((SearchMatch match) { | |
118 String name = match.element.displayName; | |
119 return regExp.hasMatch(name); | |
120 }).toList(); | |
121 }); | |
122 } | |
123 | |
124 Future<List<SearchMatch>> _searchReferences_Angular(AngularElement element) { | |
125 _Requestor requestor = new _Requestor(_index); | |
126 requestor.add( | |
127 element, | |
128 IndexConstants.ANGULAR_REFERENCE, | |
129 MatchKind.ANGULAR_REFERENCE); | |
130 requestor.add( | |
131 element, | |
132 IndexConstants.ANGULAR_CLOSING_TAG_REFERENCE, | |
133 MatchKind.ANGULAR_CLOSING_TAG_REFERENCE); | |
134 return requestor.merge(); | |
135 } | |
136 | |
137 Future<List<SearchMatch>> _searchReferences_Class(ClassElement clazz) { | |
138 _Requestor requestor = new _Requestor(_index); | |
139 requestor.add(clazz, IndexConstants.IS_REFERENCED_BY, MatchKind.REFERENCE); | |
140 return requestor.merge(); | |
141 } | |
142 | |
143 Future<List<SearchMatch>> | |
144 _searchReferences_CompilationUnit(CompilationUnitElement unit) { | |
145 // TODO(merge?) | |
146 _Requestor requestor = new _Requestor(_index); | |
147 requestor.add(unit, IndexConstants.IS_REFERENCED_BY, MatchKind.REFERENCE); | |
148 return requestor.merge(); | |
149 } | |
150 | |
151 Future<List<SearchMatch>> | |
152 _searchReferences_Constructor(ConstructorElement constructor) { | |
153 _Requestor requestor = new _Requestor(_index); | |
154 requestor.add( | |
155 constructor, | |
156 IndexConstants.NAME_IS_DEFINED_BY, | |
157 MatchKind.DECLARATION); | |
158 requestor.add( | |
159 constructor, | |
160 IndexConstants.IS_REFERENCED_BY, | |
161 MatchKind.REFERENCE); | |
162 return requestor.merge(); | |
163 } | |
164 | |
165 Future<List<SearchMatch>> | |
166 _searchReferences_Field(PropertyInducingElement field) { | |
167 PropertyAccessorElement getter = field.getter; | |
168 PropertyAccessorElement setter = field.setter; | |
169 _Requestor requestor = new _Requestor(_index); | |
170 // field itself | |
171 requestor.add(field, IndexConstants.IS_REFERENCED_BY, MatchKind.REFERENCE); | |
172 // getter | |
173 if (getter != null) { | |
174 requestor.add(getter, IndexConstants.IS_REFERENCED_BY, MatchKind.READ); | |
175 requestor.add(getter, IndexConstants.IS_INVOKED_BY, MatchKind.INVOCATION); | |
176 } | |
177 // setter | |
178 if (setter != null) { | |
179 requestor.add(setter, IndexConstants.IS_REFERENCED_BY, MatchKind.WRITE); | |
180 } | |
181 // done | |
182 return requestor.merge(); | |
183 } | |
184 | |
185 Future<List<SearchMatch>> | |
186 _searchReferences_Function(FunctionElement function) { | |
187 _Requestor requestor = new _Requestor(_index); | |
188 requestor.add( | |
189 function, | |
190 IndexConstants.IS_REFERENCED_BY, | |
191 MatchKind.REFERENCE); | |
192 requestor.add(function, IndexConstants.IS_INVOKED_BY, MatchKind.INVOCATION); | |
193 return requestor.merge(); | |
194 } | |
195 | |
196 Future<List<SearchMatch>> | |
197 _searchReferences_FunctionTypeAlias(FunctionTypeAliasElement alias) { | |
198 _Requestor requestor = new _Requestor(_index); | |
199 requestor.add(alias, IndexConstants.IS_REFERENCED_BY, MatchKind.REFERENCE); | |
200 return requestor.merge(); | |
201 } | |
202 | |
203 Future<List<SearchMatch>> _searchReferences_Import(ImportElement imp) { | |
204 _Requestor requestor = new _Requestor(_index); | |
205 requestor.add(imp, IndexConstants.IS_REFERENCED_BY, MatchKind.REFERENCE); | |
206 return requestor.merge(); | |
207 } | |
208 | |
209 Future<List<SearchMatch>> _searchReferences_Library(LibraryElement library) { | |
210 _Requestor requestor = new _Requestor(_index); | |
211 requestor.add( | |
212 library, | |
213 IndexConstants.IS_REFERENCED_BY, | |
214 MatchKind.REFERENCE); | |
215 return requestor.merge(); | |
216 } | |
217 | |
218 Future<List<SearchMatch>> | |
219 _searchReferences_LocalVariable(LocalVariableElement variable) { | |
220 _Requestor requestor = new _Requestor(_index); | |
221 requestor.add(variable, IndexConstants.IS_READ_BY, MatchKind.READ); | |
222 requestor.add( | |
223 variable, | |
224 IndexConstants.IS_READ_WRITTEN_BY, | |
225 MatchKind.READ_WRITE); | |
226 requestor.add(variable, IndexConstants.IS_WRITTEN_BY, MatchKind.WRITE); | |
227 requestor.add(variable, IndexConstants.IS_INVOKED_BY, MatchKind.INVOCATION); | |
228 return requestor.merge(); | |
229 } | |
230 | |
231 Future<List<SearchMatch>> _searchReferences_Method(MethodElement method) { | |
232 _Requestor requestor = new _Requestor(_index); | |
233 if (method is MethodMember) { | |
234 method = (method as MethodMember).baseElement; | |
235 } | |
236 requestor.add(method, IndexConstants.IS_REFERENCED_BY, MatchKind.REFERENCE); | |
237 requestor.add(method, IndexConstants.IS_INVOKED_BY, MatchKind.INVOCATION); | |
238 return requestor.merge(); | |
239 } | |
240 | |
241 Future<List<SearchMatch>> | |
242 _searchReferences_Parameter(ParameterElement parameter) { | |
243 _Requestor requestor = new _Requestor(_index); | |
244 requestor.add(parameter, IndexConstants.IS_READ_BY, MatchKind.READ); | |
245 requestor.add( | |
246 parameter, | |
247 IndexConstants.IS_READ_WRITTEN_BY, | |
248 MatchKind.READ_WRITE); | |
249 requestor.add(parameter, IndexConstants.IS_WRITTEN_BY, MatchKind.WRITE); | |
250 requestor.add( | |
251 parameter, | |
252 IndexConstants.IS_REFERENCED_BY, | |
253 MatchKind.REFERENCE); | |
254 requestor.add( | |
255 parameter, | |
256 IndexConstants.IS_INVOKED_BY, | |
257 MatchKind.INVOCATION); | |
258 return requestor.merge(); | |
259 } | |
260 | |
261 Future<List<SearchMatch>> | |
262 _searchReferences_PropertyAccessor(PropertyAccessorElement accessor) { | |
263 _Requestor requestor = new _Requestor(_index); | |
264 requestor.add( | |
265 accessor, | |
266 IndexConstants.IS_REFERENCED_BY, | |
267 MatchKind.REFERENCE); | |
268 return requestor.merge(); | |
269 } | |
270 | |
271 Future<List<SearchMatch>> | |
272 _searchReferences_TypeParameter(TypeParameterElement typeParameter) { | |
273 _Requestor requestor = new _Requestor(_index); | |
274 requestor.add( | |
275 typeParameter, | |
276 IndexConstants.IS_REFERENCED_BY, | |
277 MatchKind.REFERENCE); | |
278 return requestor.merge(); | |
279 } | |
280 } | |
281 | |
282 | |
283 class _Requestor { | |
284 final List<Future<List<SearchMatch>>> futures = <Future<List<SearchMatch>>>[]; | |
285 final Index index; | |
286 | |
287 _Requestor(this.index); | |
288 | |
289 void add(Element element, Relationship relationship, MatchKind kind) { | |
290 Future relationsFuture = index.getRelationships(element, relationship); | |
291 Future matchesFuture = relationsFuture.then((List<Location> locations) { | |
292 List<SearchMatch> matches = <SearchMatch>[]; | |
293 for (Location location in locations) { | |
294 matches.add( | |
295 new SearchMatch( | |
296 kind, | |
297 location.element, | |
298 new SourceRange(location.offset, location.length), | |
299 location.isResolved, | |
300 location.isQualified)); | |
301 } | |
302 return matches; | |
303 }); | |
304 futures.add(matchesFuture); | |
305 } | |
306 | |
307 Future<List<SearchMatch>> merge() { | |
308 return Future.wait(futures).then((List<List<SearchMatch>> matchesList) { | |
309 return matchesList.expand((matches) => matches).toList(); | |
310 }); | |
311 } | |
312 } | |
OLD | NEW |