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