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.search.search_engine2; | |
6 | |
7 import 'dart:async'; | |
8 | |
9 import 'package:analysis_server/src/services/index2/index2.dart'; | |
10 import 'package:analysis_server/src/services/search/search_engine.dart'; | |
11 import 'package:analysis_server/src/services/search/search_engine_internal2.dart
'; | |
12 import 'package:analyzer/dart/element/element.dart'; | |
13 import 'package:analyzer/src/dart/element/element.dart'; | |
14 import 'package:analyzer/src/dart/element/member.dart'; | |
15 import 'package:analyzer/src/generated/source.dart'; | |
16 import 'package:test_reflective_loader/test_reflective_loader.dart'; | |
17 import 'package:unittest/unittest.dart'; | |
18 | |
19 import '../../abstract_single_unit.dart'; | |
20 import '../../utils.dart'; | |
21 | |
22 main() { | |
23 initializeTestEnvironment(); | |
24 defineReflectiveTests(SearchEngineImpl2Test); | |
25 } | |
26 | |
27 class ExpectedMatch { | |
28 final Element element; | |
29 final MatchKind kind; | |
30 SourceRange range; | |
31 final bool isResolved; | |
32 final bool isQualified; | |
33 | |
34 ExpectedMatch(this.element, this.kind, int offset, int length, | |
35 {this.isResolved: true, this.isQualified: false}) { | |
36 this.range = new SourceRange(offset, length); | |
37 } | |
38 | |
39 bool operator ==(SearchMatch match) { | |
40 return match.element == this.element && | |
41 match.kind == this.kind && | |
42 match.isResolved == this.isResolved && | |
43 match.isQualified == this.isQualified && | |
44 match.sourceRange == this.range; | |
45 } | |
46 | |
47 @override | |
48 String toString() { | |
49 StringBuffer buffer = new StringBuffer(); | |
50 buffer.write("ExpectedMatch(kind="); | |
51 buffer.write(kind); | |
52 buffer.write(", element="); | |
53 buffer.write(element != null ? element.displayName : 'null'); | |
54 buffer.write(", range="); | |
55 buffer.write(range); | |
56 buffer.write(", isResolved="); | |
57 buffer.write(isResolved); | |
58 buffer.write(", isQualified="); | |
59 buffer.write(isQualified); | |
60 buffer.write(")"); | |
61 return buffer.toString(); | |
62 } | |
63 } | |
64 | |
65 @reflectiveTest | |
66 class SearchEngineImpl2Test extends AbstractSingleUnitTest { | |
67 Index2 index; | |
68 SearchEngineImpl2 searchEngine; | |
69 | |
70 void setUp() { | |
71 super.setUp(); | |
72 index = createMemoryIndex2(); | |
73 searchEngine = new SearchEngineImpl2(index); | |
74 } | |
75 | |
76 test_searchAllSubtypes() async { | |
77 _indexTestUnit(''' | |
78 class T {} | |
79 class A extends T {} | |
80 class B extends A {} | |
81 class C implements B {} | |
82 '''); | |
83 ClassElement element = findElement('T'); | |
84 ClassElement elementA = findElement('A'); | |
85 ClassElement elementB = findElement('B'); | |
86 ClassElement elementC = findElement('C'); | |
87 var expected = [ | |
88 _expectId(elementA, MatchKind.DECLARATION, 'A extends T'), | |
89 _expectId(elementB, MatchKind.DECLARATION, 'B extends A'), | |
90 _expectId(elementC, MatchKind.DECLARATION, 'C implements B') | |
91 ]; | |
92 List<SearchMatch> matches = await searchEngine.searchAllSubtypes(element); | |
93 _assertMatches(matches, expected); | |
94 } | |
95 | |
96 test_searchMemberDeclarations() async { | |
97 _indexTestUnit(''' | |
98 class A { | |
99 test() {} | |
100 } | |
101 class B { | |
102 int test = 1; | |
103 main() { | |
104 int test = 2; | |
105 } | |
106 } | |
107 '''); | |
108 ClassElement elementA = findElement('A'); | |
109 ClassElement elementB = findElement('B'); | |
110 var expected = [ | |
111 _expectId(elementA.methods[0], MatchKind.DECLARATION, 'test() {}'), | |
112 _expectId(elementB.fields[0], MatchKind.DECLARATION, 'test = 1;') | |
113 ]; | |
114 List<SearchMatch> matches = | |
115 await searchEngine.searchMemberDeclarations('test'); | |
116 _assertMatches(matches, expected); | |
117 } | |
118 | |
119 test_searchMemberReferences_qualified_resolved() async { | |
120 _indexTestUnit(''' | |
121 class C { | |
122 var test; | |
123 } | |
124 main(C c) { | |
125 print(c.test); | |
126 c.test = 1; | |
127 c.test += 2; | |
128 c.test(); | |
129 } | |
130 '''); | |
131 List<SearchMatch> matches = | |
132 await searchEngine.searchMemberReferences('test'); | |
133 expect(matches, isEmpty); | |
134 } | |
135 | |
136 test_searchMemberReferences_qualified_unresolved() async { | |
137 _indexTestUnit(''' | |
138 main(p) { | |
139 print(p.test); | |
140 p.test = 1; | |
141 p.test += 2; | |
142 p.test(); | |
143 } | |
144 '''); | |
145 Element main = findElement('main'); | |
146 var expected = [ | |
147 _expectIdQU(main, MatchKind.READ, 'test);'), | |
148 _expectIdQU(main, MatchKind.WRITE, 'test = 1;'), | |
149 _expectIdQU(main, MatchKind.READ_WRITE, 'test += 2;'), | |
150 _expectIdQU(main, MatchKind.INVOCATION, 'test();'), | |
151 ]; | |
152 List<SearchMatch> matches = | |
153 await searchEngine.searchMemberReferences('test'); | |
154 _assertMatches(matches, expected); | |
155 } | |
156 | |
157 test_searchMemberReferences_unqualified_resolved() async { | |
158 _indexTestUnit(''' | |
159 class C { | |
160 var test; | |
161 main() { | |
162 print(test); | |
163 test = 1; | |
164 test += 2; | |
165 test(); | |
166 } | |
167 } | |
168 '''); | |
169 List<SearchMatch> matches = | |
170 await searchEngine.searchMemberReferences('test'); | |
171 expect(matches, isEmpty); | |
172 } | |
173 | |
174 test_searchMemberReferences_unqualified_unresolved() async { | |
175 verifyNoTestUnitErrors = false; | |
176 _indexTestUnit(''' | |
177 class C { | |
178 main() { | |
179 print(test); | |
180 test = 1; | |
181 test += 2; | |
182 test(); | |
183 } | |
184 } | |
185 '''); | |
186 Element main = findElement('main'); | |
187 var expected = [ | |
188 _expectIdU(main, MatchKind.READ, 'test);'), | |
189 _expectIdU(main, MatchKind.WRITE, 'test = 1;'), | |
190 _expectIdU(main, MatchKind.READ_WRITE, 'test += 2;'), | |
191 _expectIdU(main, MatchKind.INVOCATION, 'test();'), | |
192 ]; | |
193 List<SearchMatch> matches = | |
194 await searchEngine.searchMemberReferences('test'); | |
195 _assertMatches(matches, expected); | |
196 } | |
197 | |
198 test_searchReferences_ClassElement() async { | |
199 _indexTestUnit(''' | |
200 class A {} | |
201 main(A p) { | |
202 A v; | |
203 } | |
204 '''); | |
205 ClassElement element = findElement('A'); | |
206 Element pElement = findElement('p'); | |
207 Element vElement = findElement('v'); | |
208 var expected = [ | |
209 _expectId(pElement, MatchKind.REFERENCE, 'A p'), | |
210 _expectId(vElement, MatchKind.REFERENCE, 'A v') | |
211 ]; | |
212 await _verifyReferences(element, expected); | |
213 } | |
214 | |
215 test_searchReferences_CompilationUnitElement() async { | |
216 addSource( | |
217 '/my_part.dart', | |
218 ''' | |
219 part of lib; | |
220 '''); | |
221 _indexTestUnit(''' | |
222 library lib; | |
223 part 'my_part.dart'; | |
224 '''); | |
225 CompilationUnitElement element = testLibraryElement.parts[0]; | |
226 var expected = [ | |
227 _expectIdQ(testUnitElement, MatchKind.REFERENCE, "'my_part.dart'", | |
228 length: "'my_part.dart'".length) | |
229 ]; | |
230 await _verifyReferences(element, expected); | |
231 } | |
232 | |
233 test_searchReferences_ConstructorElement() async { | |
234 _indexTestUnit(''' | |
235 class A { | |
236 A.named() {} | |
237 } | |
238 main() { | |
239 new A.named(); | |
240 } | |
241 '''); | |
242 ConstructorElement element = findElement('named'); | |
243 Element mainElement = findElement('main'); | |
244 var expected = [ | |
245 _expectIdQ(mainElement, MatchKind.REFERENCE, '.named();', length: 6) | |
246 ]; | |
247 await _verifyReferences(element, expected); | |
248 } | |
249 | |
250 test_searchReferences_ConstructorElement_synthetic() async { | |
251 _indexTestUnit(''' | |
252 class A { | |
253 } | |
254 main() { | |
255 new A(); | |
256 } | |
257 '''); | |
258 ClassElement classElement = findElement('A'); | |
259 ConstructorElement element = classElement.unnamedConstructor; | |
260 Element mainElement = findElement('main'); | |
261 var expected = [ | |
262 _expectIdQ(mainElement, MatchKind.REFERENCE, '();', length: 0) | |
263 ]; | |
264 await _verifyReferences(element, expected); | |
265 } | |
266 | |
267 test_searchReferences_Element_unknown() async { | |
268 await _verifyReferences(DynamicElementImpl.instance, []); | |
269 } | |
270 | |
271 test_searchReferences_FieldElement() async { | |
272 _indexTestUnit(''' | |
273 class A { | |
274 var field; | |
275 A({this.field}); | |
276 main() { | |
277 new A(field: 1); | |
278 // getter | |
279 print(field); // ref-nq | |
280 print(this.field); // ref-q | |
281 field(); // inv-nq | |
282 this.field(); // inv-q | |
283 // setter | |
284 field = 2; // ref-nq; | |
285 this.field = 3; // ref-q; | |
286 } | |
287 } | |
288 '''); | |
289 FieldElement element = findElement('field'); | |
290 Element main = findElement('main'); | |
291 Element fieldParameter = findElement('field', ElementKind.PARAMETER); | |
292 var expected = [ | |
293 _expectIdQ(fieldParameter, MatchKind.WRITE, 'field}'), | |
294 _expectIdQ(main, MatchKind.REFERENCE, 'field: 1'), | |
295 _expectId(main, MatchKind.READ, 'field); // ref-nq'), | |
296 _expectIdQ(main, MatchKind.READ, 'field); // ref-q'), | |
297 _expectId(main, MatchKind.INVOCATION, 'field(); // inv-nq'), | |
298 _expectIdQ(main, MatchKind.INVOCATION, 'field(); // inv-q'), | |
299 _expectId(main, MatchKind.WRITE, 'field = 2; // ref-nq'), | |
300 _expectIdQ(main, MatchKind.WRITE, 'field = 3; // ref-q'), | |
301 ]; | |
302 await _verifyReferences(element, expected); | |
303 } | |
304 | |
305 test_searchReferences_FieldElement_ofEnum() async { | |
306 _indexTestUnit(''' | |
307 enum MyEnum { | |
308 A, B, C | |
309 } | |
310 main() { | |
311 print(MyEnum.A.index); | |
312 print(MyEnum.values); | |
313 print(MyEnum.A); | |
314 print(MyEnum.B); | |
315 } | |
316 '''); | |
317 ClassElement enumElement = findElement('MyEnum'); | |
318 Element mainElement = findElement('main'); | |
319 await _verifyReferences(enumElement.getField('index'), | |
320 [_expectIdQ(mainElement, MatchKind.READ, 'index);')]); | |
321 await _verifyReferences(enumElement.getField('values'), | |
322 [_expectIdQ(mainElement, MatchKind.READ, 'values);')]); | |
323 await _verifyReferences(enumElement.getField('A'), [ | |
324 _expectIdQ(mainElement, MatchKind.READ, 'A.index);'), | |
325 _expectIdQ(mainElement, MatchKind.READ, 'A);') | |
326 ]); | |
327 await _verifyReferences(enumElement.getField('B'), | |
328 [_expectIdQ(mainElement, MatchKind.READ, 'B);')]); | |
329 } | |
330 | |
331 test_searchReferences_FieldElement_synthetic() async { | |
332 _indexTestUnit(''' | |
333 class A { | |
334 get field => null; | |
335 set field(x) {} | |
336 main() { | |
337 // getter | |
338 print(field); // ref-nq | |
339 print(this.field); // ref-q | |
340 field(); // inv-nq | |
341 this.field(); // inv-q | |
342 // setter | |
343 field = 2; // ref-nq; | |
344 this.field = 3; // ref-q; | |
345 } | |
346 } | |
347 '''); | |
348 FieldElement element = findElement('field', ElementKind.FIELD); | |
349 Element main = findElement('main'); | |
350 var expected = [ | |
351 _expectId(main, MatchKind.READ, 'field); // ref-nq'), | |
352 _expectIdQ(main, MatchKind.READ, 'field); // ref-q'), | |
353 _expectId(main, MatchKind.INVOCATION, 'field(); // inv-nq'), | |
354 _expectIdQ(main, MatchKind.INVOCATION, 'field(); // inv-q'), | |
355 _expectId(main, MatchKind.WRITE, 'field = 2; // ref-nq'), | |
356 _expectIdQ(main, MatchKind.WRITE, 'field = 3; // ref-q'), | |
357 ]; | |
358 await _verifyReferences(element, expected); | |
359 } | |
360 | |
361 test_searchReferences_FunctionElement() async { | |
362 _indexTestUnit(''' | |
363 test() {} | |
364 main() { | |
365 test(); | |
366 print(test); | |
367 } | |
368 '''); | |
369 FunctionElement element = findElement('test'); | |
370 Element mainElement = findElement('main'); | |
371 var expected = [ | |
372 _expectId(mainElement, MatchKind.INVOCATION, 'test();'), | |
373 _expectId(mainElement, MatchKind.REFERENCE, 'test);') | |
374 ]; | |
375 await _verifyReferences(element, expected); | |
376 } | |
377 | |
378 test_searchReferences_FunctionElement_local() async { | |
379 _indexTestUnit(''' | |
380 main() { | |
381 test() {} | |
382 test(); | |
383 print(test); | |
384 } | |
385 '''); | |
386 FunctionElement element = findElement('test'); | |
387 Element mainElement = findElement('main'); | |
388 var expected = [ | |
389 _expectId(mainElement, MatchKind.INVOCATION, 'test();'), | |
390 _expectId(mainElement, MatchKind.REFERENCE, 'test);') | |
391 ]; | |
392 await _verifyReferences(element, expected); | |
393 } | |
394 | |
395 test_searchReferences_FunctionTypeAliasElement() async { | |
396 _indexTestUnit(''' | |
397 typedef Test(); | |
398 main() { | |
399 Test a; | |
400 Test b; | |
401 } | |
402 '''); | |
403 FunctionTypeAliasElement element = findElement('Test'); | |
404 Element aElement = findElement('a'); | |
405 Element bElement = findElement('b'); | |
406 var expected = [ | |
407 _expectId(aElement, MatchKind.REFERENCE, 'Test a;'), | |
408 _expectId(bElement, MatchKind.REFERENCE, 'Test b;') | |
409 ]; | |
410 await _verifyReferences(element, expected); | |
411 } | |
412 | |
413 test_searchReferences_ImportElement_noPrefix() async { | |
414 _indexTestUnit(''' | |
415 import 'dart:math' show max, PI, Random hide min; | |
416 export 'dart:math' show max, PI, Random hide min; | |
417 main() { | |
418 print(PI); | |
419 print(new Random()); | |
420 print(max(1, 2)); | |
421 } | |
422 Random bar() => null; | |
423 '''); | |
424 ImportElement element = testLibraryElement.imports[0]; | |
425 Element mainElement = findElement('main'); | |
426 Element barElement = findElement('bar'); | |
427 var kind = MatchKind.REFERENCE; | |
428 var expected = [ | |
429 _expectId(mainElement, kind, 'PI);', length: 0), | |
430 _expectId(mainElement, kind, 'Random()', length: 0), | |
431 _expectId(mainElement, kind, 'max(', length: 0), | |
432 _expectId(barElement, kind, 'Random bar()', length: 0), | |
433 ]; | |
434 await _verifyReferences(element, expected); | |
435 } | |
436 | |
437 test_searchReferences_ImportElement_withPrefix() async { | |
438 _indexTestUnit(''' | |
439 import 'dart:math' as math show max, PI, Random hide min; | |
440 export 'dart:math' show max, PI, Random hide min; | |
441 main() { | |
442 print(math.PI); | |
443 print(new math.Random()); | |
444 print(math.max(1, 2)); | |
445 } | |
446 math.Random bar() => null; | |
447 '''); | |
448 ImportElement element = testLibraryElement.imports[0]; | |
449 Element mainElement = findElement('main'); | |
450 Element barElement = findElement('bar'); | |
451 var kind = MatchKind.REFERENCE; | |
452 var length = 'math.'.length; | |
453 var expected = [ | |
454 _expectId(mainElement, kind, 'math.PI);', length: length), | |
455 _expectId(mainElement, kind, 'math.Random()', length: length), | |
456 _expectId(mainElement, kind, 'math.max(', length: length), | |
457 _expectId(barElement, kind, 'math.Random bar()', length: length), | |
458 ]; | |
459 await _verifyReferences(element, expected); | |
460 } | |
461 | |
462 test_searchReferences_LabelElement() async { | |
463 _indexTestUnit(''' | |
464 main() { | |
465 label: | |
466 while (true) { | |
467 if (true) { | |
468 break label; // 1 | |
469 } | |
470 break label; // 2 | |
471 } | |
472 } | |
473 '''); | |
474 LabelElement element = findElement('label'); | |
475 Element mainElement = findElement('main'); | |
476 var expected = [ | |
477 _expectId(mainElement, MatchKind.REFERENCE, 'label; // 1'), | |
478 _expectId(mainElement, MatchKind.REFERENCE, 'label; // 2') | |
479 ]; | |
480 await _verifyReferences(element, expected); | |
481 } | |
482 | |
483 test_searchReferences_LibraryElement() async { | |
484 var codeA = 'part of lib; // A'; | |
485 var codeB = 'part of lib; // B'; | |
486 addSource('/unitA.dart', codeA); | |
487 addSource('/unitB.dart', codeB); | |
488 _indexTestUnit(''' | |
489 library lib; | |
490 part 'unitA.dart'; | |
491 part 'unitB.dart'; | |
492 '''); | |
493 LibraryElement element = testLibraryElement; | |
494 CompilationUnitElement unitElementA = element.parts[0]; | |
495 CompilationUnitElement unitElementB = element.parts[1]; | |
496 index.indexUnit(unitElementA.computeNode()); | |
497 index.indexUnit(unitElementB.computeNode()); | |
498 var expected = [ | |
499 new ExpectedMatch(unitElementA, MatchKind.REFERENCE, | |
500 codeA.indexOf('lib; // A'), 'lib'.length), | |
501 new ExpectedMatch(unitElementB, MatchKind.REFERENCE, | |
502 codeB.indexOf('lib; // B'), 'lib'.length), | |
503 ]; | |
504 await _verifyReferences(element, expected); | |
505 } | |
506 | |
507 test_searchReferences_LocalVariableElement() async { | |
508 _indexTestUnit(''' | |
509 main() { | |
510 var v; | |
511 v = 1; | |
512 v += 2; | |
513 print(v); | |
514 v(); | |
515 } | |
516 '''); | |
517 LocalVariableElement element = findElement('v'); | |
518 Element mainElement = findElement('main'); | |
519 var expected = [ | |
520 _expectId(mainElement, MatchKind.WRITE, 'v = 1;'), | |
521 _expectId(mainElement, MatchKind.READ_WRITE, 'v += 2;'), | |
522 _expectId(mainElement, MatchKind.READ, 'v);'), | |
523 _expectId(mainElement, MatchKind.INVOCATION, 'v();') | |
524 ]; | |
525 await _verifyReferences(element, expected); | |
526 } | |
527 | |
528 test_searchReferences_MethodElement() async { | |
529 _indexTestUnit(''' | |
530 class A { | |
531 m() {} | |
532 main() { | |
533 m(); // 1 | |
534 this.m(); // 2 | |
535 print(m); // 3 | |
536 print(this.m); // 4 | |
537 } | |
538 } | |
539 '''); | |
540 MethodElement method = findElement('m'); | |
541 Element mainElement = findElement('main'); | |
542 var expected = [ | |
543 _expectId(mainElement, MatchKind.INVOCATION, 'm(); // 1'), | |
544 _expectIdQ(mainElement, MatchKind.INVOCATION, 'm(); // 2'), | |
545 _expectId(mainElement, MatchKind.REFERENCE, 'm); // 3'), | |
546 _expectIdQ(mainElement, MatchKind.REFERENCE, 'm); // 4') | |
547 ]; | |
548 await _verifyReferences(method, expected); | |
549 } | |
550 | |
551 test_searchReferences_MethodMember() async { | |
552 _indexTestUnit(''' | |
553 class A<T> { | |
554 T m() => null; | |
555 } | |
556 main(A<int> a) { | |
557 a.m(); // ref | |
558 } | |
559 '''); | |
560 MethodMember method = findNodeElementAtString('m(); // ref'); | |
561 Element mainElement = findElement('main'); | |
562 var expected = [ | |
563 _expectIdQ(mainElement, MatchKind.INVOCATION, 'm(); // ref') | |
564 ]; | |
565 await _verifyReferences(method, expected); | |
566 } | |
567 | |
568 test_searchReferences_ParameterElement_ofLocalFunction() async { | |
569 _indexTestUnit(''' | |
570 main() { | |
571 foo({p}) { | |
572 p = 1; | |
573 p += 2; | |
574 print(p); | |
575 p(); | |
576 } | |
577 foo(p: 42); | |
578 } | |
579 '''); | |
580 ParameterElement element = findElement('p'); | |
581 Element fooElement = findElement('foo'); | |
582 Element mainElement = findElement('main'); | |
583 var expected = [ | |
584 _expectId(fooElement, MatchKind.WRITE, 'p = 1;'), | |
585 _expectId(fooElement, MatchKind.READ_WRITE, 'p += 2;'), | |
586 _expectId(fooElement, MatchKind.READ, 'p);'), | |
587 _expectId(fooElement, MatchKind.INVOCATION, 'p();'), | |
588 _expectIdQ(mainElement, MatchKind.REFERENCE, 'p: 42') | |
589 ]; | |
590 await _verifyReferences(element, expected); | |
591 } | |
592 | |
593 test_searchReferences_ParameterElement_ofMethod() async { | |
594 _indexTestUnit(''' | |
595 class C { | |
596 foo({p}) { | |
597 p = 1; | |
598 p += 2; | |
599 print(p); | |
600 p(); | |
601 } | |
602 } | |
603 main(C c) { | |
604 c.foo(p: 42); | |
605 } | |
606 '''); | |
607 ParameterElement element = findElement('p'); | |
608 Element fooElement = findElement('foo'); | |
609 Element mainElement = findElement('main'); | |
610 var expected = [ | |
611 _expectId(fooElement, MatchKind.WRITE, 'p = 1;'), | |
612 _expectId(fooElement, MatchKind.READ_WRITE, 'p += 2;'), | |
613 _expectId(fooElement, MatchKind.READ, 'p);'), | |
614 _expectId(fooElement, MatchKind.INVOCATION, 'p();'), | |
615 _expectIdQ(mainElement, MatchKind.REFERENCE, 'p: 42') | |
616 ]; | |
617 await _verifyReferences(element, expected); | |
618 } | |
619 | |
620 test_searchReferences_ParameterElement_ofTopLevelFunction() async { | |
621 _indexTestUnit(''' | |
622 foo({p}) { | |
623 p = 1; | |
624 p += 2; | |
625 print(p); | |
626 p(); | |
627 } | |
628 main() { | |
629 foo(p: 42); | |
630 } | |
631 '''); | |
632 ParameterElement element = findElement('p'); | |
633 Element fooElement = findElement('foo'); | |
634 Element mainElement = findElement('main'); | |
635 var expected = [ | |
636 _expectId(fooElement, MatchKind.WRITE, 'p = 1;'), | |
637 _expectId(fooElement, MatchKind.READ_WRITE, 'p += 2;'), | |
638 _expectId(fooElement, MatchKind.READ, 'p);'), | |
639 _expectId(fooElement, MatchKind.INVOCATION, 'p();'), | |
640 _expectIdQ(mainElement, MatchKind.REFERENCE, 'p: 42') | |
641 ]; | |
642 await _verifyReferences(element, expected); | |
643 } | |
644 | |
645 test_searchReferences_PrefixElement() async { | |
646 _indexTestUnit(''' | |
647 import 'dart:async' as ppp; | |
648 main() { | |
649 ppp.Future a; | |
650 ppp.Stream b; | |
651 } | |
652 '''); | |
653 PrefixElement element = findNodeElementAtString('ppp;'); | |
654 Element elementA = findElement('a'); | |
655 Element elementB = findElement('b'); | |
656 var expected = [ | |
657 _expectId(elementA, MatchKind.REFERENCE, 'ppp.Future'), | |
658 _expectId(elementB, MatchKind.REFERENCE, 'ppp.Stream') | |
659 ]; | |
660 await _verifyReferences(element, expected); | |
661 } | |
662 | |
663 test_searchReferences_PropertyAccessorElement_getter() async { | |
664 _indexTestUnit(''' | |
665 class A { | |
666 get ggg => null; | |
667 main() { | |
668 print(ggg); // ref-nq | |
669 print(this.ggg); // ref-q | |
670 ggg(); // inv-nq | |
671 this.ggg(); // inv-q | |
672 } | |
673 } | |
674 '''); | |
675 PropertyAccessorElement element = findElement('ggg', ElementKind.GETTER); | |
676 Element main = findElement('main'); | |
677 var expected = [ | |
678 _expectId(main, MatchKind.REFERENCE, 'ggg); // ref-nq'), | |
679 _expectIdQ(main, MatchKind.REFERENCE, 'ggg); // ref-q'), | |
680 _expectId(main, MatchKind.INVOCATION, 'ggg(); // inv-nq'), | |
681 _expectIdQ(main, MatchKind.INVOCATION, 'ggg(); // inv-q'), | |
682 ]; | |
683 await _verifyReferences(element, expected); | |
684 } | |
685 | |
686 test_searchReferences_PropertyAccessorElement_setter() async { | |
687 _indexTestUnit(''' | |
688 class A { | |
689 set s(x) {} | |
690 main() { | |
691 s = 1; | |
692 this.s = 2; | |
693 } | |
694 } | |
695 '''); | |
696 PropertyAccessorElement element = findElement('s='); | |
697 Element mainElement = findElement('main'); | |
698 var expected = [ | |
699 _expectId(mainElement, MatchKind.REFERENCE, 's = 1'), | |
700 _expectIdQ(mainElement, MatchKind.REFERENCE, 's = 2') | |
701 ]; | |
702 await _verifyReferences(element, expected); | |
703 } | |
704 | |
705 test_searchReferences_TopLevelVariableElement() async { | |
706 addSource( | |
707 '/lib.dart', | |
708 ''' | |
709 library lib; | |
710 var V; | |
711 '''); | |
712 _indexTestUnit(''' | |
713 import 'lib.dart' show V; // imp | |
714 import 'lib.dart' as pref; | |
715 main() { | |
716 pref.V = 1; // q | |
717 print(pref.V); // q | |
718 pref.V(); // q | |
719 V = 1; // nq | |
720 print(V); // nq | |
721 V(); // nq | |
722 } | |
723 '''); | |
724 ImportElement importElement = testLibraryElement.imports[0]; | |
725 CompilationUnitElement impUnit = | |
726 importElement.importedLibrary.definingCompilationUnit; | |
727 TopLevelVariableElement variable = impUnit.topLevelVariables[0]; | |
728 Element main = findElement('main'); | |
729 var expected = [ | |
730 _expectIdQ(testUnitElement, MatchKind.REFERENCE, 'V; // imp'), | |
731 _expectIdQ(main, MatchKind.WRITE, 'V = 1; // q'), | |
732 _expectIdQ(main, MatchKind.READ, 'V); // q'), | |
733 _expectIdQ(main, MatchKind.INVOCATION, 'V(); // q'), | |
734 _expectId(main, MatchKind.WRITE, 'V = 1; // nq'), | |
735 _expectId(main, MatchKind.READ, 'V); // nq'), | |
736 _expectId(main, MatchKind.INVOCATION, 'V(); // nq'), | |
737 ]; | |
738 await _verifyReferences(variable, expected); | |
739 } | |
740 | |
741 test_searchReferences_TypeParameterElement() async { | |
742 _indexTestUnit(''' | |
743 class A<T> { | |
744 main(T a, T b) {} | |
745 } | |
746 '''); | |
747 TypeParameterElement element = findElement('T'); | |
748 Element aElement = findElement('a'); | |
749 Element bElement = findElement('b'); | |
750 var expected = [ | |
751 _expectId(aElement, MatchKind.REFERENCE, 'T a'), | |
752 _expectId(bElement, MatchKind.REFERENCE, 'T b') | |
753 ]; | |
754 await _verifyReferences(element, expected); | |
755 } | |
756 | |
757 test_searchSubtypes() async { | |
758 _indexTestUnit(''' | |
759 class T {} | |
760 class A extends T {} // A | |
761 class B = Object with T; // B | |
762 class C implements T {} // C | |
763 '''); | |
764 ClassElement element = findElement('T'); | |
765 ClassElement elementA = findElement('A'); | |
766 ClassElement elementB = findElement('B'); | |
767 ClassElement elementC = findElement('C'); | |
768 var expected = [ | |
769 _expectId(elementA, MatchKind.REFERENCE, 'T {} // A'), | |
770 _expectId(elementB, MatchKind.REFERENCE, 'T; // B'), | |
771 _expectId(elementC, MatchKind.REFERENCE, 'T {} // C') | |
772 ]; | |
773 List<SearchMatch> matches = await searchEngine.searchSubtypes(element); | |
774 _assertMatches(matches, expected); | |
775 } | |
776 | |
777 test_searchTopLevelDeclarations() async { | |
778 _indexTestUnit(''' | |
779 class A {} // A | |
780 class B = Object with A; | |
781 typedef C(); | |
782 D() {} | |
783 var E = null; | |
784 class NoMatchABCDE {} | |
785 '''); | |
786 Element topA = findElement('A'); | |
787 Element topB = findElement('B'); | |
788 Element topC = findElement('C'); | |
789 Element topD = findElement('D'); | |
790 Element topE = findElement('E'); | |
791 var expected = [ | |
792 _expectId(topA, MatchKind.DECLARATION, 'A {} // A'), | |
793 _expectId(topB, MatchKind.DECLARATION, 'B ='), | |
794 _expectId(topC, MatchKind.DECLARATION, 'C()'), | |
795 _expectId(topD, MatchKind.DECLARATION, 'D() {}'), | |
796 _expectId(topE, MatchKind.DECLARATION, 'E = null') | |
797 ]; | |
798 List<SearchMatch> matches = | |
799 await searchEngine.searchTopLevelDeclarations(r'^[A-E]$'); | |
800 _assertMatches(matches, expected); | |
801 } | |
802 | |
803 ExpectedMatch _expectId(Element element, MatchKind kind, String search, | |
804 {int length, bool isResolved: true, bool isQualified: false}) { | |
805 int offset = findOffset(search); | |
806 if (length == null) { | |
807 length = getLeadingIdentifierLength(search); | |
808 } | |
809 return new ExpectedMatch(element, kind, offset, length, | |
810 isResolved: isResolved, isQualified: isQualified); | |
811 } | |
812 | |
813 /** | |
814 * Create [ExpectedMatch] for a qualified and resolved match. | |
815 */ | |
816 ExpectedMatch _expectIdQ(Element element, MatchKind kind, String search, | |
817 {int length, bool isResolved: true}) { | |
818 return _expectId(element, kind, search, isQualified: true, length: length); | |
819 } | |
820 | |
821 /** | |
822 * Create [ExpectedMatch] for a qualified and unresolved match. | |
823 */ | |
824 ExpectedMatch _expectIdQU(Element element, MatchKind kind, String search, | |
825 {int length}) { | |
826 return _expectId(element, kind, search, | |
827 isQualified: true, isResolved: false, length: length); | |
828 } | |
829 | |
830 /** | |
831 * Create [ExpectedMatch] for a unqualified and unresolved match. | |
832 */ | |
833 ExpectedMatch _expectIdU(Element element, MatchKind kind, String search, | |
834 {int length}) { | |
835 return _expectId(element, kind, search, | |
836 isQualified: false, isResolved: false, length: length); | |
837 } | |
838 | |
839 void _indexTestUnit(String code) { | |
840 resolveTestUnit(code); | |
841 index.indexUnit(testUnit); | |
842 } | |
843 | |
844 Future _verifyReferences( | |
845 Element element, List<ExpectedMatch> expectedMatches) async { | |
846 List<SearchMatch> matches = await searchEngine.searchReferences(element); | |
847 _assertMatches(matches, expectedMatches); | |
848 expect(matches, hasLength(expectedMatches.length)); | |
849 } | |
850 | |
851 static void _assertMatches( | |
852 List<SearchMatch> matches, List<ExpectedMatch> expectedMatches) { | |
853 expect(matches, unorderedEquals(expectedMatches)); | |
854 } | |
855 } | |
OLD | NEW |