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 test.services.src.index.dart_index_contributor; | |
6 | |
7 import 'package:analysis_services/index/index.dart'; | |
8 import 'package:analysis_services/index/index_store.dart'; | |
9 import 'package:analysis_services/src/index/index_contributor.dart'; | |
10 import 'package:analysis_testing/abstract_single_unit.dart'; | |
11 import 'package:analysis_testing/reflective_tests.dart'; | |
12 import 'package:analyzer/src/generated/ast.dart'; | |
13 import 'package:analyzer/src/generated/element.dart'; | |
14 import 'package:analyzer/src/generated/source.dart'; | |
15 import 'package:typed_mock/typed_mock.dart'; | |
16 import 'package:unittest/unittest.dart'; | |
17 | |
18 | |
19 main() { | |
20 groupSep = ' | '; | |
21 runReflectiveTests(DartUnitContributorTest); | |
22 } | |
23 | |
24 | |
25 /** | |
26 * Returns `true` if the [actual] location the same properties as [expected]. | |
27 */ | |
28 bool _equalsLocation(Location actual, ExpectedLocation expected) { | |
29 return _equalsLocationProperties( | |
30 actual, | |
31 expected.element, | |
32 expected.offset, | |
33 expected.length, | |
34 expected.isQualified, | |
35 expected.isResolved); | |
36 } | |
37 | |
38 | |
39 /** | |
40 * Returns `true` if the [actual] location the expected properties. | |
41 */ | |
42 bool _equalsLocationProperties(Location actual, Element expectedElement, | |
43 int expectedOffset, int expectedLength, bool isQualified, bool isResolved) { | |
44 return expectedElement == actual.element && | |
45 expectedOffset == actual.offset && | |
46 expectedLength == actual.length && | |
47 isQualified == actual.isQualified && | |
48 isResolved == actual.isResolved; | |
49 } | |
50 | |
51 | |
52 bool _equalsRecordedRelation(RecordedRelation recordedRelation, | |
53 Element expectedElement, Relationship expectedRelationship, | |
54 ExpectedLocation expectedLocation) { | |
55 return expectedElement == recordedRelation.element && | |
56 expectedRelationship == recordedRelation.relationship && | |
57 (expectedLocation == null || | |
58 _equalsLocation(recordedRelation.location, expectedLocation)); | |
59 } | |
60 | |
61 | |
62 @ReflectiveTestCase() | |
63 class DartUnitContributorTest extends AbstractSingleUnitTest { | |
64 IndexStore store = new MockIndexStore(); | |
65 List<RecordedRelation> recordedRelations = <RecordedRelation>[]; | |
66 | |
67 CompilationUnitElement importedUnit({int index: 0}) { | |
68 List<ImportElement> imports = testLibraryElement.imports; | |
69 return imports[index].importedLibrary.definingCompilationUnit; | |
70 } | |
71 | |
72 void setUp() { | |
73 super.setUp(); | |
74 when(store.aboutToIndexDart(context, anyObject)).thenReturn(true); | |
75 when( | |
76 store.recordRelationship( | |
77 anyObject, | |
78 anyObject, | |
79 anyObject)).thenInvoke( | |
80 (Element element, Relationship relationship, Location location)
{ | |
81 recordedRelations.add( | |
82 new RecordedRelation(element, relationship, location)); | |
83 }); | |
84 } | |
85 | |
86 void test_NameElement_field() { | |
87 _indexTestUnit(''' | |
88 class A { | |
89 int field; | |
90 } | |
91 main(A a, p) { | |
92 print(a.field); // r | |
93 print(p.field); // ur | |
94 { | |
95 var field = 42; | |
96 print(field); // not a member | |
97 } | |
98 } | |
99 '''); | |
100 // prepare elements | |
101 Element mainElement = findElement('main'); | |
102 FieldElement fieldElement = findElement('field'); | |
103 Element nameElement = new NameElement('field'); | |
104 // verify | |
105 _assertRecordedRelation( | |
106 nameElement, | |
107 IndexConstants.NAME_IS_DEFINED_BY, | |
108 _expectedLocation(fieldElement, 'field;')); | |
109 _assertRecordedRelation( | |
110 nameElement, | |
111 IndexConstants.IS_READ_BY, | |
112 _expectedLocationQ(mainElement, 'field); // r')); | |
113 _assertRecordedRelation( | |
114 nameElement, | |
115 IndexConstants.IS_READ_BY, | |
116 _expectedLocationQU(mainElement, 'field); // ur')); | |
117 _assertNoRecordedRelation( | |
118 nameElement, | |
119 IndexConstants.IS_READ_BY, | |
120 _expectedLocation(mainElement, 'field); // not a member')); | |
121 } | |
122 | |
123 void test_NameElement_isDefinedBy_localVariable_inForEach() { | |
124 _indexTestUnit(''' | |
125 class A { | |
126 main() { | |
127 for (int test in []) { | |
128 } | |
129 } | |
130 } | |
131 '''); | |
132 // prepare elements | |
133 Element mainElement = findElement('main'); | |
134 LocalVariableElement testElement = findElement('test'); | |
135 Element nameElement = new NameElement('test'); | |
136 // verify | |
137 _assertRecordedRelation( | |
138 nameElement, | |
139 IndexConstants.NAME_IS_DEFINED_BY, | |
140 _expectedLocation(testElement, 'test in []')); | |
141 } | |
142 | |
143 void test_NameElement_method() { | |
144 _indexTestUnit(''' | |
145 class A { | |
146 method() {} | |
147 } | |
148 main(A a, p) { | |
149 a.method(); // r | |
150 p.method(); // ur | |
151 } | |
152 '''); | |
153 // prepare elements | |
154 Element mainElement = findElement('main'); | |
155 MethodElement methodElement = findElement('method'); | |
156 Element nameElement = new NameElement('method'); | |
157 // verify | |
158 _assertRecordedRelation( | |
159 nameElement, | |
160 IndexConstants.NAME_IS_DEFINED_BY, | |
161 _expectedLocation(methodElement, 'method() {}')); | |
162 _assertRecordedRelation( | |
163 nameElement, | |
164 IndexConstants.IS_INVOKED_BY, | |
165 _expectedLocationQ(mainElement, 'method(); // r')); | |
166 _assertRecordedRelation( | |
167 nameElement, | |
168 IndexConstants.IS_INVOKED_BY, | |
169 _expectedLocationQU(mainElement, 'method(); // ur')); | |
170 } | |
171 | |
172 void test_NameElement_operator_resolved() { | |
173 _indexTestUnit(''' | |
174 class A { | |
175 operator +(o) {} | |
176 operator -(o) {} | |
177 operator ~() {} | |
178 operator ==(o) {} | |
179 } | |
180 main(A a) { | |
181 a + 5; | |
182 a += 5; | |
183 a == 5; | |
184 ++a; | |
185 --a; | |
186 ~a; | |
187 a++; | |
188 a--; | |
189 } | |
190 '''); | |
191 // prepare elements | |
192 Element mainElement = findElement('main'); | |
193 // binary | |
194 _assertRecordedRelation( | |
195 new NameElement('+'), | |
196 IndexConstants.IS_INVOKED_BY, | |
197 _expectedLocationQ(mainElement, '+ 5', length: 1)); | |
198 _assertRecordedRelation( | |
199 new NameElement('+'), | |
200 IndexConstants.IS_INVOKED_BY, | |
201 _expectedLocationQ(mainElement, '+= 5', length: 2)); | |
202 _assertRecordedRelation( | |
203 new NameElement('=='), | |
204 IndexConstants.IS_INVOKED_BY, | |
205 _expectedLocationQ(mainElement, '== 5', length: 2)); | |
206 // prefix | |
207 _assertRecordedRelation( | |
208 new NameElement('+'), | |
209 IndexConstants.IS_INVOKED_BY, | |
210 _expectedLocationQ(mainElement, '++a', length: 2)); | |
211 _assertRecordedRelation( | |
212 new NameElement('-'), | |
213 IndexConstants.IS_INVOKED_BY, | |
214 _expectedLocationQ(mainElement, '--a', length: 2)); | |
215 _assertRecordedRelation( | |
216 new NameElement('~'), | |
217 IndexConstants.IS_INVOKED_BY, | |
218 _expectedLocationQ(mainElement, '~a', length: 1)); | |
219 // postfix | |
220 _assertRecordedRelation( | |
221 new NameElement('+'), | |
222 IndexConstants.IS_INVOKED_BY, | |
223 _expectedLocationQ(mainElement, '++;', length: 2)); | |
224 _assertRecordedRelation( | |
225 new NameElement('-'), | |
226 IndexConstants.IS_INVOKED_BY, | |
227 _expectedLocationQ(mainElement, '--;', length: 2)); | |
228 } | |
229 | |
230 | |
231 void test_NameElement_operator_unresolved() { | |
232 _indexTestUnit(''' | |
233 class A { | |
234 operator +(o) {} | |
235 operator -(o) {} | |
236 operator ~() {} | |
237 operator ==(o) {} | |
238 } | |
239 main(a) { | |
240 a + 5; | |
241 a += 5; | |
242 a == 5; | |
243 ++a; | |
244 --a; | |
245 ~a; | |
246 a++; | |
247 a--; | |
248 } | |
249 '''); | |
250 // prepare elements | |
251 Element mainElement = findElement('main'); | |
252 // binary | |
253 _assertRecordedRelation( | |
254 new NameElement('+'), | |
255 IndexConstants.IS_INVOKED_BY, | |
256 _expectedLocationQU(mainElement, '+ 5', length: 1)); | |
257 _assertRecordedRelation( | |
258 new NameElement('+'), | |
259 IndexConstants.IS_INVOKED_BY, | |
260 _expectedLocationQU(mainElement, '+= 5', length: 2)); | |
261 _assertRecordedRelation( | |
262 new NameElement('=='), | |
263 IndexConstants.IS_INVOKED_BY, | |
264 _expectedLocationQU(mainElement, '== 5', length: 2)); | |
265 // prefix | |
266 _assertRecordedRelation( | |
267 new NameElement('+'), | |
268 IndexConstants.IS_INVOKED_BY, | |
269 _expectedLocationQU(mainElement, '++a', length: 2)); | |
270 _assertRecordedRelation( | |
271 new NameElement('-'), | |
272 IndexConstants.IS_INVOKED_BY, | |
273 _expectedLocationQU(mainElement, '--a', length: 2)); | |
274 _assertRecordedRelation( | |
275 new NameElement('~'), | |
276 IndexConstants.IS_INVOKED_BY, | |
277 _expectedLocationQU(mainElement, '~a', length: 1)); | |
278 // postfix | |
279 _assertRecordedRelation( | |
280 new NameElement('+'), | |
281 IndexConstants.IS_INVOKED_BY, | |
282 _expectedLocationQU(mainElement, '++;', length: 2)); | |
283 _assertRecordedRelation( | |
284 new NameElement('-'), | |
285 IndexConstants.IS_INVOKED_BY, | |
286 _expectedLocationQU(mainElement, '--;', length: 2)); | |
287 } | |
288 | |
289 void test_definesClass() { | |
290 _indexTestUnit('class A {}'); | |
291 // prepare elements | |
292 ClassElement classElement = findElement("A"); | |
293 // verify | |
294 _assertDefinesTopLevelElement( | |
295 IndexConstants.DEFINES, | |
296 _expectedLocation(classElement, 'A {}')); | |
297 } | |
298 | |
299 void test_definesClassAlias() { | |
300 _indexTestUnit(''' | |
301 class Mix {} | |
302 class MyClass = Object with Mix;'''); | |
303 // prepare elements | |
304 Element classElement = findElement("MyClass"); | |
305 // verify | |
306 _assertDefinesTopLevelElement( | |
307 IndexConstants.DEFINES, | |
308 _expectedLocation(classElement, 'MyClass =')); | |
309 } | |
310 | |
311 void test_definesFunction() { | |
312 _indexTestUnit('myFunction() {}'); | |
313 // prepare elements | |
314 FunctionElement functionElement = findElement("myFunction"); | |
315 // verify | |
316 _assertDefinesTopLevelElement( | |
317 IndexConstants.DEFINES, | |
318 _expectedLocation(functionElement, 'myFunction() {}')); | |
319 } | |
320 | |
321 | |
322 void test_definesFunctionType() { | |
323 _indexTestUnit('typedef MyFunction(int p);'); | |
324 // prepare elements | |
325 FunctionTypeAliasElement typeAliasElement = findElement("MyFunction"); | |
326 // verify | |
327 _assertDefinesTopLevelElement( | |
328 IndexConstants.DEFINES, | |
329 _expectedLocation(typeAliasElement, 'MyFunction(int p);')); | |
330 } | |
331 | |
332 void test_definesVariable() { | |
333 _indexTestUnit('var myVar = 42;'); | |
334 // prepare elements | |
335 VariableElement varElement = findElement("myVar"); | |
336 // verify | |
337 _assertDefinesTopLevelElement( | |
338 IndexConstants.DEFINES, | |
339 _expectedLocation(varElement, 'myVar = 42;')); | |
340 } | |
341 | |
342 void test_forIn() { | |
343 _indexTestUnit(''' | |
344 main() { | |
345 for (var v in []) { | |
346 } | |
347 }'''); | |
348 // prepare elements | |
349 Element mainElement = findElement("main"); | |
350 VariableElement variableElement = findElement("v"); | |
351 // verify | |
352 _assertNoRecordedRelation( | |
353 variableElement, | |
354 IndexConstants.IS_READ_BY, | |
355 _expectedLocation(mainElement, 'v in []')); | |
356 } | |
357 | |
358 void test_isDefinedBy_ConstructorElement() { | |
359 _indexTestUnit(''' | |
360 class A { | |
361 A() {} | |
362 A.foo() {} | |
363 }'''); | |
364 // prepare elements | |
365 ClassElement classA = findElement("A"); | |
366 ConstructorElement consA = | |
367 findNodeElementAtString("A()", (node) => node is ConstructorDeclaration)
; | |
368 ConstructorElement consA_foo = | |
369 findNodeElementAtString("A.foo()", (node) => node is ConstructorDeclarat
ion); | |
370 // verify | |
371 _assertRecordedRelation( | |
372 consA, | |
373 IndexConstants.NAME_IS_DEFINED_BY, | |
374 _expectedLocation(classA, '() {}')); | |
375 _assertRecordedRelation( | |
376 consA_foo, | |
377 IndexConstants.NAME_IS_DEFINED_BY, | |
378 _expectedLocation(classA, '.foo() {}', length: 4)); | |
379 } | |
380 | |
381 void test_isDefinedBy_NameElement_method() { | |
382 _indexTestUnit(''' | |
383 class A { | |
384 m() {} | |
385 }'''); | |
386 // prepare elements | |
387 Element methodElement = findElement("m"); | |
388 Element nameElement = new NameElement("m"); | |
389 // verify | |
390 _assertRecordedRelation( | |
391 nameElement, | |
392 IndexConstants.NAME_IS_DEFINED_BY, | |
393 _expectedLocation(methodElement, 'm() {}')); | |
394 } | |
395 | |
396 void test_isDefinedBy_NameElement_operator() { | |
397 _indexTestUnit(''' | |
398 class A { | |
399 operator +(o) {} | |
400 }'''); | |
401 // prepare elements | |
402 Element methodElement = findElement("+"); | |
403 Element nameElement = new NameElement("+"); | |
404 // verify | |
405 _assertRecordedRelation( | |
406 nameElement, | |
407 IndexConstants.NAME_IS_DEFINED_BY, | |
408 _expectedLocation(methodElement, '+(o) {}', length: 1)); | |
409 } | |
410 | |
411 | |
412 void test_isExtendedBy_ClassDeclaration() { | |
413 _indexTestUnit(''' | |
414 class A {} // 1 | |
415 class B extends A {} // 2 | |
416 '''); | |
417 // prepare elements | |
418 ClassElement classElementA = findElement("A"); | |
419 ClassElement classElementB = findElement("B"); | |
420 // verify | |
421 _assertRecordedRelation( | |
422 classElementA, | |
423 IndexConstants.IS_EXTENDED_BY, | |
424 _expectedLocation(classElementB, 'A {} // 2')); | |
425 } | |
426 | |
427 void test_isExtendedBy_ClassDeclaration_Object() { | |
428 _indexTestUnit(''' | |
429 class A {} // 1 | |
430 '''); | |
431 // prepare elements | |
432 ClassElement classElementA = findElement("A"); | |
433 ClassElement classElementObject = classElementA.supertype.element; | |
434 // verify | |
435 _assertRecordedRelation( | |
436 classElementObject, | |
437 IndexConstants.IS_EXTENDED_BY, | |
438 _expectedLocation(classElementA, 'A {}', length: 0)); | |
439 } | |
440 | |
441 | |
442 void test_isExtendedBy_ClassTypeAlias() { | |
443 _indexTestUnit(''' | |
444 class A {} // 1 | |
445 class B {} // 2 | |
446 class C = A with B; // 3 | |
447 '''); | |
448 // prepare elements | |
449 ClassElement classElementA = findElement("A"); | |
450 ClassElement classElementC = findElement("C"); | |
451 // verify | |
452 _assertRecordedRelation( | |
453 classElementA, | |
454 IndexConstants.IS_EXTENDED_BY, | |
455 _expectedLocation(classElementC, 'A with')); | |
456 } | |
457 | |
458 void test_isImplementedBy_ClassDeclaration() { | |
459 _indexTestUnit(''' | |
460 class A {} // 1 | |
461 class B implements A {} // 2 | |
462 '''); | |
463 // prepare elements | |
464 ClassElement classElementA = findElement("A"); | |
465 ClassElement classElementB = findElement("B"); | |
466 // verify | |
467 _assertRecordedRelation( | |
468 classElementA, | |
469 IndexConstants.IS_IMPLEMENTED_BY, | |
470 _expectedLocation(classElementB, 'A {} // 2')); | |
471 } | |
472 | |
473 void test_isImplementedBy_ClassTypeAlias() { | |
474 _indexTestUnit(''' | |
475 class A {} // 1 | |
476 class B {} // 2 | |
477 class C = Object with A implements B; // 3 | |
478 '''); | |
479 // prepare elements | |
480 ClassElement classElementB = findElement("B"); | |
481 ClassElement classElementC = findElement("C"); | |
482 // verify | |
483 _assertRecordedRelation( | |
484 classElementB, | |
485 IndexConstants.IS_IMPLEMENTED_BY, | |
486 _expectedLocation(classElementC, 'B; // 3')); | |
487 } | |
488 | |
489 void test_isInvokedBy_FieldElement() { | |
490 _indexTestUnit(''' | |
491 class A { | |
492 var field; | |
493 main() { | |
494 this.field(); // q | |
495 field(); // nq | |
496 } | |
497 }'''); | |
498 // prepare elements | |
499 Element mainElement = findElement("main"); | |
500 FieldElement fieldElement = findElement("field"); | |
501 PropertyAccessorElement getterElement = fieldElement.getter; | |
502 // verify | |
503 _assertRecordedRelation( | |
504 getterElement, | |
505 IndexConstants.IS_INVOKED_BY, | |
506 _expectedLocationQ(mainElement, 'field(); // q')); | |
507 _assertRecordedRelation( | |
508 getterElement, | |
509 IndexConstants.IS_INVOKED_BY, | |
510 _expectedLocation(mainElement, 'field(); // nq')); | |
511 } | |
512 | |
513 void test_isInvokedBy_FunctionElement() { | |
514 addSource('/lib.dart', ''' | |
515 library lib; | |
516 foo() {} | |
517 '''); | |
518 _indexTestUnit(''' | |
519 import 'lib.dart'; | |
520 import 'lib.dart' as pref; | |
521 main() { | |
522 pref.foo(); // q | |
523 foo(); // nq | |
524 }'''); | |
525 // prepare elements | |
526 Element mainElement = findElement("main"); | |
527 FunctionElement functionElement = importedUnit().functions[0]; | |
528 // verify | |
529 _assertRecordedRelation( | |
530 functionElement, | |
531 IndexConstants.IS_INVOKED_BY, | |
532 _expectedLocation(mainElement, 'foo(); // q')); | |
533 _assertRecordedRelation( | |
534 functionElement, | |
535 IndexConstants.IS_INVOKED_BY, | |
536 _expectedLocation(mainElement, 'foo(); // nq')); | |
537 } | |
538 | |
539 void test_isInvokedBy_LocalVariableElement() { | |
540 _indexTestUnit(''' | |
541 main() { | |
542 var v; | |
543 v(); | |
544 }'''); | |
545 // prepare elements | |
546 Element mainElement = findElement("main"); | |
547 Element element = findElement("v"); | |
548 // verify | |
549 _assertRecordedRelation( | |
550 element, | |
551 IndexConstants.IS_INVOKED_BY, | |
552 _expectedLocation(mainElement, 'v();')); | |
553 } | |
554 | |
555 void test_isInvokedBy_MethodElement() { | |
556 _indexTestUnit(''' | |
557 class A { | |
558 foo() {} | |
559 main() { | |
560 this.foo(); // q | |
561 foo(); // nq | |
562 } | |
563 }'''); | |
564 // prepare elements | |
565 Element mainElement = findElement("main"); | |
566 Element methodElement = findElement("foo"); | |
567 // verify | |
568 _assertRecordedRelation( | |
569 methodElement, | |
570 IndexConstants.IS_INVOKED_BY, | |
571 _expectedLocationQ(mainElement, 'foo(); // q')); | |
572 _assertRecordedRelation( | |
573 methodElement, | |
574 IndexConstants.IS_INVOKED_BY, | |
575 _expectedLocation(mainElement, 'foo(); // nq')); | |
576 } | |
577 | |
578 void test_isInvokedBy_MethodElement_propagatedType() { | |
579 _indexTestUnit(''' | |
580 class A { | |
581 foo() {} | |
582 } | |
583 main() { | |
584 var a = new A(); | |
585 a.foo(); | |
586 } | |
587 '''); | |
588 // prepare elements | |
589 Element mainElement = findElement("main"); | |
590 Element methodElement = findElement("foo"); | |
591 // verify | |
592 _assertRecordedRelation( | |
593 methodElement, | |
594 IndexConstants.IS_INVOKED_BY, | |
595 _expectedLocationQ(mainElement, 'foo();')); | |
596 } | |
597 | |
598 void test_isInvokedBy_ParameterElement() { | |
599 _indexTestUnit(''' | |
600 main(p()) { | |
601 p(); | |
602 }'''); | |
603 // prepare elements | |
604 Element mainElement = findElement("main"); | |
605 Element element = findElement("p"); | |
606 // verify | |
607 _assertRecordedRelation( | |
608 element, | |
609 IndexConstants.IS_INVOKED_BY, | |
610 _expectedLocation(mainElement, 'p();')); | |
611 } | |
612 | |
613 void test_isInvokedBy_operator_binary() { | |
614 _indexTestUnit(''' | |
615 class A { | |
616 operator +(other) => this; | |
617 } | |
618 main(A a) { | |
619 print(a + 1); | |
620 a += 2; | |
621 ++a; | |
622 a++; | |
623 } | |
624 '''); | |
625 // prepare elements | |
626 MethodElement element = findElement('+'); | |
627 Element mainElement = findElement('main'); | |
628 // verify | |
629 _assertRecordedRelation( | |
630 element, | |
631 IndexConstants.IS_INVOKED_BY, | |
632 _expectedLocationQ(mainElement, '+ 1', length: 1)); | |
633 _assertRecordedRelation( | |
634 element, | |
635 IndexConstants.IS_INVOKED_BY, | |
636 _expectedLocationQ(mainElement, '+= 2', length: 2)); | |
637 _assertRecordedRelation( | |
638 element, | |
639 IndexConstants.IS_INVOKED_BY, | |
640 _expectedLocationQ(mainElement, '++a;', length: 2)); | |
641 _assertRecordedRelation( | |
642 element, | |
643 IndexConstants.IS_INVOKED_BY, | |
644 _expectedLocationQ(mainElement, '++;', length: 2)); | |
645 } | |
646 | |
647 void test_isInvokedBy_operator_index() { | |
648 _indexTestUnit(''' | |
649 class A { | |
650 operator [](i) => null; | |
651 operator []=(i, v) {} | |
652 } | |
653 main(A a) { | |
654 print(a[0]); | |
655 a[1] = 42; | |
656 } | |
657 '''); | |
658 // prepare elements | |
659 MethodElement readElement = findElement("[]"); | |
660 MethodElement writeElement = findElement("[]="); | |
661 Element mainElement = findElement('main'); | |
662 // verify | |
663 _assertRecordedRelation( | |
664 readElement, | |
665 IndexConstants.IS_INVOKED_BY, | |
666 _expectedLocationQ(mainElement, '[0]', length: 1)); | |
667 _assertRecordedRelation( | |
668 writeElement, | |
669 IndexConstants.IS_INVOKED_BY, | |
670 _expectedLocationQ(mainElement, '[1] =', length: 1)); | |
671 } | |
672 | |
673 void test_isInvokedBy_operator_prefix() { | |
674 _indexTestUnit(''' | |
675 class A { | |
676 A operator ~() => this; | |
677 } | |
678 main(A a) { | |
679 print(~a); | |
680 } | |
681 '''); | |
682 // prepare elements | |
683 MethodElement element = findElement("~"); | |
684 Element mainElement = findElement('main'); | |
685 // verify | |
686 _assertRecordedRelation( | |
687 element, | |
688 IndexConstants.IS_INVOKED_BY, | |
689 _expectedLocationQ(mainElement, '~a', length: 1)); | |
690 } | |
691 | |
692 void test_isMixedInBy_ClassDeclaration() { | |
693 _indexTestUnit(''' | |
694 class A {} // 1 | |
695 class B extends Object with A {} // 2 | |
696 '''); | |
697 // prepare elements | |
698 ClassElement classElementA = findElement("A"); | |
699 ClassElement classElementB = findElement("B"); | |
700 // verify | |
701 _assertRecordedRelation( | |
702 classElementA, | |
703 IndexConstants.IS_MIXED_IN_BY, | |
704 _expectedLocation(classElementB, 'A {} // 2')); | |
705 } | |
706 | |
707 void test_isMixedInBy_ClassTypeAlias() { | |
708 _indexTestUnit(''' | |
709 class A {} // 1 | |
710 class B = Object with A; // 2 | |
711 '''); | |
712 // prepare elements | |
713 ClassElement classElementA = findElement("A"); | |
714 ClassElement classElementB = findElement("B"); | |
715 // verify | |
716 _assertRecordedRelation( | |
717 classElementA, | |
718 IndexConstants.IS_MIXED_IN_BY, | |
719 _expectedLocation(classElementB, 'A; // 2')); | |
720 } | |
721 | |
722 void test_isReadBy_ParameterElement() { | |
723 _indexTestUnit(''' | |
724 main(var p) { | |
725 print(p); | |
726 } | |
727 '''); | |
728 // prepare elements | |
729 Element mainElement = findElement("main"); | |
730 Element parameterElement = findElement("p"); | |
731 // verify | |
732 _assertRecordedRelation( | |
733 parameterElement, | |
734 IndexConstants.IS_READ_BY, | |
735 _expectedLocation(mainElement, 'p);')); | |
736 } | |
737 | |
738 void test_isReadBy_VariableElement() { | |
739 _indexTestUnit(''' | |
740 main() { | |
741 var v = 0; | |
742 print(v); | |
743 } | |
744 '''); | |
745 // prepare elements | |
746 Element mainElement = findElement("main"); | |
747 Element variableElement = findElement("v"); | |
748 // verify | |
749 _assertRecordedRelation( | |
750 variableElement, | |
751 IndexConstants.IS_READ_BY, | |
752 _expectedLocation(mainElement, 'v);')); | |
753 } | |
754 | |
755 void test_isReadWrittenBy_ParameterElement() { | |
756 _indexTestUnit(''' | |
757 main(int p) { | |
758 p += 1; | |
759 } | |
760 '''); | |
761 // prepare elements | |
762 Element mainElement = findElement("main"); | |
763 Element parameterElement = findElement("p"); | |
764 // verify | |
765 _assertRecordedRelation( | |
766 parameterElement, | |
767 IndexConstants.IS_READ_WRITTEN_BY, | |
768 _expectedLocation(mainElement, 'p += 1')); | |
769 } | |
770 | |
771 void test_isReadWrittenBy_VariableElement() { | |
772 _indexTestUnit(''' | |
773 main() { | |
774 var v = 0; | |
775 v += 1; | |
776 } | |
777 '''); | |
778 // prepare elements | |
779 Element mainElement = findElement("main"); | |
780 Element variableElement = findElement("v"); | |
781 // verify | |
782 _assertRecordedRelation( | |
783 variableElement, | |
784 IndexConstants.IS_READ_WRITTEN_BY, | |
785 _expectedLocation(mainElement, 'v += 1')); | |
786 } | |
787 | |
788 void test_isReferencedBy_ClassElement() { | |
789 _indexTestUnit(''' | |
790 class A { | |
791 static var field; | |
792 } | |
793 main(A p) { | |
794 A v; | |
795 new A(); // 2 | |
796 A.field = 1; | |
797 print(A.field); // 3 | |
798 } | |
799 '''); | |
800 // prepare elements | |
801 ClassElement aElement = findElement("A"); | |
802 Element mainElement = findElement("main"); | |
803 ParameterElement pElement = findElement("p"); | |
804 VariableElement vElement = findElement("v"); | |
805 // verify | |
806 _assertRecordedRelation( | |
807 aElement, | |
808 IndexConstants.IS_REFERENCED_BY, | |
809 _expectedLocation(pElement, 'A p) {')); | |
810 _assertRecordedRelation( | |
811 aElement, | |
812 IndexConstants.IS_REFERENCED_BY, | |
813 _expectedLocation(vElement, 'A v;')); | |
814 _assertRecordedRelation( | |
815 aElement, | |
816 IndexConstants.IS_REFERENCED_BY, | |
817 _expectedLocation(mainElement, 'A(); // 2')); | |
818 _assertRecordedRelation( | |
819 aElement, | |
820 IndexConstants.IS_REFERENCED_BY, | |
821 _expectedLocation(mainElement, 'A.field = 1;')); | |
822 _assertRecordedRelation( | |
823 aElement, | |
824 IndexConstants.IS_REFERENCED_BY, | |
825 _expectedLocation(mainElement, 'A.field); // 3')); | |
826 } | |
827 | |
828 void test_isReferencedBy_ClassTypeAlias() { | |
829 _indexTestUnit(''' | |
830 class A {} | |
831 class B = Object with A; | |
832 main(B p) { | |
833 B v; | |
834 } | |
835 '''); | |
836 // prepare elements | |
837 ClassElement bElement = findElement("B"); | |
838 ParameterElement pElement = findElement("p"); | |
839 VariableElement vElement = findElement("v"); | |
840 // verify | |
841 _assertRecordedRelation( | |
842 bElement, | |
843 IndexConstants.IS_REFERENCED_BY, | |
844 _expectedLocation(pElement, 'B p) {')); | |
845 _assertRecordedRelation( | |
846 bElement, | |
847 IndexConstants.IS_REFERENCED_BY, | |
848 _expectedLocation(vElement, 'B v;')); | |
849 } | |
850 | |
851 void test_isReferencedBy_CompilationUnitElement_export() { | |
852 addSource('/lib.dart', ''' | |
853 library lib; | |
854 '''); | |
855 _indexTestUnit(''' | |
856 export 'lib.dart'; | |
857 '''); | |
858 // prepare elements | |
859 LibraryElement libElement = testLibraryElement.exportedLibraries[0]; | |
860 CompilationUnitElement libUnitElement = libElement.definingCompilationUnit; | |
861 // verify | |
862 _assertRecordedRelation( | |
863 libUnitElement, | |
864 IndexConstants.IS_REFERENCED_BY, | |
865 _expectedLocation(testUnitElement, "'lib.dart'", length: 10)); | |
866 } | |
867 | |
868 void test_isReferencedBy_CompilationUnitElement_import() { | |
869 addSource('/lib.dart', ''' | |
870 library lib; | |
871 '''); | |
872 _indexTestUnit(''' | |
873 import 'lib.dart'; | |
874 '''); | |
875 // prepare elements | |
876 LibraryElement libElement = testLibraryElement.imports[0].importedLibrary; | |
877 CompilationUnitElement libUnitElement = libElement.definingCompilationUnit; | |
878 // verify | |
879 _assertRecordedRelation( | |
880 libUnitElement, | |
881 IndexConstants.IS_REFERENCED_BY, | |
882 _expectedLocation(testUnitElement, "'lib.dart'", length: 10)); | |
883 } | |
884 | |
885 void test_isReferencedBy_CompilationUnitElement_part() { | |
886 addSource('/my_unit.dart', 'part of my_lib;'); | |
887 _indexTestUnit(''' | |
888 library my_lib; | |
889 part 'my_unit.dart'; | |
890 '''); | |
891 // prepare elements | |
892 CompilationUnitElement myUnitElement = testLibraryElement.parts[0]; | |
893 // verify | |
894 _assertRecordedRelation( | |
895 myUnitElement, | |
896 IndexConstants.IS_REFERENCED_BY, | |
897 _expectedLocation(testUnitElement, "'my_unit.dart';", length: 14)); | |
898 } | |
899 | |
900 void test_isReferencedBy_ConstructorElement() { | |
901 _indexTestUnit(''' | |
902 class A implements B { | |
903 A() {} | |
904 A.foo() {} | |
905 } | |
906 class B extends A { | |
907 B() : super(); // marker-1 | |
908 B.foo() : super.foo(); // marker-2 | |
909 factory B.bar() = A.foo; // marker-3 | |
910 } | |
911 main() { | |
912 new A(); // marker-main-1 | |
913 new A.foo(); // marker-main-2 | |
914 } | |
915 '''); | |
916 // prepare elements | |
917 Element mainElement = findElement('main'); | |
918 var isConstructor = (node) => node is ConstructorDeclaration; | |
919 ConstructorElement consA = findNodeElementAtString("A()", isConstructor); | |
920 ConstructorElement consA_foo = | |
921 findNodeElementAtString("A.foo()", isConstructor); | |
922 ConstructorElement consB = findNodeElementAtString("B()", isConstructor); | |
923 ConstructorElement consB_foo = | |
924 findNodeElementAtString("B.foo()", isConstructor); | |
925 ConstructorElement consB_bar = | |
926 findNodeElementAtString("B.bar()", isConstructor); | |
927 // A() | |
928 _assertRecordedRelation( | |
929 consA, | |
930 IndexConstants.IS_REFERENCED_BY, | |
931 _expectedLocation(consB, '(); // marker-1', length: 0)); | |
932 _assertRecordedRelation( | |
933 consA, | |
934 IndexConstants.IS_REFERENCED_BY, | |
935 _expectedLocation(mainElement, '(); // marker-main-1', length: 0)); | |
936 // A.foo() | |
937 _assertRecordedRelation( | |
938 consA_foo, | |
939 IndexConstants.IS_REFERENCED_BY, | |
940 _expectedLocation(consB_foo, '.foo(); // marker-2', length: 4)); | |
941 _assertRecordedRelation( | |
942 consA_foo, | |
943 IndexConstants.IS_REFERENCED_BY, | |
944 _expectedLocation(consB_bar, '.foo; // marker-3', length: 4)); | |
945 _assertRecordedRelation( | |
946 consA_foo, | |
947 IndexConstants.IS_REFERENCED_BY, | |
948 _expectedLocation(mainElement, '.foo(); // marker-main-2', length: 4)); | |
949 } | |
950 | |
951 void test_isReferencedBy_ConstructorElement_classTypeAlias() { | |
952 _indexTestUnit(''' | |
953 class M {} | |
954 class A implements B { | |
955 A() {} | |
956 A.named() {} | |
957 } | |
958 class B = A with M; | |
959 main() { | |
960 new B(); // marker-main-1 | |
961 new B.named(); // marker-main-2 | |
962 } | |
963 '''); | |
964 // prepare elements | |
965 Element mainElement = findElement('main'); | |
966 var isConstructor = (node) => node is ConstructorDeclaration; | |
967 ConstructorElement consA = findNodeElementAtString("A()", isConstructor); | |
968 ConstructorElement consA_named = | |
969 findNodeElementAtString("A.named()", isConstructor); | |
970 // verify | |
971 _assertRecordedRelation( | |
972 consA, | |
973 IndexConstants.IS_REFERENCED_BY, | |
974 _expectedLocation(mainElement, '(); // marker-main-1', length: 0)); | |
975 _assertRecordedRelation( | |
976 consA_named, | |
977 IndexConstants.IS_REFERENCED_BY, | |
978 _expectedLocation(mainElement, '.named(); // marker-main-2', length: 6))
; | |
979 } | |
980 | |
981 void test_isReferencedBy_ConstructorFieldInitializer() { | |
982 _indexTestUnit(''' | |
983 class A { | |
984 int field; | |
985 A() : field = 5; | |
986 } | |
987 '''); | |
988 // prepare elements | |
989 ConstructorElement constructorElement = | |
990 findNodeElementAtString("A()", (node) => node is ConstructorDeclaration)
; | |
991 FieldElement fieldElement = findElement("field"); | |
992 // verify | |
993 _assertRecordedRelation( | |
994 fieldElement, | |
995 IndexConstants.IS_REFERENCED_BY, | |
996 _expectedLocation(constructorElement, 'field = 5')); | |
997 } | |
998 | |
999 void test_isReferencedBy_FieldElement() { | |
1000 _indexTestUnit(''' | |
1001 class A { | |
1002 var field; | |
1003 main() { | |
1004 this.field = 5; // q | |
1005 print(this.field); // q | |
1006 field = 5; // nq | |
1007 print(field); // nq | |
1008 } | |
1009 } | |
1010 '''); | |
1011 // prepare elements | |
1012 Element mainElement = findElement("main"); | |
1013 FieldElement fieldElement = findElement("field"); | |
1014 PropertyAccessorElement getter = fieldElement.getter; | |
1015 PropertyAccessorElement setter = fieldElement.setter; | |
1016 // verify | |
1017 _assertRecordedRelation( | |
1018 setter, | |
1019 IndexConstants.IS_REFERENCED_BY, | |
1020 _expectedLocationQ(mainElement, 'field = 5; // q')); | |
1021 _assertRecordedRelation( | |
1022 getter, | |
1023 IndexConstants.IS_REFERENCED_BY, | |
1024 _expectedLocationQ(mainElement, 'field); // q')); | |
1025 _assertRecordedRelation( | |
1026 setter, | |
1027 IndexConstants.IS_REFERENCED_BY, | |
1028 _expectedLocation(mainElement, 'field = 5; // nq')); | |
1029 _assertRecordedRelation( | |
1030 getter, | |
1031 IndexConstants.IS_REFERENCED_BY, | |
1032 _expectedLocation(mainElement, 'field); // nq')); | |
1033 } | |
1034 | |
1035 void test_isReferencedBy_FieldFormalParameterElement() { | |
1036 _indexTestUnit(''' | |
1037 class A { | |
1038 int field; | |
1039 A(this.field); | |
1040 } | |
1041 '''); | |
1042 // prepare elements | |
1043 FieldElement fieldElement = findElement("field"); | |
1044 Element fieldParameterElement = findNodeElementAtString("field);"); | |
1045 // verify | |
1046 _assertRecordedRelation( | |
1047 fieldElement, | |
1048 IndexConstants.IS_REFERENCED_BY, | |
1049 _expectedLocation(fieldParameterElement, 'field);')); | |
1050 } | |
1051 | |
1052 void test_isReferencedBy_FunctionElement() { | |
1053 _indexTestUnit(''' | |
1054 foo() {} | |
1055 main() { | |
1056 print(foo); | |
1057 print(foo()); | |
1058 } | |
1059 '''); | |
1060 // prepare elements | |
1061 FunctionElement element = findElement("foo"); | |
1062 Element mainElement = findElement("main"); | |
1063 // "referenced" here | |
1064 _assertRecordedRelation( | |
1065 element, | |
1066 IndexConstants.IS_REFERENCED_BY, | |
1067 _expectedLocation(mainElement, 'foo);')); | |
1068 // only "invoked", but not "referenced" | |
1069 { | |
1070 _assertRecordedRelation( | |
1071 element, | |
1072 IndexConstants.IS_INVOKED_BY, | |
1073 _expectedLocation(mainElement, 'foo());')); | |
1074 _assertNoRecordedRelation( | |
1075 element, | |
1076 IndexConstants.IS_REFERENCED_BY, | |
1077 _expectedLocation(mainElement, 'foo());')); | |
1078 } | |
1079 } | |
1080 | |
1081 void test_isReferencedBy_FunctionTypeAliasElement() { | |
1082 _indexTestUnit(''' | |
1083 typedef A(); | |
1084 main(A p) { | |
1085 } | |
1086 '''); | |
1087 // prepare elements | |
1088 Element aElement = findElement('A'); | |
1089 Element pElement = findElement('p'); | |
1090 // verify | |
1091 _assertRecordedRelation( | |
1092 aElement, | |
1093 IndexConstants.IS_REFERENCED_BY, | |
1094 _expectedLocation(pElement, 'A p) {')); | |
1095 } | |
1096 | |
1097 void test_isReferencedBy_ImportElement_noPrefix() { | |
1098 addSource('/lib.dart', ''' | |
1099 library lib; | |
1100 var myVar; | |
1101 myFunction() {} | |
1102 myToHide() {} | |
1103 '''); | |
1104 _indexTestUnit(''' | |
1105 import 'lib.dart' show myVar, myFunction hide myToHide; | |
1106 main() { | |
1107 myVar = 1; | |
1108 myFunction(); | |
1109 print(0); | |
1110 } | |
1111 '''); | |
1112 // prepare elements | |
1113 ImportElement importElement = testLibraryElement.imports[0]; | |
1114 Element mainElement = findElement('main'); | |
1115 // verify | |
1116 _assertRecordedRelation( | |
1117 importElement, | |
1118 IndexConstants.IS_REFERENCED_BY, | |
1119 _expectedLocation(mainElement, 'myVar = 1;', length: 0)); | |
1120 _assertRecordedRelation( | |
1121 importElement, | |
1122 IndexConstants.IS_REFERENCED_BY, | |
1123 _expectedLocation(mainElement, 'myFunction();', length: 0)); | |
1124 _assertNoRecordedRelation( | |
1125 importElement, | |
1126 IndexConstants.IS_REFERENCED_BY, | |
1127 _expectedLocation(mainElement, 'print(0);', length: 0)); | |
1128 // no references from import combinators | |
1129 _assertNoRecordedRelation( | |
1130 importElement, | |
1131 IndexConstants.IS_REFERENCED_BY, | |
1132 _expectedLocation(testUnitElement, 'myVar, ', length: 0)); | |
1133 _assertNoRecordedRelation( | |
1134 importElement, | |
1135 IndexConstants.IS_REFERENCED_BY, | |
1136 _expectedLocation(testUnitElement, 'myFunction hide', length: 0)); | |
1137 _assertNoRecordedRelation( | |
1138 importElement, | |
1139 IndexConstants.IS_REFERENCED_BY, | |
1140 _expectedLocation(testUnitElement, 'myToHide;', length: 0)); | |
1141 } | |
1142 | |
1143 void test_isReferencedBy_ImportElement_withPrefix() { | |
1144 addSource('/libA.dart', ''' | |
1145 library libA; | |
1146 var myVar; | |
1147 '''); | |
1148 addSource('/libB.dart', ''' | |
1149 library libB; | |
1150 class MyClass {} | |
1151 '''); | |
1152 _indexTestUnit(''' | |
1153 import 'libA.dart' as pref; | |
1154 import 'libB.dart' as pref; | |
1155 main() { | |
1156 pref.myVar = 1; | |
1157 new pref.MyClass(); | |
1158 } | |
1159 '''); | |
1160 // prepare elements | |
1161 ImportElement importElementA = testLibraryElement.imports[0]; | |
1162 ImportElement importElementB = testLibraryElement.imports[1]; | |
1163 Element mainElement = findElement('main'); | |
1164 // verify | |
1165 _assertRecordedRelation( | |
1166 importElementA, | |
1167 IndexConstants.IS_REFERENCED_BY, | |
1168 _expectedLocation(mainElement, 'pref.myVar = 1;', length: 5)); | |
1169 _assertRecordedRelation( | |
1170 importElementB, | |
1171 IndexConstants.IS_REFERENCED_BY, | |
1172 _expectedLocation(mainElement, 'pref.MyClass();', length: 5)); | |
1173 } | |
1174 | |
1175 void test_isReferencedBy_ImportElement_withPrefix_combinators() { | |
1176 addSource('/lib.dart', ''' | |
1177 library lib; | |
1178 class A {} | |
1179 class B {} | |
1180 '''); | |
1181 _indexTestUnit(''' | |
1182 import 'lib.dart' as pref show A; | |
1183 import 'lib.dart' as pref show B; | |
1184 import 'lib.dart'; | |
1185 import 'lib.dart' as otherPrefix; | |
1186 main() { | |
1187 new pref.A(); | |
1188 new pref.B(); | |
1189 } | |
1190 '''); | |
1191 // prepare elements | |
1192 ImportElement importElementA = testLibraryElement.imports[0]; | |
1193 ImportElement importElementB = testLibraryElement.imports[1]; | |
1194 Element mainElement = findElement('main'); | |
1195 // verify | |
1196 _assertRecordedRelation( | |
1197 importElementA, | |
1198 IndexConstants.IS_REFERENCED_BY, | |
1199 _expectedLocation(mainElement, 'pref.A();', length: 5)); | |
1200 _assertRecordedRelation( | |
1201 importElementB, | |
1202 IndexConstants.IS_REFERENCED_BY, | |
1203 _expectedLocation(mainElement, 'pref.B();', length: 5)); | |
1204 } | |
1205 | |
1206 void test_isReferencedBy_ImportElement_withPrefix_invocation() { | |
1207 addSource('/lib.dart', ''' | |
1208 library lib; | |
1209 myFunc() {} | |
1210 '''); | |
1211 _indexTestUnit(''' | |
1212 import 'lib.dart' as pref; | |
1213 main() { | |
1214 pref.myFunc(); | |
1215 } | |
1216 '''); | |
1217 // prepare elements | |
1218 ImportElement importElement = testLibraryElement.imports[0]; | |
1219 Element mainElement = findElement('main'); | |
1220 // verify | |
1221 _assertRecordedRelation( | |
1222 importElement, | |
1223 IndexConstants.IS_REFERENCED_BY, | |
1224 _expectedLocation(mainElement, 'pref.myFunc();', length: 5)); | |
1225 } | |
1226 | |
1227 void test_isReferencedBy_ImportElement_withPrefix_oneCandidate() { | |
1228 addSource('/lib.dart', ''' | |
1229 library lib; | |
1230 class A {} | |
1231 class B {} | |
1232 '''); | |
1233 _indexTestUnit(''' | |
1234 import 'lib.dart' as pref show A; | |
1235 main() { | |
1236 new pref.A(); | |
1237 } | |
1238 '''); | |
1239 // prepare elements | |
1240 ImportElement importElement = testLibraryElement.imports[0]; | |
1241 Element mainElement = findElement('main'); | |
1242 // verify | |
1243 _assertRecordedRelation( | |
1244 importElement, | |
1245 IndexConstants.IS_REFERENCED_BY, | |
1246 _expectedLocation(mainElement, 'pref.A();', length: 5)); | |
1247 } | |
1248 | |
1249 void test_isReferencedBy_ImportElement_withPrefix_unresolvedElement() { | |
1250 verifyNoTestUnitErrors = false; | |
1251 addSource('/lib.dart', ''' | |
1252 library lib; | |
1253 '''); | |
1254 _indexTestUnit(''' | |
1255 import 'lib.dart' as pref; | |
1256 main() { | |
1257 pref.myVar = 1; | |
1258 } | |
1259 '''); | |
1260 } | |
1261 | |
1262 void test_isReferencedBy_ImportElement_withPrefix_wrongInvocation() { | |
1263 verifyNoTestUnitErrors = false; | |
1264 _indexTestUnit(''' | |
1265 import 'dart:math' as m; | |
1266 main() { | |
1267 m(); | |
1268 }'''); | |
1269 } | |
1270 | |
1271 void test_isReferencedBy_ImportElement_withPrefix_wrongPrefixedIdentifier() { | |
1272 verifyNoTestUnitErrors = false; | |
1273 _indexTestUnit(''' | |
1274 import 'dart:math' as m; | |
1275 main() { | |
1276 x.m; | |
1277 } | |
1278 '''); | |
1279 } | |
1280 | |
1281 void test_isReferencedBy_LabelElement() { | |
1282 _indexTestUnit(''' | |
1283 main() { | |
1284 L: while (true) { | |
1285 break L; | |
1286 } | |
1287 } | |
1288 '''); | |
1289 // prepare elements | |
1290 Element mainElement = findElement('main'); | |
1291 Element element = findElement('L'); | |
1292 // verify | |
1293 _assertRecordedRelation( | |
1294 element, | |
1295 IndexConstants.IS_REFERENCED_BY, | |
1296 _expectedLocation(mainElement, 'L;')); | |
1297 } | |
1298 | |
1299 void test_isReferencedBy_MethodElement() { | |
1300 _indexTestUnit(''' | |
1301 class A { | |
1302 method() {} | |
1303 main() { | |
1304 print(this.method); // q | |
1305 print(method); // nq | |
1306 } | |
1307 }'''); | |
1308 // prepare elements | |
1309 Element mainElement = findElement("main"); | |
1310 MethodElement methodElement = findElement("method"); | |
1311 // verify | |
1312 _assertRecordedRelation( | |
1313 methodElement, | |
1314 IndexConstants.IS_REFERENCED_BY, | |
1315 _expectedLocationQ(mainElement, 'method); // q')); | |
1316 _assertRecordedRelation( | |
1317 methodElement, | |
1318 IndexConstants.IS_REFERENCED_BY, | |
1319 _expectedLocation(mainElement, 'method); // nq')); | |
1320 } | |
1321 | |
1322 void test_isReferencedBy_ParameterElement() { | |
1323 _indexTestUnit(''' | |
1324 foo({var p}) {} | |
1325 main() { | |
1326 foo(p: 1); | |
1327 } | |
1328 '''); | |
1329 // prepare elements | |
1330 Element mainElement = findElement('main'); | |
1331 Element element = findElement('p'); | |
1332 // verify | |
1333 _assertRecordedRelation( | |
1334 element, | |
1335 IndexConstants.IS_REFERENCED_BY, | |
1336 _expectedLocation(mainElement, 'p: 1')); | |
1337 } | |
1338 | |
1339 void test_isReferencedBy_TopLevelVariableElement() { | |
1340 addSource('/lib.dart', ''' | |
1341 library lib; | |
1342 var V; | |
1343 '''); | |
1344 _indexTestUnit(''' | |
1345 import 'lib.dart' show V; // imp | |
1346 import 'lib.dart' as pref; | |
1347 main() { | |
1348 pref.V = 5; // q | |
1349 print(pref.V); // q | |
1350 V = 5; // nq | |
1351 print(V); // nq | |
1352 }'''); | |
1353 // prepare elements | |
1354 TopLevelVariableElement variable = importedUnit().topLevelVariables[0]; | |
1355 Element mainElement = findElement("main"); | |
1356 // verify | |
1357 _assertRecordedRelation( | |
1358 variable, | |
1359 IndexConstants.IS_REFERENCED_BY, | |
1360 _expectedLocation(testUnitElement, 'V; // imp')); | |
1361 _assertRecordedRelation( | |
1362 variable.setter, | |
1363 IndexConstants.IS_REFERENCED_BY, | |
1364 _expectedLocation(mainElement, 'V = 5; // q')); | |
1365 _assertRecordedRelation( | |
1366 variable.getter, | |
1367 IndexConstants.IS_REFERENCED_BY, | |
1368 _expectedLocation(mainElement, 'V); // q')); | |
1369 _assertRecordedRelation( | |
1370 variable.setter, | |
1371 IndexConstants.IS_REFERENCED_BY, | |
1372 _expectedLocation(mainElement, 'V = 5; // nq')); | |
1373 _assertRecordedRelation( | |
1374 variable.getter, | |
1375 IndexConstants.IS_REFERENCED_BY, | |
1376 _expectedLocation(mainElement, 'V); // nq')); | |
1377 } | |
1378 | |
1379 void test_isReferencedBy_TypeParameterElement() { | |
1380 _indexTestUnit(''' | |
1381 class A<T> { | |
1382 T f; | |
1383 foo(T p) { | |
1384 T v; | |
1385 } | |
1386 } | |
1387 '''); | |
1388 // prepare elements | |
1389 Element typeParameterElement = findElement('T'); | |
1390 Element fieldElement = findElement('f'); | |
1391 Element parameterElement = findElement('p'); | |
1392 Element variableElement = findElement('v'); | |
1393 // verify | |
1394 _assertRecordedRelation( | |
1395 typeParameterElement, | |
1396 IndexConstants.IS_REFERENCED_BY, | |
1397 _expectedLocation(fieldElement, 'T f')); | |
1398 _assertRecordedRelation( | |
1399 typeParameterElement, | |
1400 IndexConstants.IS_REFERENCED_BY, | |
1401 _expectedLocation(parameterElement, 'T p')); | |
1402 _assertRecordedRelation( | |
1403 typeParameterElement, | |
1404 IndexConstants.IS_REFERENCED_BY, | |
1405 _expectedLocation(variableElement, 'T v')); | |
1406 } | |
1407 | |
1408 /** | |
1409 * There was a bug in the AST structure, when single [Comment] was cloned and | |
1410 * assigned to both [FieldDeclaration] and [VariableDeclaration]. | |
1411 * | |
1412 * This caused duplicate indexing. | |
1413 * Here we test that the problem is fixed one way or another. | |
1414 */ | |
1415 void test_isReferencedBy_identifierInComment() { | |
1416 _indexTestUnit(''' | |
1417 class A {} | |
1418 /// [A] text | |
1419 var myVariable = null; | |
1420 '''); | |
1421 // prepare elements | |
1422 Element aElement = findElement('A'); | |
1423 Element variableElement = findElement('myVariable'); | |
1424 // verify | |
1425 _assertRecordedRelation( | |
1426 aElement, | |
1427 IndexConstants.IS_REFERENCED_BY, | |
1428 _expectedLocation(testUnitElement, 'A] text')); | |
1429 _assertNoRecordedRelation( | |
1430 aElement, | |
1431 IndexConstants.IS_REFERENCED_BY, | |
1432 _expectedLocation(variableElement, 'A] text')); | |
1433 } | |
1434 | |
1435 void test_isReferencedBy_libraryName() { | |
1436 Source libSource = addSource('/lib.dart', ''' | |
1437 library lib; | |
1438 part 'test.dart'; | |
1439 '''); | |
1440 testCode = 'part of lib;'; | |
1441 testSource = addSource('/test.dart', testCode); | |
1442 testUnit = resolveDartUnit(testSource, libSource); | |
1443 testUnitElement = testUnit.element; | |
1444 testLibraryElement = testUnitElement.library; | |
1445 indexDartUnit(store, context, testUnit); | |
1446 // verify | |
1447 _assertRecordedRelation( | |
1448 testLibraryElement, | |
1449 IndexConstants.IS_REFERENCED_BY, | |
1450 _expectedLocation(testUnitElement, "lib;")); | |
1451 } | |
1452 | |
1453 void test_isReferencedBy_typeInVariableList() { | |
1454 _indexTestUnit(''' | |
1455 class A {} | |
1456 A myVariable = null; | |
1457 '''); | |
1458 // prepare elements | |
1459 Element classElementA = findElement('A'); | |
1460 Element variableElement = findElement('myVariable'); | |
1461 // verify | |
1462 _assertRecordedRelation( | |
1463 classElementA, | |
1464 IndexConstants.IS_REFERENCED_BY, | |
1465 _expectedLocation(variableElement, 'A myVariable')); | |
1466 } | |
1467 | |
1468 void test_isWrittenBy_ParameterElement() { | |
1469 _indexTestUnit(''' | |
1470 main(var p) { | |
1471 p = 1; | |
1472 }'''); | |
1473 // prepare elements | |
1474 Element mainElement = findElement("main"); | |
1475 ParameterElement pElement = findElement("p"); | |
1476 // verify | |
1477 _assertRecordedRelation( | |
1478 pElement, | |
1479 IndexConstants.IS_WRITTEN_BY, | |
1480 _expectedLocation(mainElement, 'p = 1')); | |
1481 } | |
1482 | |
1483 void test_isWrittenBy_VariableElement() { | |
1484 _indexTestUnit(''' | |
1485 main() { | |
1486 var v = 0; | |
1487 v = 1; | |
1488 }'''); | |
1489 // prepare elements | |
1490 Element mainElement = findElement("main"); | |
1491 LocalVariableElement vElement = findElement("v"); | |
1492 // verify | |
1493 _assertRecordedRelation( | |
1494 vElement, | |
1495 IndexConstants.IS_WRITTEN_BY, | |
1496 _expectedLocation(mainElement, 'v = 1')); | |
1497 } | |
1498 | |
1499 void test_nameIsInvokedBy() { | |
1500 _indexTestUnit(''' | |
1501 class A { | |
1502 test(x) {} | |
1503 } | |
1504 main(A a, p) { | |
1505 a.test(1); | |
1506 p.test(2); | |
1507 }'''); | |
1508 // prepare elements | |
1509 Element mainElement = findElement("main"); | |
1510 Element nameElement = new NameElement('test'); | |
1511 // verify | |
1512 _assertRecordedRelation( | |
1513 nameElement, | |
1514 IndexConstants.IS_INVOKED_BY, | |
1515 _expectedLocationQ(mainElement, 'test(1)')); | |
1516 _assertRecordedRelation( | |
1517 nameElement, | |
1518 IndexConstants.IS_INVOKED_BY, | |
1519 _expectedLocationQU(mainElement, 'test(2)')); | |
1520 _assertNoRecordedRelation( | |
1521 nameElement, | |
1522 IndexConstants.IS_READ_BY, | |
1523 _expectedLocationQU(mainElement, 'test(2)')); | |
1524 } | |
1525 | |
1526 void test_nameIsReadBy() { | |
1527 _indexTestUnit(''' | |
1528 class A { | |
1529 var test; | |
1530 } | |
1531 main(A a, p) { | |
1532 print(a.test); // a | |
1533 print(p.test); // p | |
1534 }'''); | |
1535 // prepare elements | |
1536 Element mainElement = findElement("main"); | |
1537 Element nameElement = new NameElement('test'); | |
1538 // verify | |
1539 _assertRecordedRelation( | |
1540 nameElement, | |
1541 IndexConstants.IS_READ_BY, | |
1542 _expectedLocationQ(mainElement, 'test); // a')); | |
1543 _assertRecordedRelation( | |
1544 nameElement, | |
1545 IndexConstants.IS_READ_BY, | |
1546 _expectedLocationQU(mainElement, 'test); // p')); | |
1547 } | |
1548 | |
1549 void test_nameIsReadWrittenBy() { | |
1550 _indexTestUnit(''' | |
1551 class A { | |
1552 var test; | |
1553 } | |
1554 main(A a, p) { | |
1555 a.test += 1; | |
1556 p.test += 2; | |
1557 }'''); | |
1558 // prepare elements | |
1559 Element mainElement = findElement("main"); | |
1560 Element nameElement = new NameElement('test'); | |
1561 // verify | |
1562 _assertRecordedRelation( | |
1563 nameElement, | |
1564 IndexConstants.IS_READ_WRITTEN_BY, | |
1565 _expectedLocationQ(mainElement, 'test += 1')); | |
1566 _assertRecordedRelation( | |
1567 nameElement, | |
1568 IndexConstants.IS_READ_WRITTEN_BY, | |
1569 _expectedLocationQU(mainElement, 'test += 2')); | |
1570 } | |
1571 | |
1572 void test_nameIsWrittenBy() { | |
1573 _indexTestUnit(''' | |
1574 class A { | |
1575 var test; | |
1576 } | |
1577 main(A a, p) { | |
1578 a.test = 1; | |
1579 p.test = 2; | |
1580 }'''); | |
1581 // prepare elements | |
1582 Element mainElement = findElement("main"); | |
1583 Element nameElement = new NameElement('test'); | |
1584 // verify | |
1585 _assertRecordedRelation( | |
1586 nameElement, | |
1587 IndexConstants.IS_WRITTEN_BY, | |
1588 _expectedLocationQ(mainElement, 'test = 1')); | |
1589 _assertRecordedRelation( | |
1590 nameElement, | |
1591 IndexConstants.IS_WRITTEN_BY, | |
1592 _expectedLocationQU(mainElement, 'test = 2')); | |
1593 } | |
1594 | |
1595 void test_nullUnit() { | |
1596 indexDartUnit(store, context, null); | |
1597 } | |
1598 | |
1599 void test_nullUnitElement() { | |
1600 CompilationUnit unit = new CompilationUnit(null, null, [], [], null); | |
1601 indexDartUnit(store, context, unit); | |
1602 } | |
1603 | |
1604 void _assertDefinesTopLevelElement(Relationship relationship, | |
1605 ExpectedLocation expectedLocation) { | |
1606 _assertRecordedRelation(testLibraryElement, relationship, expectedLocation); | |
1607 _assertRecordedRelation( | |
1608 UniverseElement.INSTANCE, | |
1609 relationship, | |
1610 expectedLocation); | |
1611 } | |
1612 | |
1613 /** | |
1614 * Asserts that [recordedRelations] has no item with the specified properties. | |
1615 */ | |
1616 void _assertNoRecordedRelation(Element element, Relationship relationship, | |
1617 ExpectedLocation location) { | |
1618 for (RecordedRelation recordedRelation in recordedRelations) { | |
1619 if (_equalsRecordedRelation( | |
1620 recordedRelation, | |
1621 element, | |
1622 relationship, | |
1623 location)) { | |
1624 fail( | |
1625 'not expected: ${recordedRelation} in\n' + recordedRelations.join('\
n')); | |
1626 } | |
1627 } | |
1628 } | |
1629 | |
1630 /** | |
1631 * Asserts that [recordedRelations] has an item with the expected properties. | |
1632 */ | |
1633 Location _assertRecordedRelation(Element expectedElement, | |
1634 Relationship expectedRelationship, ExpectedLocation expectedLocation) { | |
1635 for (RecordedRelation recordedRelation in recordedRelations) { | |
1636 if (_equalsRecordedRelation( | |
1637 recordedRelation, | |
1638 expectedElement, | |
1639 expectedRelationship, | |
1640 expectedLocation)) { | |
1641 return recordedRelation.location; | |
1642 } | |
1643 } | |
1644 fail( | |
1645 "not found\n$expectedElement $expectedRelationship " "in $expectedLocati
on in\n" | |
1646 + | |
1647 recordedRelations.join('\n')); | |
1648 return null; | |
1649 } | |
1650 | |
1651 ExpectedLocation _expectedLocation(Element element, String search, | |
1652 {int length: -1, bool isQualified: false, bool isResolved: true}) { | |
1653 int offset = findOffset(search); | |
1654 if (length == -1) { | |
1655 length = getLeadingIdentifierLength(search); | |
1656 } | |
1657 return new ExpectedLocation( | |
1658 element, | |
1659 offset, | |
1660 length, | |
1661 isQualified, | |
1662 isResolved); | |
1663 } | |
1664 | |
1665 ExpectedLocation _expectedLocationQ(Element element, String search, | |
1666 {int length: -1}) { | |
1667 return _expectedLocation( | |
1668 element, | |
1669 search, | |
1670 length: length, | |
1671 isQualified: true); | |
1672 } | |
1673 | |
1674 ExpectedLocation _expectedLocationQU(Element element, String search, | |
1675 {int length: -1}) { | |
1676 return _expectedLocation( | |
1677 element, | |
1678 search, | |
1679 length: length, | |
1680 isQualified: true, | |
1681 isResolved: false); | |
1682 } | |
1683 | |
1684 void _indexTestUnit(String code) { | |
1685 resolveTestUnit(code); | |
1686 indexDartUnit(store, context, testUnit); | |
1687 } | |
1688 } | |
1689 | |
1690 class ExpectedLocation { | |
1691 Element element; | |
1692 int offset; | |
1693 int length; | |
1694 bool isQualified; | |
1695 bool isResolved; | |
1696 | |
1697 ExpectedLocation(this.element, this.offset, this.length, this.isQualified, | |
1698 this.isResolved); | |
1699 | |
1700 @override | |
1701 String toString() { | |
1702 return 'ExpectedLocation(element=$element; offset=$offset; length=$length;' | |
1703 ' isQualified=$isQualified isResolved=$isResolved)'; | |
1704 } | |
1705 } | |
1706 | |
1707 class MockIndexStore extends TypedMock implements IndexStore { | |
1708 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); | |
1709 } | |
1710 | |
1711 | |
1712 /** | |
1713 * Information about a relation recorded into {@link IndexStore}. | |
1714 */ | |
1715 class RecordedRelation { | |
1716 final Element element; | |
1717 final Relationship relationship; | |
1718 final Location location; | |
1719 | |
1720 RecordedRelation(this.element, this.relationship, this.location); | |
1721 | |
1722 @override | |
1723 String toString() { | |
1724 return 'RecordedRelation(element=$element; relationship=$relationship; ' | |
1725 'location=$location; flags=' '${location.isQualified ? "Q" : ""}' | |
1726 '${location.isResolved ? "R" : ""})'; | |
1727 } | |
1728 } | |
OLD | NEW |