Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(240)

Side by Side Diff: pkg/analysis_server/test/search/element_references_test.dart

Issue 392693002: Initial implementation for 'search.findElementReferences'. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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.search.element_references;
6
7 import 'dart:async';
8
9 import 'package:analysis_server/src/computer/element.dart';
10 import 'package:analysis_server/src/constants.dart';
11 import 'package:analysis_server/src/protocol.dart';
12 import 'package:analysis_server/src/search/search_domain.dart';
13 import 'package:analysis_server/src/search/search_result.dart';
14 import 'package:analysis_services/index/index.dart' show Index;
15 import 'package:analysis_services/index/local_memory_index.dart';
16 import 'package:analysis_testing/reflective_tests.dart';
17 import 'package:unittest/unittest.dart';
18
19 import '../analysis_abstract.dart';
20
21
22 main() {
23 groupSep = ' | ';
24 group('findElementReferences', () {
25 runReflectiveTests(ElementReferencesTest);
26 });
27 }
28
29
30 @ReflectiveTestCase()
31 class ElementReferencesTest extends AbstractAnalysisTest {
32 String searchId;
33 bool searchDone = false;
34 List<SearchResult> results = <SearchResult>[];
35 SearchResult result;
36
37 void assertHasResult(SearchResultKind kind, String search, [int length]) {
38 int offset = findOffset(search);
39 if (length == null) {
40 length = findIdentifierLength(search);
41 }
42 findResult(kind, testFile, offset, length, true);
43 }
44
45 void assertNoResult(SearchResultKind kind, String search, [int length]) {
46 int offset = findOffset(search);
47 if (length == null) {
48 length = findIdentifierLength(search);
49 }
50 findResult(kind, testFile, offset, length, false);
51 }
52
53 @override
54 Index createIndex() {
55 return createLocalMemoryIndex();
56 }
57
58 fail_test_hierarchyMembers_field_explicit() {
59 // TODO(scheglov) implement
60 addTestFile('''
61 class A {
62 int fff; // in A
63 }
64 class B extends A {
65 int fff; // in B
66 }
67 class C extends B {
68 int fff; // in C
69 }
70 main(A a, B b, C c) {
71 a.fff = 10;
72 b.fff = 20;
73 c.fff = 30;
74 }
75 ''');
76 return findElementReferences('fff; // in B', false).then((_) {
77 assertHasResult(SearchResultKind.DECLARATION, 'fff; // in A');
78 assertHasResult(SearchResultKind.DECLARATION, 'fff; // in B');
79 assertHasResult(SearchResultKind.DECLARATION, 'fff; // in C');
80 assertHasResult(SearchResultKind.WRITE, 'fff = 10;');
81 assertHasResult(SearchResultKind.WRITE, 'fff = 20;');
82 assertHasResult(SearchResultKind.WRITE, 'fff = 30;');
83 });
84 }
85
86 fail_test_hierarchyMembers_method() {
87 // TODO(scheglov) implement
88 addTestFile('''
89 class A {
90 mmm() {} // in A
91 }
92 class B extends A {
93 mmm() {} // in B
94 }
95 class C extends B {
96 mmm() {} // in C
97 }
98 main(A a, B b, C c) {
99 a.mmm(10);
100 b.mmm(20);
101 c.mmm(30);
102 }
103 ''');
104 return findElementReferences('mmm() {} // in B', false).then((_) {
105 assertHasResult(SearchResultKind.INVOCATION, 'mmm(10)');
106 assertHasResult(SearchResultKind.INVOCATION, 'mmm(20)');
107 assertHasResult(SearchResultKind.INVOCATION, 'mmm(30)');
108 });
109 }
110
111 Future findElementReferences(String search, bool includePotential) {
112 int offset = findOffset(search);
113 return waitForTasksFinished().then((_) {
114 Request request = new Request('0', SEARCH_FIND_ELEMENT_REFERENCES);
115 request.setParameter(FILE, testFile);
116 request.setParameter(OFFSET, offset);
117 request.setParameter(INCLUDE_POTENTIAL, includePotential);
118 Response response = handleSuccessfulRequest(request);
119 searchId = response.getResult(ID);
120 results.clear();
121 return _waitForSearchResults();
122 });
123 }
124
125 void findResult(SearchResultKind kind, String file, int offset, int length,
126 bool expected) {
127 for (SearchResult result in results) {
128 Location location = result.location;
129 if (result.kind == kind &&
130 location.file == file &&
131 location.offset == offset &&
132 location.length == length) {
133 if (!expected) {
134 fail('Unexpected result $result in\n' + results.join('\n'));
135 }
136 this.result = result;
137 return;
138 }
139 }
140 if (expected) {
141 fail(
142 'Not found: "search" kind=$kind offset=$offset length=$length\nin\n' +
143 results.join('\n'));
144 }
145 }
146
147 String getPathString(List<Element> path) {
148 return path.map((Element element) {
149 return '${element.kind} ${element.name}';
150 }).join('\n');
151 }
152
153 void processNotification(Notification notification) {
154 if (notification.event == SEARCH_RESULTS) {
155 String id = notification.getParameter(ID);
156 if (id == searchId) {
157 for (Map<String, Object> json in notification.getParameter(RESULTS)) {
158 results.add(new SearchResult.fromJson(json));
159 }
160 searchDone = notification.getParameter(LAST);
161 }
162 }
163 }
164
165 @override
166 void setUp() {
167 super.setUp();
168 createProject();
169 handler = new SearchDomainHandler(server);
170 }
171
172 test_constructor_named() {
173 addTestFile('''
174 class A {
175 A.named(p);
176 }
177 main() {
178 new A.named(1);
179 new A.named(2);
180 }
181 ''');
182 return findElementReferences('named(p)', false).then((_) {
183 assertHasResult(SearchResultKind.REFERENCE, '.named(1)', 6);
184 assertHasResult(SearchResultKind.REFERENCE, '.named(2)', 6);
185 });
186 }
187
188 test_constructor_unamed() {
189 addTestFile('''
190 class A {
191 A(p);
192 }
193 main() {
194 new A(1);
195 new A(2);
196 }
197 ''');
198 return findElementReferences('A(p)', false).then((_) {
199 assertHasResult(SearchResultKind.REFERENCE, '(1)', 0);
200 assertHasResult(SearchResultKind.REFERENCE, '(2)', 0);
201 });
202 }
203
204 test_field_explicit() {
205 addTestFile('''
206 class A {
207 var fff; // declaration
208 A(this.fff); // in constructor
209 m() {
210 fff = 2;
211 fff += 3;
212 print(fff); // in m()
213 fff(); // in m()
214 }
215 }
216 main(A a) {
217 a.fff = 20;
218 a.fff += 30;
219 print(a.fff); // in main()
220 a.fff(); // in main()
221 }
222 ''');
223 return findElementReferences('fff; // declaration', false).then((_) {
224 expect(results, hasLength(10));
225 assertHasResult(SearchResultKind.DECLARATION, 'fff; // declaration');
226 assertHasResult(SearchResultKind.REFERENCE, 'fff); // in constructor');
227 // m()
228 assertHasResult(SearchResultKind.WRITE, 'fff = 2;');
229 assertHasResult(SearchResultKind.WRITE, 'fff += 3;');
230 assertHasResult(SearchResultKind.READ, 'fff); // in m()');
231 assertHasResult(SearchResultKind.INVOCATION, 'fff(); // in m()');
232 // main()
233 assertHasResult(SearchResultKind.WRITE, 'fff = 20;');
234 assertHasResult(SearchResultKind.WRITE, 'fff += 30;');
235 assertHasResult(SearchResultKind.READ, 'fff); // in main()');
236 assertHasResult(SearchResultKind.INVOCATION, 'fff(); // in main()');
237 });
238 }
239
240 test_field_implicit() {
241 addTestFile('''
242 class A {
243 var get fff => null;
244 void set fff(x) {}
245 m() {
246 print(fff); // in m()
247 fff = 1;
248 }
249 }
250 main(A a) {
251 print(a.fff); // in main()
252 a.fff = 10;
253 }
254 ''');
255 var forGetter = findElementReferences('fff =>', false).then((_) {
256 expect(results, hasLength(4));
257 assertHasResult(SearchResultKind.READ, 'fff); // in m()');
258 assertHasResult(SearchResultKind.WRITE, 'fff = 1;');
259 assertHasResult(SearchResultKind.READ, 'fff); // in main()');
260 assertHasResult(SearchResultKind.WRITE, 'fff = 10;');
261 });
262 var forSetter = findElementReferences('fff(x) {}', false).then((_) {
263 expect(results, hasLength(4));
264 assertHasResult(SearchResultKind.READ, 'fff); // in m()');
265 assertHasResult(SearchResultKind.WRITE, 'fff = 1;');
266 assertHasResult(SearchResultKind.READ, 'fff); // in main()');
267 assertHasResult(SearchResultKind.WRITE, 'fff = 10;');
268 });
269 return Future.wait([forGetter, forSetter]);
270 }
271
272 test_field_inFormalParameter() {
273 addTestFile('''
274 class A {
275 var fff; // declaration
276 A(this.fff); // in constructor
277 m() {
278 fff = 2;
279 print(fff); // in m()
280 }
281 }
282 ''');
283 return findElementReferences('fff); // in constructor', false).then((_) {
284 expect(results, hasLength(4));
285 assertHasResult(SearchResultKind.DECLARATION, 'fff; // declaration');
286 assertHasResult(SearchResultKind.REFERENCE, 'fff); // in constructor');
287 assertHasResult(SearchResultKind.WRITE, 'fff = 2;');
288 assertHasResult(SearchResultKind.READ, 'fff); // in m()');
289 });
290 }
291
292 test_function() {
293 addTestFile('''
294 fff(p) {}
295 main() {
296 fff(1);
297 print(fff);
298 }
299 ''');
300 return findElementReferences('fff(p) {}', false).then((_) {
301 expect(results, hasLength(2));
302 assertHasResult(SearchResultKind.INVOCATION, 'fff(1)');
303 assertHasResult(SearchResultKind.REFERENCE, 'fff);');
304 });
305 }
306
307 test_localVariable() {
308 addTestFile('''
309 main() {
310 var vvv = 1;
311 print(vvv);
312 vvv += 3;
313 vvv = 2;
314 vvv();
315 }
316 ''');
317 return findElementReferences('vvv = 1', false).then((_) {
318 expect(results, hasLength(5));
319 assertHasResult(SearchResultKind.DECLARATION, 'vvv = 1');
320 assertHasResult(SearchResultKind.READ, 'vvv);');
321 assertHasResult(SearchResultKind.READ_WRITE, 'vvv += 3');
322 assertHasResult(SearchResultKind.WRITE, 'vvv = 2');
323 assertHasResult(SearchResultKind.INVOCATION, 'vvv();');
324 });
325 }
326
327 test_method() {
328 addTestFile('''
329 class A {
330 mmm(p) {}
331 m() {
332 mmm(1);
333 print(mmm); // in m()
334 }
335 }
336 main(A a) {
337 a.mmm(10);
338 print(a.mmm); // in main()
339 }
340 ''');
341 return findElementReferences('mmm(p) {}', false).then((_) {
342 expect(results, hasLength(4));
343 assertHasResult(SearchResultKind.INVOCATION, 'mmm(1);');
344 assertHasResult(SearchResultKind.REFERENCE, 'mmm); // in m()');
345 assertHasResult(SearchResultKind.INVOCATION, 'mmm(10);');
346 assertHasResult(SearchResultKind.REFERENCE, 'mmm); // in main()');
347 });
348 }
349
350 test_method_propagatedType() {
351 addTestFile('''
352 class A {
353 mmm(p) {}
354 }
355 main() {
356 var a = new A();
357 a.mmm(10);
358 print(a.mmm);
359 }
360 ''');
361 return findElementReferences('mmm(p) {}', false).then((_) {
362 expect(results, hasLength(2));
363 assertHasResult(SearchResultKind.INVOCATION, 'mmm(10);');
364 assertHasResult(SearchResultKind.REFERENCE, 'mmm);');
365 });
366 }
367
368 test_oneUnit_twoLibraries() {
369 var pathA = '/project/bin/libA.dart';
370 var pathB = '/project/bin/libB.dart';
371 var codeA = '''
372 library lib;
373 part 'test.dart';
374 main() {
375 fff(1);
376 }
377 ''';
378 var codeB = '''
379 library lib;
380 part 'test.dart';
381 main() {
382 fff(2);
383 }
384 ''';
385 addFile(pathA, codeA);
386 addFile(pathB, codeB);
387 addTestFile('''
388 part of lib;
389 fff(p) {}
390 ''');
391 return findElementReferences('fff(p) {}', false).then((_) {
392 expect(results, hasLength(2));
393 findResult(
394 SearchResultKind.INVOCATION,
395 pathA,
396 codeA.indexOf('fff(1)'),
397 3,
398 true);
399 findResult(
400 SearchResultKind.INVOCATION,
401 pathB,
402 codeB.indexOf('fff(2)'),
403 3,
404 true);
405 });
406 }
407
408 test_oneUnit_zeroLibraries() {
409 addTestFile('''
410 part of lib;
411 fff(p) {}
412 main() {
413 fff(10);
414 }
415 ''');
416 return findElementReferences('fff(p) {}', false).then((_) {
417 expect(results, isEmpty);
418 });
419 }
420
421 test_parameter() {
422 addTestFile('''
423 main(ppp) {
424 print(ppp);
425 ppp += 3;
426 ppp = 2;
427 ppp();
428 }
429 ''');
430 return findElementReferences('ppp) {', false).then((_) {
431 expect(results, hasLength(5));
432 assertHasResult(SearchResultKind.DECLARATION, 'ppp) {');
433 assertHasResult(SearchResultKind.READ, 'ppp);');
434 assertHasResult(SearchResultKind.READ_WRITE, 'ppp += 3');
435 assertHasResult(SearchResultKind.WRITE, 'ppp = 2');
436 assertHasResult(SearchResultKind.INVOCATION, 'ppp();');
437 });
438 }
439
440 test_path_inConstructor_named() {
441 addTestFile('''
442 library my_lib;
443 class A {}
444 class B {
445 B.named() {
446 A a = null;
447 }
448 }
449 ''');
450 return findElementReferences('A {}', false).then((_) {
451 assertHasResult(SearchResultKind.REFERENCE, 'A a = null;');
452 expect(getPathString(result.path), '''
453 LOCAL_VARIABLE a
454 CONSTRUCTOR named
455 CLASS B
456 COMPILATION_UNIT test.dart
457 LIBRARY my_lib''');
458 });
459 }
460
461 test_path_inConstructor_unnamed() {
462 addTestFile('''
463 library my_lib;
464 class A {}
465 class B {
466 B() {
467 A a = null;
468 }
469 }
470 ''');
471 return findElementReferences('A {}', false).then((_) {
472 assertHasResult(SearchResultKind.REFERENCE, 'A a = null;');
473 expect(getPathString(result.path), '''
474 LOCAL_VARIABLE a
475 CONSTRUCTOR
476 CLASS B
477 COMPILATION_UNIT test.dart
478 LIBRARY my_lib''');
479 });
480 }
481
482 test_path_inFunction() {
483 addTestFile('''
484 library my_lib;
485 class A {}
486 main() {
487 A a = null;
488 }
489 ''');
490 return findElementReferences('A {}', false).then((_) {
491 assertHasResult(SearchResultKind.REFERENCE, 'A a = null;');
492 expect(getPathString(result.path), '''
493 LOCAL_VARIABLE a
494 FUNCTION main
495 COMPILATION_UNIT test.dart
496 LIBRARY my_lib''');
497 });
498 }
499
500 test_potential_disabled() {
501 addTestFile('''
502 class A {
503 test(p) {}
504 }
505 main(A a, p) {
506 a.test(1);
507 p.test(2);
508 }
509 ''');
510 return findElementReferences('test(p) {}', false).then((_) {
511 assertHasResult(SearchResultKind.INVOCATION, 'test(1);');
512 assertNoResult(SearchResultKind.INVOCATION, 'test(2);');
513 });
514 }
515
516 test_potential_field() {
517 addTestFile('''
518 class A {
519 test; // declaration
520 }
521 main(A a, p) {
522 a.test = 1;
523 p.test = 2;
524 print(p.test); // p
525 }
526 ''');
527 return findElementReferences('test; // declaration', true).then((_) {
528 {
529 assertHasResult(SearchResultKind.WRITE, 'test = 1;');
530 expect(result.isPotential, isFalse);
531 }
532 {
533 assertHasResult(SearchResultKind.WRITE, 'test = 2;');
534 expect(result.isPotential, isTrue);
535 }
536 {
537 assertHasResult(SearchResultKind.READ, 'test); // p');
538 expect(result.isPotential, isTrue);
539 }
540 });
541 }
542
543 test_potential_method() {
544 addTestFile('''
545 class A {
546 test(p) {}
547 }
548 main(A a, p) {
549 a.test(1);
550 p.test(2);
551 }
552 ''');
553 return findElementReferences('test(p) {}', true).then((_) {
554 {
555 assertHasResult(SearchResultKind.INVOCATION, 'test(1);');
556 expect(result.isPotential, isFalse);
557 }
558 {
559 assertHasResult(SearchResultKind.INVOCATION, 'test(2);');
560 expect(result.isPotential, isTrue);
561 }
562 });
563 }
564
565 test_topLevelVariable_explicit() {
566 addTestFile('''
567 var vvv = 1;
568 main() {
569 print(vvv);
570 vvv += 3;
571 vvv = 2;
572 vvv();
573 }
574 ''');
575 return findElementReferences('vvv = 1', false).then((_) {
576 expect(results, hasLength(5));
577 assertHasResult(SearchResultKind.DECLARATION, 'vvv = 1;');
578 assertHasResult(SearchResultKind.READ, 'vvv);');
579 assertHasResult(SearchResultKind.WRITE, 'vvv += 3');
580 assertHasResult(SearchResultKind.WRITE, 'vvv = 2');
581 assertHasResult(SearchResultKind.INVOCATION, 'vvv();');
582 });
583 }
584
585 test_topLevelVariable_implicit() {
586 addTestFile('''
587 get vvv => null;
588 set vvv(x) {}
589 main() {
590 print(vvv);
591 vvv = 1;
592 }
593 ''');
594 var forGetter = findElementReferences('vvv =>', false).then((_) {
595 expect(results, hasLength(2));
596 assertHasResult(SearchResultKind.READ, 'vvv);');
597 assertHasResult(SearchResultKind.WRITE, 'vvv = 1;');
598 });
599 var forSetter = findElementReferences('vvv(x) {}', false).then((_) {
600 expect(results, hasLength(2));
601 assertHasResult(SearchResultKind.READ, 'vvv);');
602 assertHasResult(SearchResultKind.WRITE, 'vvv = 1;');
603 });
604 return Future.wait([forGetter, forSetter]);
605 }
606
607 test_typeReference_class() {
608 addTestFile('''
609 main() {
610 int a = 1;
611 int b = 2;
612 }
613 ''');
614 return findElementReferences('int a', false).then((_) {
615 assertHasResult(SearchResultKind.REFERENCE, 'int a');
616 assertHasResult(SearchResultKind.REFERENCE, 'int b');
617 });
618 }
619
620 test_typeReference_functionType() {
621 addTestFile('''
622 typedef F();
623 main(F f) {
624 }
625 ''');
626 return findElementReferences('F()', false).then((_) {
627 expect(results, hasLength(1));
628 assertHasResult(SearchResultKind.REFERENCE, 'F f');
629 });
630 }
631
632 test_typeReference_typeVariable() {
633 addTestFile('''
634 class A<T> {
635 T f;
636 T m() => null;
637 }
638 ''');
639 return findElementReferences('T> {', false).then((_) {
640 expect(results, hasLength(2));
641 assertHasResult(SearchResultKind.REFERENCE, 'T f;');
642 assertHasResult(SearchResultKind.REFERENCE, 'T m()');
643 });
644 }
645
646 Future _waitForSearchResults() {
647 if (searchDone) {
648 return new Future.value();
649 }
650 return new Future.delayed(Duration.ZERO, _waitForSearchResults);
651 }
652 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698