| 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 // This code was auto-generated, is not intended to be edited, and is subject to | 5 // This code was auto-generated, is not intended to be edited, and is subject to |
| 6 // significant change. Please see the README file for more information. | 6 // significant change. Please see the README file for more information. |
| 7 | 7 |
| 8 library engine.index; | 8 library engine.index; |
| 9 | 9 |
| 10 import 'dart:collection' show Queue; | 10 import 'dart:collection' show Queue; |
| 11 import 'java_core.dart'; | 11 import 'java_core.dart'; |
| 12 import 'java_engine.dart'; | 12 import 'java_engine.dart'; |
| 13 import 'source.dart'; | 13 import 'source.dart'; |
| 14 import 'scanner.dart' show Token; | 14 import 'scanner.dart' show Token; |
| 15 import 'ast.dart'; | 15 import 'ast.dart'; |
| 16 import 'element.dart'; | 16 import 'element.dart'; |
| 17 import 'resolver.dart' show Namespace, NamespaceBuilder; | 17 import 'resolver.dart' show Namespace, NamespaceBuilder; |
| 18 import 'engine.dart'; | 18 import 'engine.dart'; |
| 19 import 'html.dart' as ht; | 19 import 'html.dart' as ht; |
| 20 | 20 |
| 21 /** | 21 /** |
| 22 * Instances of the [RemoveSourceOperation] implement an operation that removes
from the index | 22 * Implementation of [UniverseElement]. |
| 23 * any data based on the content of a specified source. | 23 */ |
| 24 */ | 24 class UniverseElementImpl extends ElementImpl implements UniverseElement { |
| 25 class RemoveSourceOperation implements IndexOperation { | 25 static UniverseElementImpl INSTANCE = new UniverseElementImpl(); |
| 26 |
| 27 UniverseElementImpl() : super("--universe--", -1); |
| 28 |
| 29 @override |
| 30 accept(ElementVisitor visitor) => null; |
| 31 |
| 32 @override |
| 33 ElementKind get kind => ElementKind.UNIVERSE; |
| 34 } |
| 35 |
| 36 /** |
| 37 * Container of information computed by the index - relationships between elemen
ts. |
| 38 */ |
| 39 abstract class IndexStore { |
| 40 /** |
| 41 * Notifies the index store that we are going to index the unit with the given
element. |
| 42 * |
| 43 * If the unit is a part of a library, then all its locations are removed. If
it is a defining |
| 44 * compilation unit of a library, then index store also checks if some previou
sly indexed parts of |
| 45 * the library are not parts of the library anymore, and clears their informat
ion. |
| 46 * |
| 47 * @param the [AnalysisContext] in which unit being indexed |
| 48 * @param unitElement the element of the unit being indexed |
| 49 * @return `true` the given [AnalysisContext] is active, or `false` if it was |
| 50 * removed before, so no any unit may be indexed with it |
| 51 */ |
| 52 bool aboutToIndexDart(AnalysisContext context, CompilationUnitElement unitElem
ent); |
| 53 |
| 54 /** |
| 55 * Notifies the index store that we are going to index the given [HtmlElement]
. |
| 56 * |
| 57 * @param the [AnalysisContext] in which unit being indexed |
| 58 * @param htmlElement the [HtmlElement] being indexed |
| 59 * @return `true` the given [AnalysisContext] is active, or `false` if it was |
| 60 * removed before, so no any unit may be indexed with it |
| 61 */ |
| 62 bool aboutToIndexHtml(AnalysisContext context, HtmlElement htmlElement); |
| 63 |
| 64 /** |
| 65 * Return the locations of the elements that have the given relationship with
the given element. |
| 66 * For example, if the element represents a method and the relationship is the
is-referenced-by |
| 67 * relationship, then the returned locations will be all of the places where t
he method is |
| 68 * invoked. |
| 69 * |
| 70 * @param element the the element that has the relationship with the locations
to be returned |
| 71 * @param relationship the [Relationship] between the given element and the lo
cations to be |
| 72 * returned |
| 73 * @return the locations that have the given relationship with the given eleme
nt |
| 74 */ |
| 75 List<Location> getRelationships(Element element, Relationship relationship); |
| 76 |
| 77 /** |
| 78 * Answer index statistics. |
| 79 */ |
| 80 String get statistics; |
| 81 |
| 82 /** |
| 83 * Record that the given element and location have the given relationship. For
example, if the |
| 84 * relationship is the is-referenced-by relationship, then the element would b
e the element being |
| 85 * referenced and the location would be the point at which it is referenced. E
ach element can have |
| 86 * the same relationship with multiple locations. In other words, if the follo
wing code were |
| 87 * executed |
| 88 * |
| 89 * <pre> |
| 90 * recordRelationship(element, isReferencedBy, location1); |
| 91 * recordRelationship(element, isReferencedBy, location2); |
| 92 * </pre> |
| 93 * |
| 94 * then both relationships would be maintained in the index and the result of
executing |
| 95 * |
| 96 * <pre> |
| 97 * getRelationship(element, isReferencedBy); |
| 98 * </pre> |
| 99 * |
| 100 * would be an array containing both <code>location1</code> and <code>location
2</code>. |
| 101 * |
| 102 * @param element the element that is related to the location |
| 103 * @param relationship the [Relationship] between the element and the location |
| 104 * @param location the [Location] where relationship happens |
| 105 */ |
| 106 void recordRelationship(Element element, Relationship relationship, Location l
ocation); |
| 107 |
| 108 /** |
| 109 * Remove from the index all of the information associated with [AnalysisConte
xt]. |
| 110 * |
| 111 * This method should be invoked when a context is disposed. |
| 112 * |
| 113 * @param the [AnalysisContext] being removed |
| 114 */ |
| 115 void removeContext(AnalysisContext context); |
| 116 |
| 117 /** |
| 118 * Remove from the index all of the information associated with elements or lo
cations in the given |
| 119 * source. This includes relationships between an element in the given source
and any other |
| 120 * locations, relationships between any other elements and a location within t
he given source. |
| 121 * |
| 122 * This method should be invoked when a source is no longer part of the code b
ase. |
| 123 * |
| 124 * @param the [AnalysisContext] in which [Source] being removed |
| 125 * @param source the source being removed |
| 126 */ |
| 127 void removeSource(AnalysisContext context, Source source); |
| 128 |
| 129 /** |
| 130 * Remove from the index all of the information associated with elements or lo
cations in the given |
| 131 * sources. This includes relationships between an element in the given source
s and any other |
| 132 * locations, relationships between any other elements and a location within t
he given sources. |
| 133 * |
| 134 * This method should be invoked when multiple sources are no longer part of t
he code base. |
| 135 * |
| 136 * @param the [AnalysisContext] in which [Source]s being removed |
| 137 * @param container the [SourceContainer] holding the sources being removed |
| 138 */ |
| 139 void removeSources(AnalysisContext context, SourceContainer container); |
| 140 } |
| 141 |
| 142 /** |
| 143 * Visits resolved [HtmlUnit] and adds relationships into [IndexStore]. |
| 144 */ |
| 145 class AngularHtmlIndexContributor extends ExpressionVisitor { |
| 146 /** |
| 147 * The [IndexStore] to record relations into. |
| 148 */ |
| 149 final IndexStore _store; |
| 150 |
| 151 /** |
| 152 * The index contributor used to index Dart [Expression]s. |
| 153 */ |
| 154 IndexContributor _indexContributor; |
| 155 |
| 156 HtmlElement _htmlUnitElement; |
| 157 |
| 158 /** |
| 159 * Initialize a newly created Angular HTML index contributor. |
| 160 * |
| 161 * @param store the [IndexStore] to record relations into. |
| 162 */ |
| 163 AngularHtmlIndexContributor(this._store) { |
| 164 _indexContributor = new IndexContributor_AngularHtmlIndexContributor(_store,
this); |
| 165 } |
| 166 |
| 167 @override |
| 168 void visitExpression(Expression expression) { |
| 169 // Formatter |
| 170 if (expression is SimpleIdentifier) { |
| 171 SimpleIdentifier identifier = expression; |
| 172 Element element = identifier.bestElement; |
| 173 if (element is AngularElement) { |
| 174 _store.recordRelationship(element, IndexConstants.ANGULAR_REFERENCE, _cr
eateLocationForIdentifier(identifier)); |
| 175 return; |
| 176 } |
| 177 } |
| 178 // index as a normal Dart expression |
| 179 expression.accept(_indexContributor); |
| 180 } |
| 181 |
| 182 @override |
| 183 Object visitHtmlUnit(ht.HtmlUnit node) { |
| 184 _htmlUnitElement = node.element; |
| 185 CompilationUnitElement dartUnitElement = _htmlUnitElement.angularCompilation
Unit; |
| 186 _indexContributor.enterScope(dartUnitElement); |
| 187 return super.visitHtmlUnit(node); |
| 188 } |
| 189 |
| 190 @override |
| 191 Object visitXmlAttributeNode(ht.XmlAttributeNode node) { |
| 192 Element element = node.element; |
| 193 if (element != null) { |
| 194 ht.Token nameToken = node.nameToken; |
| 195 Location location = _createLocationForToken(nameToken); |
| 196 _store.recordRelationship(element, IndexConstants.ANGULAR_REFERENCE, locat
ion); |
| 197 } |
| 198 return super.visitXmlAttributeNode(node); |
| 199 } |
| 200 |
| 201 @override |
| 202 Object visitXmlTagNode(ht.XmlTagNode node) { |
| 203 Element element = node.element; |
| 204 if (element != null) { |
| 205 // tag |
| 206 { |
| 207 ht.Token tagToken = node.tagToken; |
| 208 Location location = _createLocationForToken(tagToken); |
| 209 _store.recordRelationship(element, IndexConstants.ANGULAR_REFERENCE, loc
ation); |
| 210 } |
| 211 // maybe add closing tag range |
| 212 ht.Token closingTag = node.closingTag; |
| 213 if (closingTag != null) { |
| 214 Location location = _createLocationForToken(closingTag); |
| 215 _store.recordRelationship(element, IndexConstants.ANGULAR_CLOSING_TAG_RE
FERENCE, location); |
| 216 } |
| 217 } |
| 218 return super.visitXmlTagNode(node); |
| 219 } |
| 220 |
| 221 Location _createLocationForIdentifier(SimpleIdentifier identifier) => new Loca
tion(_htmlUnitElement, identifier.offset, identifier.length); |
| 222 |
| 223 Location _createLocationForToken(ht.Token token) => new Location(_htmlUnitElem
ent, token.offset, token.length); |
| 224 } |
| 225 |
| 226 class IndexContributor_AngularHtmlIndexContributor extends IndexContributor { |
| 227 final AngularHtmlIndexContributor AngularHtmlIndexContributor_this; |
| 228 |
| 229 IndexContributor_AngularHtmlIndexContributor(IndexStore arg0, this.AngularHtml
IndexContributor_this) : super(arg0); |
| 230 |
| 231 @override |
| 232 Element peekElement() => AngularHtmlIndexContributor_this._htmlUnitElement; |
| 233 |
| 234 @override |
| 235 void recordRelationship(Element element, Relationship relationship, Location l
ocation) { |
| 236 AngularElement angularElement = AngularHtmlUnitResolver.getAngularElement(el
ement); |
| 237 if (angularElement != null) { |
| 238 element = angularElement; |
| 239 relationship = IndexConstants.ANGULAR_REFERENCE; |
| 240 } |
| 241 super.recordRelationship(element, relationship, location); |
| 242 } |
| 243 } |
| 244 |
| 245 /** |
| 246 * Recursively visits [HtmlUnit] and every embedded [Expression]. |
| 247 */ |
| 248 abstract class ExpressionVisitor extends ht.RecursiveXmlVisitor<Object> { |
| 249 /** |
| 250 * Visits the given [Expression]s embedded into tag or attribute. |
| 251 * |
| 252 * @param expression the [Expression] to visit, not `null` |
| 253 */ |
| 254 void visitExpression(Expression expression); |
| 255 |
| 256 @override |
| 257 Object visitXmlAttributeNode(ht.XmlAttributeNode node) { |
| 258 _visitExpressions(node.expressions); |
| 259 return super.visitXmlAttributeNode(node); |
| 260 } |
| 261 |
| 262 @override |
| 263 Object visitXmlTagNode(ht.XmlTagNode node) { |
| 264 _visitExpressions(node.expressions); |
| 265 return super.visitXmlTagNode(node); |
| 266 } |
| 267 |
| 268 /** |
| 269 * Visits [Expression]s of the given [XmlExpression]s. |
| 270 */ |
| 271 void _visitExpressions(List<ht.XmlExpression> expressions) { |
| 272 for (ht.XmlExpression xmlExpression in expressions) { |
| 273 if (xmlExpression is AngularXmlExpression) { |
| 274 AngularXmlExpression angularXmlExpression = xmlExpression; |
| 275 List<Expression> dartExpressions = angularXmlExpression.expression.expre
ssions; |
| 276 for (Expression dartExpression in dartExpressions) { |
| 277 visitExpression(dartExpression); |
| 278 } |
| 279 } |
| 280 if (xmlExpression is ht.RawXmlExpression) { |
| 281 ht.RawXmlExpression rawXmlExpression = xmlExpression; |
| 282 visitExpression(rawXmlExpression.expression); |
| 283 } |
| 284 } |
| 285 } |
| 286 } |
| 287 |
| 288 /** |
| 289 * Instances of the [IndexHtmlUnitOperation] implement an operation that adds da
ta to the |
| 290 * index based on the resolved [HtmlUnit]. |
| 291 */ |
| 292 class IndexHtmlUnitOperation implements IndexOperation { |
| 26 /** | 293 /** |
| 27 * The index store against which this operation is being run. | 294 * The index store against which this operation is being run. |
| 28 */ | 295 */ |
| 29 final IndexStore _indexStore; | 296 final IndexStore _indexStore; |
| 30 | 297 |
| 31 /** | 298 /** |
| 32 * The context in which source being removed. | 299 * The context in which [HtmlUnit] was resolved. |
| 33 */ | 300 */ |
| 34 final AnalysisContext _context; | 301 final AnalysisContext _context; |
| 35 | 302 |
| 36 /** | 303 /** |
| 37 * The source being removed. | 304 * The [HtmlUnit] being indexed. |
| 38 */ | 305 */ |
| 39 final Source source; | 306 final ht.HtmlUnit unit; |
| 307 |
| 308 /** |
| 309 * The element of the [HtmlUnit] being indexed. |
| 310 */ |
| 311 HtmlElement _htmlElement; |
| 312 |
| 313 /** |
| 314 * The source being indexed. |
| 315 */ |
| 316 Source _source; |
| 317 |
| 318 /** |
| 319 * Initialize a newly created operation that will index the specified [HtmlUni
t]. |
| 320 * |
| 321 * @param indexStore the index store against which this operation is being run |
| 322 * @param context the context in which [HtmlUnit] was resolved |
| 323 * @param unit the fully resolved [HtmlUnit] |
| 324 */ |
| 325 IndexHtmlUnitOperation(this._indexStore, this._context, this.unit) { |
| 326 this._htmlElement = unit.element; |
| 327 this._source = _htmlElement.source; |
| 328 } |
| 329 |
| 330 /** |
| 331 * @return the [Source] to be indexed. |
| 332 */ |
| 333 Source get source => _source; |
| 334 |
| 335 @override |
| 336 bool get isQuery => false; |
| 337 |
| 338 @override |
| 339 void performOperation() { |
| 340 try { |
| 341 bool mayIndex = _indexStore.aboutToIndexHtml(_context, _htmlElement); |
| 342 if (!mayIndex) { |
| 343 return; |
| 344 } |
| 345 AngularHtmlIndexContributor contributor = new AngularHtmlIndexContributor(
_indexStore); |
| 346 unit.accept(contributor); |
| 347 } catch (exception) { |
| 348 AnalysisEngine.instance.logger.logError2("Could not index ${unit.element.l
ocation}", exception); |
| 349 } |
| 350 } |
| 351 |
| 352 @override |
| 353 bool removeWhenSourceRemoved(Source source) => this._source == source; |
| 354 |
| 355 @override |
| 356 String toString() => "IndexHtmlUnitOperation(${_source.fullName})"; |
| 357 } |
| 358 |
| 359 /** |
| 360 * Visits resolved [CompilationUnit] and adds Angular specific relationships int
o |
| 361 * [IndexStore]. |
| 362 */ |
| 363 class AngularDartIndexContributor extends GeneralizingAstVisitor<Object> { |
| 364 final IndexStore _store; |
| 365 |
| 366 AngularDartIndexContributor(this._store); |
| 367 |
| 368 @override |
| 369 Object visitClassDeclaration(ClassDeclaration node) { |
| 370 ClassElement classElement = node.element; |
| 371 if (classElement != null) { |
| 372 List<ToolkitObjectElement> toolkitObjects = classElement.toolkitObjects; |
| 373 for (ToolkitObjectElement object in toolkitObjects) { |
| 374 if (object is AngularComponentElement) { |
| 375 _indexComponent(object); |
| 376 } |
| 377 if (object is AngularDecoratorElement) { |
| 378 AngularDecoratorElement directive = object; |
| 379 _indexDirective(directive); |
| 380 } |
| 381 } |
| 382 } |
| 383 // stop visiting |
| 384 return null; |
| 385 } |
| 386 |
| 387 @override |
| 388 Object visitCompilationUnitMember(CompilationUnitMember node) => null; |
| 389 |
| 390 void _indexComponent(AngularComponentElement component) { |
| 391 _indexProperties(component.properties); |
| 392 } |
| 393 |
| 394 void _indexDirective(AngularDecoratorElement directive) { |
| 395 _indexProperties(directive.properties); |
| 396 } |
| 397 |
| 398 /** |
| 399 * Index [FieldElement] references from [AngularPropertyElement]s. |
| 400 */ |
| 401 void _indexProperties(List<AngularPropertyElement> properties) { |
| 402 for (AngularPropertyElement property in properties) { |
| 403 FieldElement field = property.field; |
| 404 if (field != null) { |
| 405 int offset = property.fieldNameOffset; |
| 406 if (offset == -1) { |
| 407 continue; |
| 408 } |
| 409 int length = field.name.length; |
| 410 Location location = new Location(property, offset, length); |
| 411 // getter reference |
| 412 if (property.propertyKind.callsGetter()) { |
| 413 PropertyAccessorElement getter = field.getter; |
| 414 if (getter != null) { |
| 415 _store.recordRelationship(getter, IndexConstants.IS_REFERENCED_BY_QU
ALIFIED, location); |
| 416 } |
| 417 } |
| 418 // setter reference |
| 419 if (property.propertyKind.callsSetter()) { |
| 420 PropertyAccessorElement setter = field.setter; |
| 421 if (setter != null) { |
| 422 _store.recordRelationship(setter, IndexConstants.IS_REFERENCED_BY_QU
ALIFIED, location); |
| 423 } |
| 424 } |
| 425 } |
| 426 } |
| 427 } |
| 428 } |
| 429 |
| 430 /** |
| 431 * Special [Element] which is used to index references to the name without speci
fying concrete |
| 432 * kind of this name - field, method or something else. |
| 433 */ |
| 434 class NameElementImpl extends ElementImpl { |
| 435 NameElementImpl(String name) : super("name:${name}", -1); |
| 436 |
| 437 @override |
| 438 accept(ElementVisitor visitor) => null; |
| 439 |
| 440 @override |
| 441 ElementKind get kind => ElementKind.NAME; |
| 442 } |
| 443 |
| 444 /** |
| 445 * The interface <code>RelationshipCallback</code> defines the behavior of objec
ts that are invoked |
| 446 * with the results of a query about a given relationship. |
| 447 */ |
| 448 abstract class RelationshipCallback { |
| 449 /** |
| 450 * This method is invoked when the locations that have a specified relationshi
p with a specified |
| 451 * element are available. For example, if the element is a field and the relat
ionship is the |
| 452 * is-referenced-by relationship, then this method will be invoked with each l
ocation at which the |
| 453 * field is referenced. |
| 454 * |
| 455 * @param element the [Element] that has the relationship with the locations |
| 456 * @param relationship the relationship between the given element and the loca
tions |
| 457 * @param locations the locations that were found |
| 458 */ |
| 459 void hasRelationships(Element element, Relationship relationship, List<Locatio
n> locations); |
| 460 } |
| 461 |
| 462 /** |
| 463 * Instances of the [RemoveSourcesOperation] implement an operation that removes
from the |
| 464 * index any data based on the content of source belonging to a [SourceContainer
]. |
| 465 */ |
| 466 class RemoveSourcesOperation implements IndexOperation { |
| 467 /** |
| 468 * The index store against which this operation is being run. |
| 469 */ |
| 470 final IndexStore _indexStore; |
| 471 |
| 472 /** |
| 473 * The context to remove container. |
| 474 */ |
| 475 final AnalysisContext _context; |
| 476 |
| 477 /** |
| 478 * The source container to remove. |
| 479 */ |
| 480 final SourceContainer container; |
| 40 | 481 |
| 41 /** | 482 /** |
| 42 * Initialize a newly created operation that will remove the specified resourc
e. | 483 * Initialize a newly created operation that will remove the specified resourc
e. |
| 43 * | 484 * |
| 44 * @param indexStore the index store against which this operation is being run | 485 * @param indexStore the index store against which this operation is being run |
| 45 * @param context the [AnalysisContext] to remove source in | 486 * @param context the [AnalysisContext] to remove container in |
| 46 * @param source the [Source] to remove from index | 487 * @param container the [SourceContainer] to remove from index |
| 47 */ | 488 */ |
| 48 RemoveSourceOperation(this._indexStore, this._context, this.source); | 489 RemoveSourcesOperation(this._indexStore, this._context, this.container); |
| 49 | 490 |
| 50 @override | 491 @override |
| 51 bool get isQuery => false; | 492 bool get isQuery => false; |
| 52 | 493 |
| 53 @override | 494 @override |
| 54 void performOperation() { | 495 void performOperation() { |
| 55 _indexStore.removeSource(_context, source); | 496 _indexStore.removeSources(_context, container); |
| 56 } | 497 } |
| 57 | 498 |
| 58 @override | 499 @override |
| 59 bool removeWhenSourceRemoved(Source source) => false; | 500 bool removeWhenSourceRemoved(Source source) => false; |
| 60 | 501 |
| 61 @override | 502 @override |
| 62 String toString() => "RemoveSource(${source.fullName})"; | 503 String toString() => "RemoveSources(${container})"; |
| 63 } | 504 } |
| 64 | 505 |
| 65 /** | 506 /** |
| 66 * The interface [IndexOperation] defines the behavior of objects used to perfor
m operations | 507 * Instances of the [IndexUnitOperation] implement an operation that adds data t
o the index |
| 67 * on an index. | 508 * based on the resolved [CompilationUnit]. |
| 68 */ | 509 */ |
| 69 abstract class IndexOperation { | 510 class IndexUnitOperation implements IndexOperation { |
| 70 /** | 511 /** |
| 71 * Return `true` if this operation returns information from the index. | 512 * The index store against which this operation is being run. |
| 72 * | 513 */ |
| 73 * @return `true` if this operation returns information from the index | 514 final IndexStore _indexStore; |
| 74 */ | 515 |
| 75 bool get isQuery; | 516 /** |
| 76 | 517 * The context in which compilation unit was resolved. |
| 77 /** | 518 */ |
| 78 * Perform the operation implemented by this operation. | 519 final AnalysisContext _context; |
| 79 */ | 520 |
| 80 void performOperation(); | 521 /** |
| 81 | 522 * The compilation unit being indexed. |
| 82 /** | 523 */ |
| 83 * Return `true` if this operation should be removed from the operation queue
when the | 524 final CompilationUnit unit; |
| 84 * given resource has been removed. | 525 |
| 85 * | 526 /** |
| 86 * @param source the [Source] that has been removed | 527 * The element of the compilation unit being indexed. |
| 87 * @return `true` if this operation should be removed from the operation queue
as a | 528 */ |
| 88 * result of removing the resource | 529 CompilationUnitElement _unitElement; |
| 89 */ | 530 |
| 90 bool removeWhenSourceRemoved(Source source); | 531 /** |
| 532 * The source being indexed. |
| 533 */ |
| 534 Source _source; |
| 535 |
| 536 /** |
| 537 * Initialize a newly created operation that will index the specified unit. |
| 538 * |
| 539 * @param indexStore the index store against which this operation is being run |
| 540 * @param context the context in which compilation unit was resolved |
| 541 * @param unit the fully resolved AST structure |
| 542 */ |
| 543 IndexUnitOperation(this._indexStore, this._context, this.unit) { |
| 544 this._unitElement = unit.element; |
| 545 this._source = _unitElement.source; |
| 546 } |
| 547 |
| 548 /** |
| 549 * @return the [Source] to be indexed. |
| 550 */ |
| 551 Source get source => _source; |
| 552 |
| 553 @override |
| 554 bool get isQuery => false; |
| 555 |
| 556 @override |
| 557 void performOperation() { |
| 558 try { |
| 559 bool mayIndex = _indexStore.aboutToIndexDart(_context, _unitElement); |
| 560 if (!mayIndex) { |
| 561 return; |
| 562 } |
| 563 unit.accept(new IndexContributor(_indexStore)); |
| 564 unit.accept(new AngularDartIndexContributor(_indexStore)); |
| 565 } catch (exception) { |
| 566 AnalysisEngine.instance.logger.logError2("Could not index ${unit.element.l
ocation}", exception); |
| 567 } |
| 568 } |
| 569 |
| 570 @override |
| 571 bool removeWhenSourceRemoved(Source source) => this._source == source; |
| 572 |
| 573 @override |
| 574 String toString() => "IndexUnitOperation(${_source.fullName})"; |
| 91 } | 575 } |
| 92 | 576 |
| 93 /** | 577 /** |
| 94 * [IndexStore] which keeps full index in memory. | 578 * [IndexStore] which keeps full index in memory. |
| 95 */ | 579 */ |
| 96 class MemoryIndexStoreImpl implements MemoryIndexStore { | 580 class MemoryIndexStoreImpl implements MemoryIndexStore { |
| 97 /** | 581 /** |
| 98 * When logging is on, [AnalysisEngine] actually creates | 582 * When logging is on, [AnalysisEngine] actually creates |
| 99 * [InstrumentedAnalysisContextImpl], which wraps [AnalysisContextImpl] used t
o create | 583 * [InstrumentedAnalysisContextImpl], which wraps [AnalysisContextImpl] used t
o create |
| 100 * actual [Element]s. So, in index we have to unwrap [InstrumentedAnalysisCont
extImpl] | 584 * actual [Element]s. So, in index we have to unwrap [InstrumentedAnalysisCont
extImpl] |
| (...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 577 } | 1061 } |
| 578 | 1062 |
| 579 @override | 1063 @override |
| 580 int get hashCode => JavaArrays.makeHashCode([_librarySource, _unitSource]); | 1064 int get hashCode => JavaArrays.makeHashCode([_librarySource, _unitSource]); |
| 581 | 1065 |
| 582 @override | 1066 @override |
| 583 String toString() => "${_librarySource} ${_unitSource}"; | 1067 String toString() => "${_librarySource} ${_unitSource}"; |
| 584 } | 1068 } |
| 585 | 1069 |
| 586 /** | 1070 /** |
| 587 * Instances of the [IndexUnitOperation] implement an operation that adds data t
o the index | |
| 588 * based on the resolved [CompilationUnit]. | |
| 589 */ | |
| 590 class IndexUnitOperation implements IndexOperation { | |
| 591 /** | |
| 592 * The index store against which this operation is being run. | |
| 593 */ | |
| 594 final IndexStore _indexStore; | |
| 595 | |
| 596 /** | |
| 597 * The context in which compilation unit was resolved. | |
| 598 */ | |
| 599 final AnalysisContext _context; | |
| 600 | |
| 601 /** | |
| 602 * The compilation unit being indexed. | |
| 603 */ | |
| 604 final CompilationUnit unit; | |
| 605 | |
| 606 /** | |
| 607 * The element of the compilation unit being indexed. | |
| 608 */ | |
| 609 CompilationUnitElement _unitElement; | |
| 610 | |
| 611 /** | |
| 612 * The source being indexed. | |
| 613 */ | |
| 614 Source _source; | |
| 615 | |
| 616 /** | |
| 617 * Initialize a newly created operation that will index the specified unit. | |
| 618 * | |
| 619 * @param indexStore the index store against which this operation is being run | |
| 620 * @param context the context in which compilation unit was resolved | |
| 621 * @param unit the fully resolved AST structure | |
| 622 */ | |
| 623 IndexUnitOperation(this._indexStore, this._context, this.unit) { | |
| 624 this._unitElement = unit.element; | |
| 625 this._source = _unitElement.source; | |
| 626 } | |
| 627 | |
| 628 /** | |
| 629 * @return the [Source] to be indexed. | |
| 630 */ | |
| 631 Source get source => _source; | |
| 632 | |
| 633 @override | |
| 634 bool get isQuery => false; | |
| 635 | |
| 636 @override | |
| 637 void performOperation() { | |
| 638 try { | |
| 639 bool mayIndex = _indexStore.aboutToIndexDart(_context, _unitElement); | |
| 640 if (!mayIndex) { | |
| 641 return; | |
| 642 } | |
| 643 unit.accept(new IndexContributor(_indexStore)); | |
| 644 unit.accept(new AngularDartIndexContributor(_indexStore)); | |
| 645 } catch (exception) { | |
| 646 AnalysisEngine.instance.logger.logError2("Could not index ${unit.element.l
ocation}", exception); | |
| 647 } | |
| 648 } | |
| 649 | |
| 650 @override | |
| 651 bool removeWhenSourceRemoved(Source source) => this._source == source; | |
| 652 | |
| 653 @override | |
| 654 String toString() => "IndexUnitOperation(${_source.fullName})"; | |
| 655 } | |
| 656 | |
| 657 /** | |
| 658 * Recursively visits [HtmlUnit] and every embedded [Expression]. | |
| 659 */ | |
| 660 abstract class ExpressionVisitor extends ht.RecursiveXmlVisitor<Object> { | |
| 661 /** | |
| 662 * Visits the given [Expression]s embedded into tag or attribute. | |
| 663 * | |
| 664 * @param expression the [Expression] to visit, not `null` | |
| 665 */ | |
| 666 void visitExpression(Expression expression); | |
| 667 | |
| 668 @override | |
| 669 Object visitXmlAttributeNode(ht.XmlAttributeNode node) { | |
| 670 _visitExpressions(node.expressions); | |
| 671 return super.visitXmlAttributeNode(node); | |
| 672 } | |
| 673 | |
| 674 @override | |
| 675 Object visitXmlTagNode(ht.XmlTagNode node) { | |
| 676 _visitExpressions(node.expressions); | |
| 677 return super.visitXmlTagNode(node); | |
| 678 } | |
| 679 | |
| 680 /** | |
| 681 * Visits [Expression]s of the given [XmlExpression]s. | |
| 682 */ | |
| 683 void _visitExpressions(List<ht.XmlExpression> expressions) { | |
| 684 for (ht.XmlExpression xmlExpression in expressions) { | |
| 685 if (xmlExpression is AngularXmlExpression) { | |
| 686 AngularXmlExpression angularXmlExpression = xmlExpression; | |
| 687 List<Expression> dartExpressions = angularXmlExpression.expression.expre
ssions; | |
| 688 for (Expression dartExpression in dartExpressions) { | |
| 689 visitExpression(dartExpression); | |
| 690 } | |
| 691 } | |
| 692 if (xmlExpression is ht.RawXmlExpression) { | |
| 693 ht.RawXmlExpression rawXmlExpression = xmlExpression; | |
| 694 visitExpression(rawXmlExpression.expression); | |
| 695 } | |
| 696 } | |
| 697 } | |
| 698 } | |
| 699 | |
| 700 /** | |
| 701 * Relationship between an element and a location. Relationships are identified
by a globally unique | |
| 702 * identifier. | |
| 703 */ | |
| 704 class Relationship { | |
| 705 /** | |
| 706 * The unique identifier for this relationship. | |
| 707 */ | |
| 708 final String _uniqueId; | |
| 709 | |
| 710 /** | |
| 711 * A table mapping relationship identifiers to relationships. | |
| 712 */ | |
| 713 static Map<String, Relationship> _RelationshipMap = {}; | |
| 714 | |
| 715 /** | |
| 716 * Return the relationship with the given unique identifier. | |
| 717 * | |
| 718 * @param uniqueId the unique identifier for the relationship | |
| 719 * @return the relationship with the given unique identifier | |
| 720 */ | |
| 721 static Relationship getRelationship(String uniqueId) { | |
| 722 Relationship relationship = _RelationshipMap[uniqueId]; | |
| 723 if (relationship == null) { | |
| 724 relationship = new Relationship(uniqueId); | |
| 725 _RelationshipMap[uniqueId] = relationship; | |
| 726 } | |
| 727 return relationship; | |
| 728 } | |
| 729 | |
| 730 /** | |
| 731 * @return all registered [Relationship]s. | |
| 732 */ | |
| 733 static Iterable<Relationship> values() => _RelationshipMap.values; | |
| 734 | |
| 735 /** | |
| 736 * Initialize a newly created relationship to have the given unique identifier
. | |
| 737 * | |
| 738 * @param uniqueId the unique identifier for this relationship | |
| 739 */ | |
| 740 Relationship(this._uniqueId); | |
| 741 | |
| 742 /** | |
| 743 * Return the unique identifier for this relationship. | |
| 744 * | |
| 745 * @return the unique identifier for this relationship | |
| 746 */ | |
| 747 String get identifier => _uniqueId; | |
| 748 | |
| 749 @override | |
| 750 String toString() => _uniqueId; | |
| 751 } | |
| 752 | |
| 753 /** | |
| 754 * Instances of the [RemoveSourcesOperation] implement an operation that removes
from the | |
| 755 * index any data based on the content of source belonging to a [SourceContainer
]. | |
| 756 */ | |
| 757 class RemoveSourcesOperation implements IndexOperation { | |
| 758 /** | |
| 759 * The index store against which this operation is being run. | |
| 760 */ | |
| 761 final IndexStore _indexStore; | |
| 762 | |
| 763 /** | |
| 764 * The context to remove container. | |
| 765 */ | |
| 766 final AnalysisContext _context; | |
| 767 | |
| 768 /** | |
| 769 * The source container to remove. | |
| 770 */ | |
| 771 final SourceContainer container; | |
| 772 | |
| 773 /** | |
| 774 * Initialize a newly created operation that will remove the specified resourc
e. | |
| 775 * | |
| 776 * @param indexStore the index store against which this operation is being run | |
| 777 * @param context the [AnalysisContext] to remove container in | |
| 778 * @param container the [SourceContainer] to remove from index | |
| 779 */ | |
| 780 RemoveSourcesOperation(this._indexStore, this._context, this.container); | |
| 781 | |
| 782 @override | |
| 783 bool get isQuery => false; | |
| 784 | |
| 785 @override | |
| 786 void performOperation() { | |
| 787 _indexStore.removeSources(_context, container); | |
| 788 } | |
| 789 | |
| 790 @override | |
| 791 bool removeWhenSourceRemoved(Source source) => false; | |
| 792 | |
| 793 @override | |
| 794 String toString() => "RemoveSources(${container})"; | |
| 795 } | |
| 796 | |
| 797 /** | |
| 798 * The interface `UniverseElement` defines element to use when we want to reques
t "defines" | 1071 * The interface `UniverseElement` defines element to use when we want to reques
t "defines" |
| 799 * relations without specifying exact library. | 1072 * relations without specifying exact library. |
| 800 */ | 1073 */ |
| 801 abstract class UniverseElement implements Element { | 1074 abstract class UniverseElement implements Element { |
| 802 static final UniverseElement INSTANCE = UniverseElementImpl.INSTANCE; | 1075 static final UniverseElement INSTANCE = UniverseElementImpl.INSTANCE; |
| 803 } | 1076 } |
| 804 | 1077 |
| 805 /** | 1078 /** |
| 806 * The enumeration <code>ProcessorState</code> represents the possible states of
an operation | 1079 * The enumeration <code>ProcessorState</code> represents the possible states of
an operation |
| 807 * processor. | 1080 * processor. |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 971 */ | 1244 */ |
| 972 static final Relationship ANGULAR_REFERENCE = Relationship.getRelationship("an
gular-reference"); | 1245 static final Relationship ANGULAR_REFERENCE = Relationship.getRelationship("an
gular-reference"); |
| 973 | 1246 |
| 974 /** | 1247 /** |
| 975 * Reference to some closing tag of an XML element. | 1248 * Reference to some closing tag of an XML element. |
| 976 */ | 1249 */ |
| 977 static final Relationship ANGULAR_CLOSING_TAG_REFERENCE = Relationship.getRela
tionship("angular-closing-tag-reference"); | 1250 static final Relationship ANGULAR_CLOSING_TAG_REFERENCE = Relationship.getRela
tionship("angular-closing-tag-reference"); |
| 978 } | 1251 } |
| 979 | 1252 |
| 980 /** | 1253 /** |
| 981 * Visits resolved [HtmlUnit] and adds relationships into [IndexStore]. | |
| 982 */ | |
| 983 class AngularHtmlIndexContributor extends ExpressionVisitor { | |
| 984 /** | |
| 985 * The [IndexStore] to record relations into. | |
| 986 */ | |
| 987 final IndexStore _store; | |
| 988 | |
| 989 /** | |
| 990 * The index contributor used to index Dart [Expression]s. | |
| 991 */ | |
| 992 IndexContributor _indexContributor; | |
| 993 | |
| 994 HtmlElement _htmlUnitElement; | |
| 995 | |
| 996 /** | |
| 997 * Initialize a newly created Angular HTML index contributor. | |
| 998 * | |
| 999 * @param store the [IndexStore] to record relations into. | |
| 1000 */ | |
| 1001 AngularHtmlIndexContributor(this._store) { | |
| 1002 _indexContributor = new IndexContributor_AngularHtmlIndexContributor(_store,
this); | |
| 1003 } | |
| 1004 | |
| 1005 @override | |
| 1006 void visitExpression(Expression expression) { | |
| 1007 // Formatter | |
| 1008 if (expression is SimpleIdentifier) { | |
| 1009 SimpleIdentifier identifier = expression; | |
| 1010 Element element = identifier.bestElement; | |
| 1011 if (element is AngularElement) { | |
| 1012 _store.recordRelationship(element, IndexConstants.ANGULAR_REFERENCE, _cr
eateLocationForIdentifier(identifier)); | |
| 1013 return; | |
| 1014 } | |
| 1015 } | |
| 1016 // index as a normal Dart expression | |
| 1017 expression.accept(_indexContributor); | |
| 1018 } | |
| 1019 | |
| 1020 @override | |
| 1021 Object visitHtmlUnit(ht.HtmlUnit node) { | |
| 1022 _htmlUnitElement = node.element; | |
| 1023 CompilationUnitElement dartUnitElement = _htmlUnitElement.angularCompilation
Unit; | |
| 1024 _indexContributor.enterScope(dartUnitElement); | |
| 1025 return super.visitHtmlUnit(node); | |
| 1026 } | |
| 1027 | |
| 1028 @override | |
| 1029 Object visitXmlAttributeNode(ht.XmlAttributeNode node) { | |
| 1030 Element element = node.element; | |
| 1031 if (element != null) { | |
| 1032 ht.Token nameToken = node.nameToken; | |
| 1033 Location location = _createLocationForToken(nameToken); | |
| 1034 _store.recordRelationship(element, IndexConstants.ANGULAR_REFERENCE, locat
ion); | |
| 1035 } | |
| 1036 return super.visitXmlAttributeNode(node); | |
| 1037 } | |
| 1038 | |
| 1039 @override | |
| 1040 Object visitXmlTagNode(ht.XmlTagNode node) { | |
| 1041 Element element = node.element; | |
| 1042 if (element != null) { | |
| 1043 // tag | |
| 1044 { | |
| 1045 ht.Token tagToken = node.tagToken; | |
| 1046 Location location = _createLocationForToken(tagToken); | |
| 1047 _store.recordRelationship(element, IndexConstants.ANGULAR_REFERENCE, loc
ation); | |
| 1048 } | |
| 1049 // maybe add closing tag range | |
| 1050 ht.Token closingTag = node.closingTag; | |
| 1051 if (closingTag != null) { | |
| 1052 Location location = _createLocationForToken(closingTag); | |
| 1053 _store.recordRelationship(element, IndexConstants.ANGULAR_CLOSING_TAG_RE
FERENCE, location); | |
| 1054 } | |
| 1055 } | |
| 1056 return super.visitXmlTagNode(node); | |
| 1057 } | |
| 1058 | |
| 1059 Location _createLocationForIdentifier(SimpleIdentifier identifier) => new Loca
tion(_htmlUnitElement, identifier.offset, identifier.length); | |
| 1060 | |
| 1061 Location _createLocationForToken(ht.Token token) => new Location(_htmlUnitElem
ent, token.offset, token.length); | |
| 1062 } | |
| 1063 | |
| 1064 class IndexContributor_AngularHtmlIndexContributor extends IndexContributor { | |
| 1065 final AngularHtmlIndexContributor AngularHtmlIndexContributor_this; | |
| 1066 | |
| 1067 IndexContributor_AngularHtmlIndexContributor(IndexStore arg0, this.AngularHtml
IndexContributor_this) : super(arg0); | |
| 1068 | |
| 1069 @override | |
| 1070 Element peekElement() => AngularHtmlIndexContributor_this._htmlUnitElement; | |
| 1071 | |
| 1072 @override | |
| 1073 void recordRelationship(Element element, Relationship relationship, Location l
ocation) { | |
| 1074 AngularElement angularElement = AngularHtmlUnitResolver.getAngularElement(el
ement); | |
| 1075 if (angularElement != null) { | |
| 1076 element = angularElement; | |
| 1077 relationship = IndexConstants.ANGULAR_REFERENCE; | |
| 1078 } | |
| 1079 super.recordRelationship(element, relationship, location); | |
| 1080 } | |
| 1081 } | |
| 1082 | |
| 1083 /** | |
| 1084 * The interface [Index] defines the behavior of objects that maintain an index
storing | |
| 1085 * [Relationship] between [Element]. All of the operations | |
| 1086 * defined on the index are asynchronous, and results, when there are any, are p
rovided through a | |
| 1087 * callback. | |
| 1088 * | |
| 1089 * Despite being asynchronous, the results of the operations are guaranteed to b
e consistent with | |
| 1090 * the expectation that operations are performed in the order in which they are
requested. | |
| 1091 * Modification operations are executed before any read operation. There is no g
uarantee about the | |
| 1092 * order in which the callbacks for read operations will be invoked. | |
| 1093 */ | |
| 1094 abstract class Index { | |
| 1095 /** | |
| 1096 * Asynchronously invoke the given callback with an array containing all of th
e locations of the | |
| 1097 * elements that have the given relationship with the given element. For examp
le, if the element | |
| 1098 * represents a method and the relationship is the is-referenced-by relationsh
ip, then the | |
| 1099 * locations that will be passed into the callback will be all of the places w
here the method is | |
| 1100 * invoked. | |
| 1101 * | |
| 1102 * @param element the element that has the relationship with the locations to
be returned | |
| 1103 * @param relationship the relationship between the given element and the loca
tions to be returned | |
| 1104 * @param callback the callback that will be invoked when the locations are fo
und | |
| 1105 */ | |
| 1106 void getRelationships(Element element, Relationship relationship, Relationship
Callback callback); | |
| 1107 | |
| 1108 /** | |
| 1109 * Answer index statistics. | |
| 1110 */ | |
| 1111 String get statistics; | |
| 1112 | |
| 1113 /** | |
| 1114 * Asynchronously process the given [HtmlUnit] in order to record the relation
ships. | |
| 1115 * | |
| 1116 * @param context the [AnalysisContext] in which [HtmlUnit] was resolved | |
| 1117 * @param unit the [HtmlUnit] being indexed | |
| 1118 */ | |
| 1119 void indexHtmlUnit(AnalysisContext context, ht.HtmlUnit unit); | |
| 1120 | |
| 1121 /** | |
| 1122 * Asynchronously process the given [CompilationUnit] in order to record the r
elationships. | |
| 1123 * | |
| 1124 * @param context the [AnalysisContext] in which [CompilationUnit] was resolve
d | |
| 1125 * @param unit the [CompilationUnit] being indexed | |
| 1126 */ | |
| 1127 void indexUnit(AnalysisContext context, CompilationUnit unit); | |
| 1128 | |
| 1129 /** | |
| 1130 * Asynchronously remove from the index all of the information associated with
the given context. | |
| 1131 * | |
| 1132 * This method should be invoked when a context is disposed. | |
| 1133 * | |
| 1134 * @param context the [AnalysisContext] to remove | |
| 1135 */ | |
| 1136 void removeContext(AnalysisContext context); | |
| 1137 | |
| 1138 /** | |
| 1139 * Asynchronously remove from the index all of the information associated with
elements or | |
| 1140 * locations in the given source. This includes relationships between an eleme
nt in the given | |
| 1141 * source and any other locations, relationships between any other elements an
d a location within | |
| 1142 * the given source. | |
| 1143 * | |
| 1144 * This method should be invoked when a source is no longer part of the code b
ase. | |
| 1145 * | |
| 1146 * @param context the [AnalysisContext] in which [Source] being removed | |
| 1147 * @param source the [Source] being removed | |
| 1148 */ | |
| 1149 void removeSource(AnalysisContext context, Source source); | |
| 1150 | |
| 1151 /** | |
| 1152 * Asynchronously remove from the index all of the information associated with
elements or | |
| 1153 * locations in the given sources. This includes relationships between an elem
ent in the given | |
| 1154 * sources and any other locations, relationships between any other elements a
nd a location within | |
| 1155 * the given sources. | |
| 1156 * | |
| 1157 * This method should be invoked when multiple sources are no longer part of t
he code base. | |
| 1158 * | |
| 1159 * @param the [AnalysisContext] in which [Source]s being removed | |
| 1160 * @param container the [SourceContainer] holding the sources being removed | |
| 1161 */ | |
| 1162 void removeSources(AnalysisContext context, SourceContainer container); | |
| 1163 | |
| 1164 /** | |
| 1165 * Should be called in separate [Thread] to process request in this [Index]. D
oes not | |
| 1166 * return until the [stop] method is called. | |
| 1167 */ | |
| 1168 void run(); | |
| 1169 | |
| 1170 /** | |
| 1171 * Should be called to stop process running [run], so stop processing requests
. | |
| 1172 */ | |
| 1173 void stop(); | |
| 1174 } | |
| 1175 | |
| 1176 /** | |
| 1177 * Container of information computed by the index - relationships between elemen
ts. | |
| 1178 */ | |
| 1179 abstract class IndexStore { | |
| 1180 /** | |
| 1181 * Notifies the index store that we are going to index the unit with the given
element. | |
| 1182 * | |
| 1183 * If the unit is a part of a library, then all its locations are removed. If
it is a defining | |
| 1184 * compilation unit of a library, then index store also checks if some previou
sly indexed parts of | |
| 1185 * the library are not parts of the library anymore, and clears their informat
ion. | |
| 1186 * | |
| 1187 * @param the [AnalysisContext] in which unit being indexed | |
| 1188 * @param unitElement the element of the unit being indexed | |
| 1189 * @return `true` the given [AnalysisContext] is active, or `false` if it was | |
| 1190 * removed before, so no any unit may be indexed with it | |
| 1191 */ | |
| 1192 bool aboutToIndexDart(AnalysisContext context, CompilationUnitElement unitElem
ent); | |
| 1193 | |
| 1194 /** | |
| 1195 * Notifies the index store that we are going to index the given [HtmlElement]
. | |
| 1196 * | |
| 1197 * @param the [AnalysisContext] in which unit being indexed | |
| 1198 * @param htmlElement the [HtmlElement] being indexed | |
| 1199 * @return `true` the given [AnalysisContext] is active, or `false` if it was | |
| 1200 * removed before, so no any unit may be indexed with it | |
| 1201 */ | |
| 1202 bool aboutToIndexHtml(AnalysisContext context, HtmlElement htmlElement); | |
| 1203 | |
| 1204 /** | |
| 1205 * Return the locations of the elements that have the given relationship with
the given element. | |
| 1206 * For example, if the element represents a method and the relationship is the
is-referenced-by | |
| 1207 * relationship, then the returned locations will be all of the places where t
he method is | |
| 1208 * invoked. | |
| 1209 * | |
| 1210 * @param element the the element that has the relationship with the locations
to be returned | |
| 1211 * @param relationship the [Relationship] between the given element and the lo
cations to be | |
| 1212 * returned | |
| 1213 * @return the locations that have the given relationship with the given eleme
nt | |
| 1214 */ | |
| 1215 List<Location> getRelationships(Element element, Relationship relationship); | |
| 1216 | |
| 1217 /** | |
| 1218 * Answer index statistics. | |
| 1219 */ | |
| 1220 String get statistics; | |
| 1221 | |
| 1222 /** | |
| 1223 * Record that the given element and location have the given relationship. For
example, if the | |
| 1224 * relationship is the is-referenced-by relationship, then the element would b
e the element being | |
| 1225 * referenced and the location would be the point at which it is referenced. E
ach element can have | |
| 1226 * the same relationship with multiple locations. In other words, if the follo
wing code were | |
| 1227 * executed | |
| 1228 * | |
| 1229 * <pre> | |
| 1230 * recordRelationship(element, isReferencedBy, location1); | |
| 1231 * recordRelationship(element, isReferencedBy, location2); | |
| 1232 * </pre> | |
| 1233 * | |
| 1234 * then both relationships would be maintained in the index and the result of
executing | |
| 1235 * | |
| 1236 * <pre> | |
| 1237 * getRelationship(element, isReferencedBy); | |
| 1238 * </pre> | |
| 1239 * | |
| 1240 * would be an array containing both <code>location1</code> and <code>location
2</code>. | |
| 1241 * | |
| 1242 * @param element the element that is related to the location | |
| 1243 * @param relationship the [Relationship] between the element and the location | |
| 1244 * @param location the [Location] where relationship happens | |
| 1245 */ | |
| 1246 void recordRelationship(Element element, Relationship relationship, Location l
ocation); | |
| 1247 | |
| 1248 /** | |
| 1249 * Remove from the index all of the information associated with [AnalysisConte
xt]. | |
| 1250 * | |
| 1251 * This method should be invoked when a context is disposed. | |
| 1252 * | |
| 1253 * @param the [AnalysisContext] being removed | |
| 1254 */ | |
| 1255 void removeContext(AnalysisContext context); | |
| 1256 | |
| 1257 /** | |
| 1258 * Remove from the index all of the information associated with elements or lo
cations in the given | |
| 1259 * source. This includes relationships between an element in the given source
and any other | |
| 1260 * locations, relationships between any other elements and a location within t
he given source. | |
| 1261 * | |
| 1262 * This method should be invoked when a source is no longer part of the code b
ase. | |
| 1263 * | |
| 1264 * @param the [AnalysisContext] in which [Source] being removed | |
| 1265 * @param source the source being removed | |
| 1266 */ | |
| 1267 void removeSource(AnalysisContext context, Source source); | |
| 1268 | |
| 1269 /** | |
| 1270 * Remove from the index all of the information associated with elements or lo
cations in the given | |
| 1271 * sources. This includes relationships between an element in the given source
s and any other | |
| 1272 * locations, relationships between any other elements and a location within t
he given sources. | |
| 1273 * | |
| 1274 * This method should be invoked when multiple sources are no longer part of t
he code base. | |
| 1275 * | |
| 1276 * @param the [AnalysisContext] in which [Source]s being removed | |
| 1277 * @param container the [SourceContainer] holding the sources being removed | |
| 1278 */ | |
| 1279 void removeSources(AnalysisContext context, SourceContainer container); | |
| 1280 } | |
| 1281 | |
| 1282 /** | |
| 1283 * Implementation of [UniverseElement]. | |
| 1284 */ | |
| 1285 class UniverseElementImpl extends ElementImpl implements UniverseElement { | |
| 1286 static UniverseElementImpl INSTANCE = new UniverseElementImpl(); | |
| 1287 | |
| 1288 UniverseElementImpl() : super("--universe--", -1); | |
| 1289 | |
| 1290 @override | |
| 1291 accept(ElementVisitor visitor) => null; | |
| 1292 | |
| 1293 @override | |
| 1294 ElementKind get kind => ElementKind.UNIVERSE; | |
| 1295 } | |
| 1296 | |
| 1297 /** | |
| 1298 * Visits resolved AST and adds relationships into [IndexStore]. | 1254 * Visits resolved AST and adds relationships into [IndexStore]. |
| 1299 */ | 1255 */ |
| 1300 class IndexContributor extends GeneralizingAstVisitor<Object> { | 1256 class IndexContributor extends GeneralizingAstVisitor<Object> { |
| 1301 /** | 1257 /** |
| 1302 * @return the [Location] representing location of the [Element]. | 1258 * @return the [Location] representing location of the [Element]. |
| 1303 */ | 1259 */ |
| 1304 static Location createLocation(Element element) { | 1260 static Location createLocation(Element element) { |
| 1305 if (element != null) { | 1261 if (element != null) { |
| 1306 int offset = element.nameOffset; | 1262 int offset = element.nameOffset; |
| 1307 int length = element.displayName.length; | 1263 int length = element.displayName.length; |
| (...skipping 839 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2147 * Information about [ImportElement] and place where it is referenced using | 2103 * Information about [ImportElement] and place where it is referenced using |
| 2148 * [PrefixElement]. | 2104 * [PrefixElement]. |
| 2149 */ | 2105 */ |
| 2150 class IndexContributor_ImportElementInfo { | 2106 class IndexContributor_ImportElementInfo { |
| 2151 ImportElement _element; | 2107 ImportElement _element; |
| 2152 | 2108 |
| 2153 int _periodEnd = 0; | 2109 int _periodEnd = 0; |
| 2154 } | 2110 } |
| 2155 | 2111 |
| 2156 /** | 2112 /** |
| 2157 * Special [Element] which is used to index references to the name without speci
fying concrete | 2113 * The interface [Index] defines the behavior of objects that maintain an index
storing |
| 2158 * kind of this name - field, method or something else. | 2114 * [Relationship] between [Element]. All of the operations |
| 2159 */ | 2115 * defined on the index are asynchronous, and results, when there are any, are p
rovided through a |
| 2160 class NameElementImpl extends ElementImpl { | 2116 * callback. |
| 2161 NameElementImpl(String name) : super("name:${name}", -1); | 2117 * |
| 2162 | 2118 * Despite being asynchronous, the results of the operations are guaranteed to b
e consistent with |
| 2163 @override | 2119 * the expectation that operations are performed in the order in which they are
requested. |
| 2164 accept(ElementVisitor visitor) => null; | 2120 * Modification operations are executed before any read operation. There is no g
uarantee about the |
| 2165 | 2121 * order in which the callbacks for read operations will be invoked. |
| 2166 @override | 2122 */ |
| 2167 ElementKind get kind => ElementKind.NAME; | 2123 abstract class Index { |
| 2168 } | 2124 /** |
| 2169 | 2125 * Asynchronously invoke the given callback with an array containing all of th
e locations of the |
| 2170 /** | 2126 * elements that have the given relationship with the given element. For examp
le, if the element |
| 2171 * Visits resolved [CompilationUnit] and adds Angular specific relationships int
o | 2127 * represents a method and the relationship is the is-referenced-by relationsh
ip, then the |
| 2172 * [IndexStore]. | 2128 * locations that will be passed into the callback will be all of the places w
here the method is |
| 2173 */ | 2129 * invoked. |
| 2174 class AngularDartIndexContributor extends GeneralizingAstVisitor<Object> { | 2130 * |
| 2175 final IndexStore _store; | 2131 * @param element the element that has the relationship with the locations to
be returned |
| 2176 | 2132 * @param relationship the relationship between the given element and the loca
tions to be returned |
| 2177 AngularDartIndexContributor(this._store); | 2133 * @param callback the callback that will be invoked when the locations are fo
und |
| 2178 | 2134 */ |
| 2179 @override | 2135 void getRelationships(Element element, Relationship relationship, Relationship
Callback callback); |
| 2180 Object visitClassDeclaration(ClassDeclaration node) { | 2136 |
| 2181 ClassElement classElement = node.element; | 2137 /** |
| 2182 if (classElement != null) { | 2138 * Answer index statistics. |
| 2183 List<ToolkitObjectElement> toolkitObjects = classElement.toolkitObjects; | 2139 */ |
| 2184 for (ToolkitObjectElement object in toolkitObjects) { | 2140 String get statistics; |
| 2185 if (object is AngularComponentElement) { | 2141 |
| 2186 _indexComponent(object); | 2142 /** |
| 2187 } | 2143 * Asynchronously process the given [HtmlUnit] in order to record the relation
ships. |
| 2188 if (object is AngularDecoratorElement) { | 2144 * |
| 2189 AngularDecoratorElement directive = object; | 2145 * @param context the [AnalysisContext] in which [HtmlUnit] was resolved |
| 2190 _indexDirective(directive); | 2146 * @param unit the [HtmlUnit] being indexed |
| 2191 } | 2147 */ |
| 2192 } | 2148 void indexHtmlUnit(AnalysisContext context, ht.HtmlUnit unit); |
| 2193 } | 2149 |
| 2194 // stop visiting | 2150 /** |
| 2195 return null; | 2151 * Asynchronously process the given [CompilationUnit] in order to record the r
elationships. |
| 2196 } | 2152 * |
| 2197 | 2153 * @param context the [AnalysisContext] in which [CompilationUnit] was resolve
d |
| 2198 @override | 2154 * @param unit the [CompilationUnit] being indexed |
| 2199 Object visitCompilationUnitMember(CompilationUnitMember node) => null; | 2155 */ |
| 2200 | 2156 void indexUnit(AnalysisContext context, CompilationUnit unit); |
| 2201 void _indexComponent(AngularComponentElement component) { | 2157 |
| 2202 _indexProperties(component.properties); | 2158 /** |
| 2203 } | 2159 * Asynchronously remove from the index all of the information associated with
the given context. |
| 2204 | 2160 * |
| 2205 void _indexDirective(AngularDecoratorElement directive) { | 2161 * This method should be invoked when a context is disposed. |
| 2206 _indexProperties(directive.properties); | 2162 * |
| 2207 } | 2163 * @param context the [AnalysisContext] to remove |
| 2208 | 2164 */ |
| 2209 /** | 2165 void removeContext(AnalysisContext context); |
| 2210 * Index [FieldElement] references from [AngularPropertyElement]s. | 2166 |
| 2211 */ | 2167 /** |
| 2212 void _indexProperties(List<AngularPropertyElement> properties) { | 2168 * Asynchronously remove from the index all of the information associated with
elements or |
| 2213 for (AngularPropertyElement property in properties) { | 2169 * locations in the given source. This includes relationships between an eleme
nt in the given |
| 2214 FieldElement field = property.field; | 2170 * source and any other locations, relationships between any other elements an
d a location within |
| 2215 if (field != null) { | 2171 * the given source. |
| 2216 int offset = property.fieldNameOffset; | 2172 * |
| 2217 if (offset == -1) { | 2173 * This method should be invoked when a source is no longer part of the code b
ase. |
| 2218 continue; | 2174 * |
| 2219 } | 2175 * @param context the [AnalysisContext] in which [Source] being removed |
| 2220 int length = field.name.length; | 2176 * @param source the [Source] being removed |
| 2221 Location location = new Location(property, offset, length); | 2177 */ |
| 2222 // getter reference | 2178 void removeSource(AnalysisContext context, Source source); |
| 2223 if (property.propertyKind.callsGetter()) { | 2179 |
| 2224 PropertyAccessorElement getter = field.getter; | 2180 /** |
| 2225 if (getter != null) { | 2181 * Asynchronously remove from the index all of the information associated with
elements or |
| 2226 _store.recordRelationship(getter, IndexConstants.IS_REFERENCED_BY_QU
ALIFIED, location); | 2182 * locations in the given sources. This includes relationships between an elem
ent in the given |
| 2227 } | 2183 * sources and any other locations, relationships between any other elements a
nd a location within |
| 2228 } | 2184 * the given sources. |
| 2229 // setter reference | 2185 * |
| 2230 if (property.propertyKind.callsSetter()) { | 2186 * This method should be invoked when multiple sources are no longer part of t
he code base. |
| 2231 PropertyAccessorElement setter = field.setter; | 2187 * |
| 2232 if (setter != null) { | 2188 * @param the [AnalysisContext] in which [Source]s being removed |
| 2233 _store.recordRelationship(setter, IndexConstants.IS_REFERENCED_BY_QU
ALIFIED, location); | 2189 * @param container the [SourceContainer] holding the sources being removed |
| 2234 } | 2190 */ |
| 2235 } | 2191 void removeSources(AnalysisContext context, SourceContainer container); |
| 2236 } | 2192 |
| 2237 } | 2193 /** |
| 2238 } | 2194 * Should be called in separate [Thread] to process request in this [Index]. D
oes not |
| 2195 * return until the [stop] method is called. |
| 2196 */ |
| 2197 void run(); |
| 2198 |
| 2199 /** |
| 2200 * Should be called to stop process running [run], so stop processing requests
. |
| 2201 */ |
| 2202 void stop(); |
| 2239 } | 2203 } |
| 2240 | 2204 |
| 2241 /** | 2205 /** |
| 2242 * Instances of the [RemoveContextOperation] implement an operation that removes
from the | 2206 * Instances of the [RemoveContextOperation] implement an operation that removes
from the |
| 2243 * index any data based on the specified [AnalysisContext]. | 2207 * index any data based on the specified [AnalysisContext]. |
| 2244 */ | 2208 */ |
| 2245 class RemoveContextOperation implements IndexOperation { | 2209 class RemoveContextOperation implements IndexOperation { |
| 2246 /** | 2210 /** |
| 2247 * The index store against which this operation is being run. | 2211 * The index store against which this operation is being run. |
| 2248 */ | 2212 */ |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2270 } | 2234 } |
| 2271 | 2235 |
| 2272 @override | 2236 @override |
| 2273 bool removeWhenSourceRemoved(Source source) => false; | 2237 bool removeWhenSourceRemoved(Source source) => false; |
| 2274 | 2238 |
| 2275 @override | 2239 @override |
| 2276 String toString() => "RemoveContext(${context})"; | 2240 String toString() => "RemoveContext(${context})"; |
| 2277 } | 2241 } |
| 2278 | 2242 |
| 2279 /** | 2243 /** |
| 2280 * Instances of the [IndexHtmlUnitOperation] implement an operation that adds da
ta to the | 2244 * Instances of the [GetRelationshipsOperation] implement an operation used to a
ccess the |
| 2281 * index based on the resolved [HtmlUnit]. | 2245 * locations that have a specified relationship with a specified element. |
| 2282 */ | 2246 */ |
| 2283 class IndexHtmlUnitOperation implements IndexOperation { | 2247 class GetRelationshipsOperation implements IndexOperation { |
| 2248 final IndexStore _indexStore; |
| 2249 |
| 2250 final Element element; |
| 2251 |
| 2252 final Relationship relationship; |
| 2253 |
| 2254 final RelationshipCallback callback; |
| 2255 |
| 2256 /** |
| 2257 * Initialize a newly created operation that will access the locations that ha
ve a specified |
| 2258 * relationship with a specified element. |
| 2259 */ |
| 2260 GetRelationshipsOperation(this._indexStore, this.element, this.relationship, t
his.callback); |
| 2261 |
| 2262 @override |
| 2263 bool get isQuery => true; |
| 2264 |
| 2265 @override |
| 2266 void performOperation() { |
| 2267 List<Location> locations; |
| 2268 locations = _indexStore.getRelationships(element, relationship); |
| 2269 callback.hasRelationships(element, relationship, locations); |
| 2270 } |
| 2271 |
| 2272 @override |
| 2273 bool removeWhenSourceRemoved(Source source) => false; |
| 2274 |
| 2275 @override |
| 2276 String toString() => "GetRelationships(${element}, ${relationship})"; |
| 2277 } |
| 2278 |
| 2279 /** |
| 2280 * Instances of the [RemoveSourceOperation] implement an operation that removes
from the index |
| 2281 * any data based on the content of a specified source. |
| 2282 */ |
| 2283 class RemoveSourceOperation implements IndexOperation { |
| 2284 /** | 2284 /** |
| 2285 * The index store against which this operation is being run. | 2285 * The index store against which this operation is being run. |
| 2286 */ | 2286 */ |
| 2287 final IndexStore _indexStore; | 2287 final IndexStore _indexStore; |
| 2288 | 2288 |
| 2289 /** | 2289 /** |
| 2290 * The context in which [HtmlUnit] was resolved. | 2290 * The context in which source being removed. |
| 2291 */ | 2291 */ |
| 2292 final AnalysisContext _context; | 2292 final AnalysisContext _context; |
| 2293 | 2293 |
| 2294 /** | 2294 /** |
| 2295 * The [HtmlUnit] being indexed. | 2295 * The source being removed. |
| 2296 */ | 2296 */ |
| 2297 final ht.HtmlUnit unit; | 2297 final Source source; |
| 2298 | 2298 |
| 2299 /** | 2299 /** |
| 2300 * The element of the [HtmlUnit] being indexed. | 2300 * Initialize a newly created operation that will remove the specified resourc
e. |
| 2301 */ | |
| 2302 HtmlElement _htmlElement; | |
| 2303 | |
| 2304 /** | |
| 2305 * The source being indexed. | |
| 2306 */ | |
| 2307 Source _source; | |
| 2308 | |
| 2309 /** | |
| 2310 * Initialize a newly created operation that will index the specified [HtmlUni
t]. | |
| 2311 * | 2301 * |
| 2312 * @param indexStore the index store against which this operation is being run | 2302 * @param indexStore the index store against which this operation is being run |
| 2313 * @param context the context in which [HtmlUnit] was resolved | 2303 * @param context the [AnalysisContext] to remove source in |
| 2314 * @param unit the fully resolved [HtmlUnit] | 2304 * @param source the [Source] to remove from index |
| 2315 */ | 2305 */ |
| 2316 IndexHtmlUnitOperation(this._indexStore, this._context, this.unit) { | 2306 RemoveSourceOperation(this._indexStore, this._context, this.source); |
| 2317 this._htmlElement = unit.element; | 2307 |
| 2318 this._source = _htmlElement.source; | 2308 @override |
| 2309 bool get isQuery => false; |
| 2310 |
| 2311 @override |
| 2312 void performOperation() { |
| 2313 _indexStore.removeSource(_context, source); |
| 2319 } | 2314 } |
| 2320 | 2315 |
| 2321 /** | 2316 @override |
| 2322 * @return the [Source] to be indexed. | 2317 bool removeWhenSourceRemoved(Source source) => false; |
| 2323 */ | 2318 |
| 2324 Source get source => _source; | 2319 @override |
| 2325 | 2320 String toString() => "RemoveSource(${source.fullName})"; |
| 2326 @override | 2321 } |
| 2327 bool get isQuery => false; | 2322 |
| 2328 | 2323 /** |
| 2329 @override | 2324 * The interface [IndexOperation] defines the behavior of objects used to perfor
m operations |
| 2330 void performOperation() { | 2325 * on an index. |
| 2331 try { | 2326 */ |
| 2332 bool mayIndex = _indexStore.aboutToIndexHtml(_context, _htmlElement); | 2327 abstract class IndexOperation { |
| 2333 if (!mayIndex) { | 2328 /** |
| 2334 return; | 2329 * Return `true` if this operation returns information from the index. |
| 2335 } | 2330 * |
| 2336 AngularHtmlIndexContributor contributor = new AngularHtmlIndexContributor(
_indexStore); | 2331 * @return `true` if this operation returns information from the index |
| 2337 unit.accept(contributor); | 2332 */ |
| 2338 } catch (exception) { | 2333 bool get isQuery; |
| 2339 AnalysisEngine.instance.logger.logError2("Could not index ${unit.element.l
ocation}", exception); | 2334 |
| 2335 /** |
| 2336 * Perform the operation implemented by this operation. |
| 2337 */ |
| 2338 void performOperation(); |
| 2339 |
| 2340 /** |
| 2341 * Return `true` if this operation should be removed from the operation queue
when the |
| 2342 * given resource has been removed. |
| 2343 * |
| 2344 * @param source the [Source] that has been removed |
| 2345 * @return `true` if this operation should be removed from the operation queue
as a |
| 2346 * result of removing the resource |
| 2347 */ |
| 2348 bool removeWhenSourceRemoved(Source source); |
| 2349 } |
| 2350 |
| 2351 /** |
| 2352 * [IndexStore] which keeps all information in memory, but can write it to strea
m and read |
| 2353 * later. |
| 2354 */ |
| 2355 abstract class MemoryIndexStore implements IndexStore { |
| 2356 } |
| 2357 |
| 2358 /** |
| 2359 * [Location] with attached data. |
| 2360 */ |
| 2361 class LocationWithData<D> extends Location { |
| 2362 final D data; |
| 2363 |
| 2364 LocationWithData.con1(Location location, this.data) : super(location.element,
location.offset, location.length); |
| 2365 |
| 2366 LocationWithData.con2(Element element, int offset, int length, this.data) : su
per(element, offset, length); |
| 2367 |
| 2368 @override |
| 2369 Location newClone() => new LocationWithData<D>.con2(element, offset, length, d
ata); |
| 2370 } |
| 2371 |
| 2372 /** |
| 2373 * Relationship between an element and a location. Relationships are identified
by a globally unique |
| 2374 * identifier. |
| 2375 */ |
| 2376 class Relationship { |
| 2377 /** |
| 2378 * The unique identifier for this relationship. |
| 2379 */ |
| 2380 final String _uniqueId; |
| 2381 |
| 2382 /** |
| 2383 * A table mapping relationship identifiers to relationships. |
| 2384 */ |
| 2385 static Map<String, Relationship> _RelationshipMap = {}; |
| 2386 |
| 2387 /** |
| 2388 * Return the relationship with the given unique identifier. |
| 2389 * |
| 2390 * @param uniqueId the unique identifier for the relationship |
| 2391 * @return the relationship with the given unique identifier |
| 2392 */ |
| 2393 static Relationship getRelationship(String uniqueId) { |
| 2394 Relationship relationship = _RelationshipMap[uniqueId]; |
| 2395 if (relationship == null) { |
| 2396 relationship = new Relationship(uniqueId); |
| 2397 _RelationshipMap[uniqueId] = relationship; |
| 2340 } | 2398 } |
| 2399 return relationship; |
| 2341 } | 2400 } |
| 2342 | 2401 |
| 2343 @override | 2402 /** |
| 2344 bool removeWhenSourceRemoved(Source source) => this._source == source; | 2403 * @return all registered [Relationship]s. |
| 2345 | 2404 */ |
| 2346 @override | 2405 static Iterable<Relationship> values() => _RelationshipMap.values; |
| 2347 String toString() => "IndexHtmlUnitOperation(${_source.fullName})"; | 2406 |
| 2348 } | 2407 /** |
| 2349 | 2408 * Initialize a newly created relationship to have the given unique identifier
. |
| 2350 /** | 2409 * |
| 2410 * @param uniqueId the unique identifier for this relationship |
| 2411 */ |
| 2412 Relationship(this._uniqueId); |
| 2413 |
| 2414 /** |
| 2415 * Return the unique identifier for this relationship. |
| 2416 * |
| 2417 * @return the unique identifier for this relationship |
| 2418 */ |
| 2419 String get identifier => _uniqueId; |
| 2420 |
| 2421 @override |
| 2422 String toString() => _uniqueId; |
| 2423 } |
| 2424 |
| 2425 /** |
| 2351 * Instances of the class <code>Location</code> represent a location related to
an element. The | 2426 * Instances of the class <code>Location</code> represent a location related to
an element. The |
| 2352 * location is expressed as an offset and length, but the offset is relative to
the resource | 2427 * location is expressed as an offset and length, but the offset is relative to
the resource |
| 2353 * containing the element rather than the start of the element within that resou
rce. | 2428 * containing the element rather than the start of the element within that resou
rce. |
| 2354 */ | 2429 */ |
| 2355 class Location { | 2430 class Location { |
| 2356 /** | 2431 /** |
| 2357 * An empty array of locations. | 2432 * An empty array of locations. |
| 2358 */ | 2433 */ |
| 2359 static List<Location> EMPTY_ARRAY = new List<Location>(0); | 2434 static List<Location> EMPTY_ARRAY = new List<Location>(0); |
| 2360 | 2435 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2392 } | 2467 } |
| 2393 } | 2468 } |
| 2394 | 2469 |
| 2395 /** | 2470 /** |
| 2396 * Returns a clone of this [Location]. | 2471 * Returns a clone of this [Location]. |
| 2397 */ | 2472 */ |
| 2398 Location newClone() => new Location(element, offset, length); | 2473 Location newClone() => new Location(element, offset, length); |
| 2399 | 2474 |
| 2400 @override | 2475 @override |
| 2401 String toString() => "[${offset} - ${(offset + length)}) in ${element}"; | 2476 String toString() => "[${offset} - ${(offset + length)}) in ${element}"; |
| 2402 } | |
| 2403 | |
| 2404 /** | |
| 2405 * [IndexStore] which keeps all information in memory, but can write it to strea
m and read | |
| 2406 * later. | |
| 2407 */ | |
| 2408 abstract class MemoryIndexStore implements IndexStore { | |
| 2409 } | |
| 2410 | |
| 2411 /** | |
| 2412 * Instances of the [GetRelationshipsOperation] implement an operation used to a
ccess the | |
| 2413 * locations that have a specified relationship with a specified element. | |
| 2414 */ | |
| 2415 class GetRelationshipsOperation implements IndexOperation { | |
| 2416 final IndexStore _indexStore; | |
| 2417 | |
| 2418 final Element element; | |
| 2419 | |
| 2420 final Relationship relationship; | |
| 2421 | |
| 2422 final RelationshipCallback callback; | |
| 2423 | |
| 2424 /** | |
| 2425 * Initialize a newly created operation that will access the locations that ha
ve a specified | |
| 2426 * relationship with a specified element. | |
| 2427 */ | |
| 2428 GetRelationshipsOperation(this._indexStore, this.element, this.relationship, t
his.callback); | |
| 2429 | |
| 2430 @override | |
| 2431 bool get isQuery => true; | |
| 2432 | |
| 2433 @override | |
| 2434 void performOperation() { | |
| 2435 List<Location> locations; | |
| 2436 locations = _indexStore.getRelationships(element, relationship); | |
| 2437 callback.hasRelationships(element, relationship, locations); | |
| 2438 } | |
| 2439 | |
| 2440 @override | |
| 2441 bool removeWhenSourceRemoved(Source source) => false; | |
| 2442 | |
| 2443 @override | |
| 2444 String toString() => "GetRelationships(${element}, ${relationship})"; | |
| 2445 } | |
| 2446 | |
| 2447 /** | |
| 2448 * [Location] with attached data. | |
| 2449 */ | |
| 2450 class LocationWithData<D> extends Location { | |
| 2451 final D data; | |
| 2452 | |
| 2453 LocationWithData.con1(Location location, this.data) : super(location.element,
location.offset, location.length); | |
| 2454 | |
| 2455 LocationWithData.con2(Element element, int offset, int length, this.data) : su
per(element, offset, length); | |
| 2456 | |
| 2457 @override | |
| 2458 Location newClone() => new LocationWithData<D>.con2(element, offset, length, d
ata); | |
| 2459 } | |
| 2460 | |
| 2461 /** | |
| 2462 * The interface <code>RelationshipCallback</code> defines the behavior of objec
ts that are invoked | |
| 2463 * with the results of a query about a given relationship. | |
| 2464 */ | |
| 2465 abstract class RelationshipCallback { | |
| 2466 /** | |
| 2467 * This method is invoked when the locations that have a specified relationshi
p with a specified | |
| 2468 * element are available. For example, if the element is a field and the relat
ionship is the | |
| 2469 * is-referenced-by relationship, then this method will be invoked with each l
ocation at which the | |
| 2470 * field is referenced. | |
| 2471 * | |
| 2472 * @param element the [Element] that has the relationship with the locations | |
| 2473 * @param relationship the relationship between the given element and the loca
tions | |
| 2474 * @param locations the locations that were found | |
| 2475 */ | |
| 2476 void hasRelationships(Element element, Relationship relationship, List<Locatio
n> locations); | |
| 2477 } | 2477 } |
| OLD | NEW |