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

Side by Side Diff: pkg/analyzer2dart/test/identifier_semantics_test.dart

Issue 587323004: Classify method and property accesses semantically. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 3 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 import 'package:unittest/unittest.dart';
6 import 'package:analyzer/file_system/memory_file_system.dart';
7 import 'mock_sdk.dart';
8 import 'package:analyzer/src/generated/sdk.dart';
9 import 'package:analyzer/file_system/file_system.dart';
10 import 'package:analyzer/src/generated/source.dart';
11 import 'package:analyzer/src/generated/engine.dart';
12 import 'package:analyzer/src/generated/element.dart';
13 import 'package:analyzer/src/generated/source_io.dart';
14 import 'package:analyzer/analyzer.dart';
15 import 'package:analyzer2dart/src/identifier_semantics.dart';
16
17 main() {
18 test('Call function defined at top level', () {
19 Helper helper = new Helper('''
20 g() {}
21
22 f() {
23 g();
24 }
25 ''');
26 helper.checkStaticMethodInvocation('g()', null, 'g', true);
27 });
28
29 test('Call function defined at top level via prefix', () {
30 Helper helper = new Helper('''
31 import 'lib.dart' as l;
32
33 f() {
34 l.g();
35 }
36 ''');
37 helper.addFile('/lib.dart', '''
38 library lib;
39
40 g() {}
41 ''');
42 helper.checkStaticMethodInvocation('l.g()', null, 'g', true);
43 });
44
45 test('Call method defined statically in class from inside class', () {
46 Helper helper = new Helper('''
47 class A {
48 static g() {}
49
50 f() {
51 g();
52 }
53 }
54 ''');
55 helper.checkStaticMethodInvocation('g()', 'A', 'g', true);
56 });
57
58 test('Call method defined statically in class from outside class', () {
59 Helper helper = new Helper('''
60 class A {
61 static g() {}
62 }
63 f() {
64 A.g();
65 }
66 ''');
67 helper.checkStaticMethodInvocation('A.g()', 'A', 'g', true);
68 });
69
70 test('Call method defined dynamically in class from inside class', () {
71 Helper helper = new Helper('''
72 class A {
73 g() {}
74
75 f() {
76 g();
77 }
78 }
79 ''');
80 helper.checkDynamicMethodInvocation('g()', null, 'g');
81 });
82
83 test(
84 'Call method defined dynamically in class from outside class via typed var ',
85 () {
86 Helper helper = new Helper('''
87 class A {
88 g() {}
89 }
90 f(A a) {
91 a.g();
92 }
93 ''');
94 helper.checkDynamicMethodInvocation('a.g()', 'a', 'g');
95 });
96
97 test(
98 'Call method defined dynamically in class from outside class via typed exp ression',
99 () {
100 Helper helper = new Helper('''
101 class A {
102 g() {}
103 }
104 A h() => null;
105 f() {
106 h().g();
107 }
108 ''');
109 helper.checkDynamicMethodInvocation('h().g()', 'h()', 'g');
110 });
111
112 test(
113 'Call method defined dynamically in class from outside class via dynamic v ar',
114 () {
115 Helper helper = new Helper('''
116 f(a) {
117 a.g();
118 }
119 ''');
120 helper.checkDynamicMethodInvocation('a.g()', 'a', 'g');
121 });
122
123 test(
124 'Call method defined dynamically in class from outside class via dynamic e xpression',
125 () {
126 Helper helper = new Helper('''
127 h() => null;
128 f() {
129 h().g();
130 }
131 ''');
132 helper.checkDynamicMethodInvocation('h().g()', 'h()', 'g');
133 });
134
135 test('Call method defined locally', () {
136 Helper helper = new Helper('''
137 f() {
138 g() {}
139 g();
140 }
141 ''');
142 helper.checkLocalFunctionInvocation('g()', 'g');
143 });
144
145 test('Call method undefined at top level', () {
146 Helper helper = new Helper('''
147 f() {
148 g();
149 }
150 ''');
151 // Undefined top level invocations are treated as DynamicMethodInvocation.
152 // TODO(paulberry): not sure if this is a good idea. In general, when such
153 // a call appears inside an instance method, it is dynamic, because "this"
154 // might be an instance of a derived class that implements g(). However,
155 // in this case, we are not inside an instance method, so we know that the
156 // target is undefined.
157 helper.checkDynamicMethodInvocation('g()', null, 'g');
158 });
159
160 test('Call method undefined at top level via prefix', () {
161 Helper helper = new Helper('''
162 import 'lib.dart' as l;
163
164 f() {
165 l.g();
166 }
167 ''');
168 helper.addFile('/lib.dart', '''
169 library lib;
170 ''');
171 // Undefined top level invocations are treated as DynamicMethodInvocation.
172 // TODO(paulberry): not sure if this is a good idea, for similar reasons to
173 // the case above.
174 helper.checkDynamicMethodInvocation('l.g()', null, 'g');
175 });
176
177 test('Call method undefined statically in class from outside class', () {
178 Helper helper = new Helper('''
179 class A {}
180
181 f() {
182 A.g();
183 }
184 ''');
185 helper.checkStaticMethodInvocation('A.g()', 'A', 'g', false);
186 });
187
188 test('Call method undefined dynamically in class from inside class', () {
189 Helper helper = new Helper('''
190 class A {
191 f() {
192 g();
193 }
194 }
195 ''');
196 helper.checkDynamicMethodInvocation('g()', null, 'g');
197 });
198
199 test(
200 'Call method undefined dynamically in class from outside class via typed v ar',
201 () {
202 Helper helper = new Helper('''
203 class A {}
204
205 f(A a) {
206 a.g();
207 }
208 ''');
209 helper.checkDynamicMethodInvocation('a.g()', 'a', 'g');
210 });
211
212 test(
213 'Call method undefined dynamically in class from outside class via typed e xpression',
214 () {
215 Helper helper = new Helper('''
216 class A {}
217
218 A h() => null;
219
220 f() {
221 h().g();
222 }
223 ''');
224 helper.checkDynamicMethodInvocation('h().g()', 'h()', 'g');
225 });
226
227 test('Get variable defined at top level', () {
228 Helper helper = new Helper('''
229 var x;
230
231 f() {
232 return x;
233 }
234 ''');
235 helper.checkStaticFieldElementRef('x', null, 'x', true, false);
236 });
237
238 test('Get variable defined at top level via prefix', () {
239 Helper helper = new Helper('''
240 import 'lib.dart' as l;
241
242 f() {
243 return l.x;
244 }
245 ''');
246 helper.addFile('/lib.dart', '''
247 library lib;
248
249 var x;
250 ''');
251 helper.checkStaticFieldElementRef('l.x', null, 'x', true, false);
252 });
253
254 test('Get field defined statically in class from inside class', () {
255 Helper helper = new Helper('''
256 class A {
257 static var x;
258
259 f() {
260 return x;
261 }
262 }
263 ''');
264 helper.checkStaticFieldElementRef('x', 'A', 'x', true, false);
265 });
266
267 test('Get field defined statically in class from outside class', () {
268 Helper helper = new Helper('''
269 class A {
270 static var x;
271 }
272
273 f() {
274 return A.x;
275 }
276 ''');
277 helper.checkStaticFieldElementRef('A.x', 'A', 'x', true, false);
278 });
279
280 test('Get field defined dynamically in class from inside class', () {
281 Helper helper = new Helper('''
282 class A {
283 var x;
284
285 f() {
286 return x;
287 }
288 }
289 ''');
290 helper.checkDynamicPropertyAccess('x', null, 'x', true, false);
291 });
292
293 test(
294 'Get field defined dynamically in class from outside class via typed var',
295 () {
296 Helper helper = new Helper('''
297 class A {
298 var x;
299 }
300
301 f(A a) {
302 return a.x;
303 }
304 ''');
305 helper.checkDynamicPropertyAccess('a.x', 'a', 'x', true, false);
306 });
307
308 test(
309 'Get field defined dynamically in class from outside class via typed expre ssion',
310 () {
311 Helper helper = new Helper('''
312 class A {
313 var x;
314 }
315
316 A h() => null;
317
318 f() {
319 return h().x;
320 }
321 ''');
322 helper.checkDynamicPropertyAccess('h().x', 'h()', 'x', true, false);
323 });
324
325 test(
326 'Get field defined dynamically in class from outside class via dynamic var ',
327 () {
328 Helper helper = new Helper('''
329 f(a) {
330 return a.x;
331 }
332 ''');
333 helper.checkDynamicPropertyAccess('a.x', 'a', 'x', true, false);
334 });
335
336 test(
337 'Get field defined dynamically in class from outside class via dynamic exp ression',
338 () {
339 Helper helper = new Helper('''
340 h() => null;
341
342 f() {
343 return h().x;
344 }
345 ''');
346 helper.checkDynamicPropertyAccess('h().x', 'h()', 'x', true, false);
347 });
348
349 test('Get variable defined locally', () {
350 Helper helper = new Helper('''
351 f() {
352 var x;
353 return x;
354 }
355 ''');
356 helper.checkLocalVariableAccess('x', true, false);
357 });
358
359 test('Get accessor defined at top level', () {
360 Helper helper = new Helper('''
361 get x => null;
362
363 f() {
364 return x;
365 }
366 ''');
367 helper.checkStaticPropertyAccess('x', null, 'x', true, true, false);
368 });
369
370 test('Get accessor defined at top level via prefix', () {
371 Helper helper = new Helper('''
372 import 'lib.dart' as l;
373
374 f() {
375 return l.x;
376 }
377 ''');
378 helper.addFile('/lib.dart', '''
379 library lib;
380
381 get x => null;
382 ''');
383 helper.checkStaticPropertyAccess('l.x', null, 'x', true, true, false);
384 });
385
386 test('Get accessor defined statically in class from inside class', () {
387 Helper helper = new Helper('''
388 class A {
389 static get x => null;
390
391 f() {
392 return x;
393 }
394 }
395 ''');
396 helper.checkStaticPropertyAccess('x', 'A', 'x', true, true, false);
397 });
398
399 test('Get accessor defined statically in class from outside class', () {
400 Helper helper = new Helper('''
401 class A {
402 static get x => null;
403 }
404
405 f() {
406 return A.x;
407 }
408 ''');
409 helper.checkStaticPropertyAccess('A.x', 'A', 'x', true, true, false);
410 });
411
412 test('Get accessor defined dynamically in class from inside class', () {
413 Helper helper = new Helper('''
414 class A {
415 get x => null;
416
417 f() {
418 return x;
419 }
420 }
421 ''');
422 helper.checkDynamicPropertyAccess('x', null, 'x', true, false);
423 });
424
425 test(
426 'Get accessor defined dynamically in class from outside class via typed va r',
427 () {
428 Helper helper = new Helper('''
429 class A {
430 get x => null;
431 }
432
433 f(A a) {
434 return a.x;
435 }
436 ''');
437 helper.checkDynamicPropertyAccess('a.x', 'a', 'x', true, false);
438 });
439
440 test(
441 'Get accessor defined dynamically in class from outside class via typed ex pression',
442 () {
443 Helper helper = new Helper('''
444 class A {
445 get x => null;
446 }
447
448 A h() => null;
449
450 f() {
451 return h().x;
452 }
453 ''');
454 helper.checkDynamicPropertyAccess('h().x', 'h()', 'x', true, false);
455 });
456
457 test(
458 'Get accessor defined dynamically in class from outside class via dynamic var',
459 () {
460 Helper helper = new Helper('''
461 f(a) {
462 return a.x;
463 }
464 ''');
465 helper.checkDynamicPropertyAccess('a.x', 'a', 'x', true, false);
466 });
467
468 test(
469 'Get accessor defined dynamically in class from outside class via dynamic expression',
470 () {
471 Helper helper = new Helper('''
472 h() => null;
473
474 f() {
475 return h().x;
476 }
477 ''');
478 helper.checkDynamicPropertyAccess('h().x', 'h()', 'x', true, false);
479 });
480
481 test('Get accessor undefined at top level', () {
482 Helper helper = new Helper('''
483 f() {
484 return x;
485 }
486 ''');
487 // Undefined top level property accesses are treated as
488 // DynamicPropertyAccess. TODO(paulberry): not sure if this is a good
489 // idea. In general, when such an access appears inside an instance
490 // method, it is dynamic, because "this" might be an instance of a derived
491 // class that implements x. However, in this case, we are not inside an
492 // instance method, so we know that the target is undefined.
493 helper.checkDynamicPropertyAccess('x', null, 'x', true, false);
494 });
495
496 test('Get accessor undefined at top level via prefix', () {
497 Helper helper = new Helper('''
498 import 'lib.dart' as l;
499
500 f() {
501 return l.x;
502 }
503 ''');
504 helper.addFile('/lib.dart', '''
505 library lib;
506 ''');
507 // Undefined top level property accesses are treated as
508 // DynamicPropertyAccess. TODO(paulberry): not sure if this is a good
509 // idea, for similar reasons to the case above.
510 helper.checkDynamicPropertyAccess('l.x', null, 'x', true, false);
511 });
512
513 test('Get accessor undefined statically in class from outside class', () {
514 Helper helper = new Helper('''
515 class A {}
516
517 f() {
518 return A.x;
519 }
520 ''');
521 helper.checkStaticPropertyAccess('A.x', 'A', 'x', false, true, false);
522 });
523
524 test('Get accessor undefined dynamically in class from inside class', () {
525 Helper helper = new Helper('''
526 class A {
527 f() {
528 return x;
529 }
530 }
531 ''');
532 helper.checkDynamicPropertyAccess('x', null, 'x', true, false);
533 });
534
535 test(
536 'Get accessor undefined dynamically in class from outside class via typed var',
537 () {
538 Helper helper = new Helper('''
539 class A {}
540
541 f(A a) {
542 return a.x;
543 }
544 ''');
545 helper.checkDynamicPropertyAccess('a.x', 'a', 'x', true, false);
546 });
547
548 test(
549 'Get accessor undefined dynamically in class from outside class via typed expression',
550 () {
551 Helper helper = new Helper('''
552 class A {}
553
554 A h() => null;
555
556 f() {
557 return h().x;
558 }
559 ''');
560 helper.checkDynamicPropertyAccess('h().x', 'h()', 'x', true, false);
561 });
562
563 test('Set variable defined at top level', () {
564 Helper helper = new Helper('''
565 var x;
566
567 f() {
568 x = 1;
569 }
570 ''');
571 helper.checkStaticFieldElementRef('x', null, 'x', false, true);
572 });
573
574 test('Set variable defined at top level via prefix', () {
575 Helper helper = new Helper('''
576 import 'lib.dart' as l;
577
578 f() {
579 l.x = 1;
580 }
581 ''');
582 helper.addFile('/lib.dart', '''
583 library lib;
584
585 var x;
586 ''');
587 helper.checkStaticFieldElementRef('l.x', null, 'x', false, true);
588 });
589
590 test('Set field defined statically in class from inside class', () {
591 Helper helper = new Helper('''
592 class A {
593 static var x;
594
595 f() {
596 x = 1;
597 }
598 }
599 ''');
600 helper.checkStaticFieldElementRef('x', 'A', 'x', false, true);
601 });
602
603 test('Set field defined statically in class from outside class', () {
604 Helper helper = new Helper('''
605 class A {
606 static var x;
607 }
608
609 f() {
610 A.x = 1;
611 }
612 ''');
613 helper.checkStaticFieldElementRef('A.x', 'A', 'x', false, true);
614 });
615
616 test('Set field defined dynamically in class from inside class', () {
617 Helper helper = new Helper('''
618 class A {
619 var x;
620
621 f() {
622 x = 1;
623 }
624 }
625 ''');
626 helper.checkDynamicPropertyAccess('x', null, 'x', false, true);
627 });
628
629 test(
630 'Set field defined dynamically in class from outside class via typed var',
631 () {
632 Helper helper = new Helper('''
633 class A {
634 var x;
635 }
636
637 f(A a) {
638 a.x = 1;
639 }
640 ''');
641 helper.checkDynamicPropertyAccess('a.x', 'a', 'x', false, true);
642 });
643
644 test(
645 'Set field defined dynamically in class from outside class via typed expre ssion',
646 () {
647 Helper helper = new Helper('''
648 class A {
649 var x;
650 }
651
652 A h() => null;
653
654 f() {
655 h().x = 1;
656 }
657 ''');
658 helper.checkDynamicPropertyAccess('h().x', 'h()', 'x', false, true);
659 });
660
661 test('Set variable defined locally', () {
662 Helper helper = new Helper('''
663 f() {
664 var x;
665 x = 1;
666 }
667 ''');
668 helper.checkLocalVariableAccess('x', false, true);
669 });
670
671 test('Set accessor defined at top level', () {
672 Helper helper = new Helper('''
673 set x(value) {};
674
675 f() {
676 x = 1;
677 }
678 ''');
679 helper.checkStaticPropertyAccess('x', null, 'x', true, false, true);
680 });
681
682 test('Set accessor defined at top level via prefix', () {
683 Helper helper = new Helper('''
684 import 'lib.dart' as l;
685
686 f() {
687 l.x = 1;
688 }
689 ''');
690 helper.addFile('/lib.dart', '''
691 library lib;
692
693 set x(value) {};
694 ''');
695 helper.checkStaticPropertyAccess('l.x', null, 'x', true, false, true);
696 });
697
698 test('Set accessor defined statically in class from inside class', () {
699 Helper helper = new Helper('''
700 class A {
701 static set x(value) {}
702
703 f() {
704 x = 1;
705 }
706 }
707 ''');
708 helper.checkStaticPropertyAccess('x', 'A', 'x', true, false, true);
709 });
710
711 test('Set accessor defined statically in class from outside class', () {
712 Helper helper = new Helper('''
713 class A {
714 static set x(value) {}
715 }
716
717 f() {
718 A.x = 1;
719 }
720 ''');
721 helper.checkStaticPropertyAccess('A.x', 'A', 'x', true, false, true);
722 });
723
724 test('Set accessor defined dynamically in class from inside class', () {
725 Helper helper = new Helper('''
726 class A {
727 set x(value) {}
728
729 f() {
730 x = 1;
731 }
732 }
733 ''');
734 helper.checkDynamicPropertyAccess('x', null, 'x', false, true);
735 });
736
737 test(
738 'Set accessor defined dynamically in class from outside class via typed va r',
739 () {
740 Helper helper = new Helper('''
741 class A {
742 set x(value) {}
743 }
744
745 f(A a) {
746 a.x = 1;
747 }
748 ''');
749 helper.checkDynamicPropertyAccess('a.x', 'a', 'x', false, true);
750 });
751
752 test(
753 'Set accessor defined dynamically in class from outside class via typed ex pression',
754 () {
755 Helper helper = new Helper('''
756 class A {
757 set x(value) {}
758 }
759
760 A h() => null;
761
762 f() {
763 h().x = 1;
764 }
765 ''');
766 helper.checkDynamicPropertyAccess('h().x', 'h()', 'x', false, true);
767 });
768
769 test(
770 'Set accessor defined dynamically in class from outside class via dynamic var',
771 () {
772 Helper helper = new Helper('''
773 f(a) {
774 a.x = 1;
775 }
776 ''');
777 helper.checkDynamicPropertyAccess('a.x', 'a', 'x', false, true);
778 });
779
780 test(
781 'Set accessor defined dynamically in class from outside class via dynamic expression',
782 () {
783 Helper helper = new Helper('''
784 h() => null;
785
786 f() {
787 h().x = 1;
788 }
789 ''');
790 helper.checkDynamicPropertyAccess('h().x', 'h()', 'x', false, true);
791 });
792
793 test('Set accessor undefined at top level', () {
794 Helper helper = new Helper('''
795 f() {
796 x = 1;
797 }
798 ''');
799 helper.checkDynamicPropertyAccess('x', null, 'x', false, true);
800 });
801
802 test('Set accessor undefined at top level via prefix', () {
803 Helper helper = new Helper('''
804 import 'lib.dart' as l;
805
806 f() {
807 l.x = 1;
808 }
809 ''');
810 helper.addFile('/lib.dart', '''
811 library lib;
812 ''');
813 helper.checkDynamicPropertyAccess('l.x', null, 'x', false, true);
814 });
815
816 test('Set accessor undefined statically in class from outside class', () {
817 Helper helper = new Helper('''
818 class A {}
819
820 f() {
821 A.x = 1;
822 }
823 ''');
824 helper.checkStaticPropertyAccess('A.x', 'A', 'x', false, false, true);
825 });
826
827 test('Set accessor undefined dynamically in class from inside class', () {
828 Helper helper = new Helper('''
829 class A {
830 f() {
831 x = 1;
832 }
833 }
834 ''');
835 helper.checkDynamicPropertyAccess('x', null, 'x', false, true);
836 });
837
838 test(
839 'Set accessor undefined dynamically in class from outside class via typed var',
840 () {
841 Helper helper = new Helper('''
842 class A {}
843
844 f(A a) {
845 a.x = 1;
846 }
847 ''');
848 helper.checkDynamicPropertyAccess('a.x', 'a', 'x', false, true);
849 });
850
851 test(
852 'Set accessor undefined dynamically in class from outside class via typed expression',
853 () {
854 Helper helper = new Helper('''
855 class A {}
856
857 A h() => null;
858
859 f() {
860 h().x = 1;
861 }
862 ''');
863 helper.checkDynamicPropertyAccess('h().x', 'h()', 'x', false, true);
864 });
865
866 test('RMW variable defined at top level', () {
867 Helper helper = new Helper('''
868 var x;
869
870 f() {
871 x += 1;
872 }
873 ''');
874 helper.checkStaticFieldElementRef('x', null, 'x', true, true);
875 });
876
877 test('RMW variable defined at top level via prefix', () {
878 Helper helper = new Helper('''
879 import 'lib.dart' as l;
880
881 f() {
882 l.x += 1;
883 }
884 ''');
885 helper.addFile('/lib.dart', '''
886 library lib;
887
888 var x;
889 ''');
890 helper.checkStaticFieldElementRef('l.x', null, 'x', true, true);
891 });
892
893 test('RMW field defined statically in class from inside class', () {
894 Helper helper = new Helper('''
895 class A {
896 static var x;
897
898 f() {
899 x += 1;
900 }
901 }
902 ''');
903 helper.checkStaticFieldElementRef('x', 'A', 'x', true, true);
904 });
905
906 test('RMW field defined statically in class from outside class', () {
907 Helper helper = new Helper('''
908 class A {
909 static var x;
910 }
911
912 f() {
913 A.x += 1;
914 }
915 ''');
916 helper.checkStaticFieldElementRef('A.x', 'A', 'x', true, true);
917 });
918
919 test('RMW field defined dynamically in class from inside class', () {
920 Helper helper = new Helper('''
921 class A {
922 var x;
923
924 f() {
925 x += 1;
926 }
927 }
928 ''');
929 helper.checkDynamicPropertyAccess('x', null, 'x', true, true);
930 });
931
932 test(
933 'RMW field defined dynamically in class from outside class via typed var',
934 () {
935 Helper helper = new Helper('''
936 class A {
937 var x;
938 }
939
940 f(A a) {
941 a.x += 1;
942 }
943 ''');
944 helper.checkDynamicPropertyAccess('a.x', 'a', 'x', true, true);
945 });
946
947 test(
948 'RMW field defined dynamically in class from outside class via typed expre ssion',
949 () {
950 Helper helper = new Helper('''
951 class A {
952 var x;
953 }
954
955 A h() => null;
956
957 f() {
958 h().x += 1;
959 }
960 ''');
961 helper.checkDynamicPropertyAccess('h().x', 'h()', 'x', true, true);
962 });
963
964 test('RMW variable defined locally', () {
965 Helper helper = new Helper('''
966 f() {
967 var x;
968 x += 1;
969 }
970 ''');
971 helper.checkLocalVariableAccess('x', true, true);
972 });
973
974 test('RMW accessor defined at top level', () {
975 Helper helper = new Helper('''
976 set x(value) {};
977
978 f() {
979 x += 1;
980 }
981 ''');
982 helper.checkStaticPropertyAccess('x', null, 'x', true, true, true);
983 });
984
985 test('RMW accessor defined at top level via prefix', () {
986 Helper helper = new Helper('''
987 import 'lib.dart' as l;
988
989 f() {
990 l.x += 1;
991 }
992 ''');
993 helper.addFile('/lib.dart', '''
994 library lib;
995
996 set x(value) {};
997 ''');
998 helper.checkStaticPropertyAccess('l.x', null, 'x', true, true, true);
999 });
1000
1001 test('RMW accessor defined statically in class from inside class', () {
1002 Helper helper = new Helper('''
1003 class A {
1004 static set x(value) {}
1005
1006 f() {
1007 x += 1;
1008 }
1009 }
1010 ''');
1011 helper.checkStaticPropertyAccess('x', 'A', 'x', true, true, true);
1012 });
1013
1014 test('RMW accessor defined statically in class from outside class', () {
1015 Helper helper = new Helper('''
1016 class A {
1017 static set x(value) {}
1018 }
1019
1020 f() {
1021 A.x += 1;
1022 }
1023 ''');
1024 helper.checkStaticPropertyAccess('A.x', 'A', 'x', true, true, true);
1025 });
1026
1027 test('RMW accessor defined dynamically in class from inside class', () {
1028 Helper helper = new Helper('''
1029 class A {
1030 set x(value) {}
1031
1032 f() {
1033 x += 1;
1034 }
1035 }
1036 ''');
1037 helper.checkDynamicPropertyAccess('x', null, 'x', true, true);
1038 });
1039
1040 test(
1041 'RMW accessor defined dynamically in class from outside class via typed va r',
1042 () {
1043 Helper helper = new Helper('''
1044 class A {
1045 set x(value) {}
1046 }
1047
1048 f(A a) {
1049 a.x += 1;
1050 }
1051 ''');
1052 helper.checkDynamicPropertyAccess('a.x', 'a', 'x', true, true);
1053 });
1054
1055 test(
1056 'RMW accessor defined dynamically in class from outside class via typed ex pression',
1057 () {
1058 Helper helper = new Helper('''
1059 class A {
1060 set x(value) {}
1061 }
1062
1063 A h() => null;
1064
1065 f() {
1066 h().x += 1;
1067 }
1068 ''');
1069 helper.checkDynamicPropertyAccess('h().x', 'h()', 'x', true, true);
1070 });
1071
1072 test(
1073 'RMW accessor defined dynamically in class from outside class via dynamic var',
1074 () {
1075 Helper helper = new Helper('''
1076 f(a) {
1077 a.x += 1;
1078 }
1079 ''');
1080 helper.checkDynamicPropertyAccess('a.x', 'a', 'x', true, true);
1081 });
1082
1083 test(
1084 'RMW accessor defined dynamically in class from outside class via dynamic expression',
1085 () {
1086 Helper helper = new Helper('''
1087 h() => null;
1088
1089 f() {
1090 h().x += 1;
1091 }
1092 ''');
1093 helper.checkDynamicPropertyAccess('h().x', 'h()', 'x', true, true);
1094 });
1095
1096 test('RMW accessor undefined at top level', () {
1097 Helper helper = new Helper('''
1098 f() {
1099 x += 1;
1100 }
1101 ''');
1102 helper.checkDynamicPropertyAccess('x', null, 'x', true, true);
1103 });
1104
1105 test('RMW accessor undefined at top level via prefix', () {
1106 Helper helper = new Helper('''
1107 import 'lib.dart' as l;
1108
1109 f() {
1110 l.x += 1;
1111 }
1112 ''');
1113 helper.addFile('/lib.dart', '''
1114 library lib;
1115 ''');
1116 helper.checkDynamicPropertyAccess('l.x', null, 'x', true, true);
1117 });
1118
1119 test('RMW accessor undefined statically in class from outside class', () {
1120 Helper helper = new Helper('''
1121 class A {}
1122
1123 f() {
1124 A.x += 1;
1125 }
1126 ''');
1127 helper.checkStaticPropertyAccess('A.x', 'A', 'x', false, true, true);
1128 });
1129
1130 test('RMW accessor undefined dynamically in class from inside class', () {
1131 Helper helper = new Helper('''
1132 class A {
1133 f() {
1134 x += 1;
1135 }
1136 }
1137 ''');
1138 helper.checkDynamicPropertyAccess('x', null, 'x', true, true);
1139 });
1140
1141 test(
1142 'RMW accessor undefined dynamically in class from outside class via typed var',
1143 () {
1144 Helper helper = new Helper('''
1145 class A {}
1146
1147 f(A a) {
1148 a.x += 1;
1149 }
1150 ''');
1151 helper.checkDynamicPropertyAccess('a.x', 'a', 'x', true, true);
1152 });
1153
1154 test(
1155 'RMW accessor undefined dynamically in class from outside class via typed expression',
1156 () {
1157 Helper helper = new Helper('''
1158 class A {}
1159
1160 A h() => null;
1161
1162 f() {
1163 h().x += 1;
1164 }
1165 ''');
1166 helper.checkDynamicPropertyAccess('h().x', 'h()', 'x', true, true);
1167 });
1168 }
1169
1170 class Helper {
1171 final MemoryResourceProvider provider = new MemoryResourceProvider();
1172 Source rootSource;
1173 AnalysisContext context;
1174
1175 Helper(String rootContents) {
1176 DartSdk sdk = new MockSdk();
1177 String rootFile = '/root.dart';
1178 File file = provider.newFile(rootFile, rootContents);
1179 rootSource = file.createSource();
1180 context = AnalysisEngine.instance.createAnalysisContext();
1181 // Set up the source factory.
1182 List<UriResolver> uriResolvers = [
1183 new ResourceUriResolver(provider),
1184 new DartUriResolver(sdk)];
1185 context.sourceFactory = new SourceFactory(uriResolvers);
1186 // add the Source
1187 ChangeSet changeSet = new ChangeSet();
1188 changeSet.addedSource(rootSource);
1189 context.applyChanges(changeSet);
1190 }
1191
1192 void addFile(String path, String contents) {
1193 provider.newFile(path, contents);
1194 }
1195
1196 LibraryElement get libraryElement {
1197 return context.computeLibraryElement(rootSource);
1198 }
1199
1200 /**
1201 * Verify that the node represented by [expectedSource] is classified as
1202 * a static field element reference.
1203 */
1204 void checkStaticFieldElementRef(String expectedSource, String expectedClass,
1205 String expectedName, bool expectedIsRead, bool expectedIsWrite) {
1206 TestVisitor visitor = new TestVisitor();
1207 int count = 0;
1208 visitor.onAccess = (Expression node, AccessSemantics semantics) {
1209 count++;
1210 expect(node.toSource(), equals(expectedSource));
1211 expect(semantics, new isInstanceOf<StaticFieldAccess>());
1212 if (semantics is StaticFieldAccess) {
1213 expect(semantics.field.displayName, equals(expectedName));
1214 if (expectedClass == null) {
1215 expect(semantics.classElement, isNull);
1216 } else {
1217 expect(semantics.classElement, isNotNull);
1218 expect(semantics.classElement.displayName, equals(expectedClass));
1219 }
1220 }
1221 expect(semantics.isRead, equals(expectedIsRead));
1222 expect(semantics.isWrite, equals(expectedIsWrite));
1223 };
1224 libraryElement.unit.accept(visitor);
1225 expect(count, equals(1));
1226 }
1227
1228 /**
1229 * Verify that the node represented by [expectedSource] is classified as
1230 * a static property access.
1231 */
1232 void checkStaticPropertyAccess(String expectedSource, String expectedClass,
1233 String expectedName, bool defined, bool expectedIsRead, bool expectedIsWri te) {
1234 TestVisitor visitor = new TestVisitor();
1235 int count = 0;
1236 visitor.onAccess = (Expression node, AccessSemantics semantics) {
1237 count++;
1238 expect(node.toSource(), equals(expectedSource));
1239 expect(semantics, new isInstanceOf<StaticPropertyAccess>());
1240 if (semantics is StaticPropertyAccess) {
1241 expect(semantics.propertyName.name, equals(expectedName));
1242 if (expectedClass == null) {
1243 expect(semantics.classElement, isNull);
1244 } else {
1245 expect(semantics.classElement, isNotNull);
1246 expect(semantics.classElement.displayName, equals(expectedClass));
1247 }
1248 if (defined) {
1249 expect(semantics.property.displayName, equals(expectedName));
1250 } else {
1251 expect(semantics.property, isNull);
1252 }
1253 }
1254 expect(semantics.isRead, equals(expectedIsRead));
1255 expect(semantics.isWrite, equals(expectedIsWrite));
1256 };
1257 libraryElement.unit.accept(visitor);
1258 expect(count, equals(1));
1259 }
1260
1261 /**
1262 * Verify that the node represented by [expectedSource] is classified as
1263 * a static method invocation.
1264 */
1265 void checkStaticMethodInvocation(String expectedSource, String expectedClass,
1266 String expectedName, bool defined) {
1267 TestVisitor visitor = new TestVisitor();
1268 int count = 0;
1269 visitor.onMethodInvocation =
1270 (MethodInvocation node, MethodInvocationSemantics semantics) {
1271 count++;
1272 expect(node.toSource(), equals(expectedSource));
1273 expect(semantics, new isInstanceOf<StaticMethodInvocation>());
1274 if (semantics is StaticMethodInvocation) {
1275 expect(semantics.methodName.name, equals(expectedName));
1276 if (expectedClass == null) {
1277 expect(semantics.classElement, isNull);
1278 if (defined) {
1279 expect(
1280 semantics.methodElement,
1281 new isInstanceOf<FunctionElement>());
1282 }
1283 } else {
1284 expect(semantics.classElement, isNotNull);
1285 expect(semantics.classElement.displayName, equals(expectedClass));
1286 if (defined) {
1287 expect(semantics.methodElement, new isInstanceOf<MethodElement>());
1288 }
1289 }
1290 if (defined) {
1291 expect(semantics.methodElement.displayName, equals(expectedName));
1292 } else {
1293 expect(semantics.methodElement, isNull);
1294 }
1295 }
1296 };
1297 libraryElement.unit.accept(visitor);
1298 expect(count, equals(1));
1299 }
1300
1301 /**
1302 * Verify that the node represented by [expectedSource] is classified as
1303 * a dynamic method invocation.
1304 */
1305 void checkDynamicMethodInvocation(String expectedSource,
1306 String expectedTarget, String expectedName) {
1307 TestVisitor visitor = new TestVisitor();
1308 int count = 0;
1309 visitor.onMethodInvocation =
1310 (MethodInvocation node, MethodInvocationSemantics semantics) {
1311 count++;
1312 expect(node.toSource(), equals(expectedSource));
1313 expect(semantics, new isInstanceOf<DynamicMethodInvocation>());
1314 if (semantics is DynamicMethodInvocation) {
1315 if (expectedTarget == null) {
1316 expect(semantics.target, isNull);
1317 } else {
1318 expect(semantics.target.toSource(), equals(expectedTarget));
1319 }
1320 expect(semantics.methodName.name, equals(expectedName));
1321 }
1322 };
1323 libraryElement.unit.accept(visitor);
1324 expect(count, equals(1));
1325 }
1326
1327 /**
1328 * Verify that the node represented by [expectedSource] is classified as
1329 * a local function invocation.
1330 */
1331 void checkLocalFunctionInvocation(String expectedSource,
1332 String expectedName) {
1333 TestVisitor visitor = new TestVisitor();
1334 int count = 0;
1335 visitor.onMethodInvocation =
1336 (MethodInvocation node, MethodInvocationSemantics semantics) {
1337 count++;
1338 expect(node.toSource(), equals(expectedSource));
1339 expect(semantics, new isInstanceOf<LocalFunctionInvocation>());
1340 if (semantics is LocalFunctionInvocation) {
1341 expect(semantics.functionElement.displayName, equals(expectedName));
1342 }
1343 };
1344 libraryElement.unit.accept(visitor);
1345 expect(count, equals(1));
1346 }
1347
1348 /**
1349 * Verify that the node represented by [expectedSource] is classified as
1350 * a dynamic property access.
1351 */
1352 void checkDynamicPropertyAccess(String expectedSource, String expectedTarget,
1353 String expectedName, bool expectedIsRead, bool expectedIsWrite) {
1354 TestVisitor visitor = new TestVisitor();
1355 int count = 0;
1356 visitor.onAccess = (Expression node, AccessSemantics semantics) {
1357 count++;
1358 expect(node.toSource(), equals(expectedSource));
1359 expect(semantics, new isInstanceOf<DynamicPropertyAccess>());
1360 if (semantics is DynamicPropertyAccess) {
1361 if (expectedTarget == null) {
1362 expect(semantics.target, isNull);
1363 } else {
1364 expect(semantics.target.toSource(), equals(expectedTarget));
1365 }
1366 expect(semantics.propertyName.name, equals(expectedName));
1367 }
1368 expect(semantics.isRead, equals(expectedIsRead));
1369 expect(semantics.isWrite, equals(expectedIsWrite));
1370 };
1371 libraryElement.unit.accept(visitor);
1372 expect(count, equals(1));
1373 }
1374
1375 /**
1376 * Verify that the node represented by [expectedSource] is classified as
1377 * a local variable access.
1378 */
1379 void checkLocalVariableAccess(String expectedName, bool expectedIsRead,
1380 bool expectedIsWrite) {
1381 TestVisitor visitor = new TestVisitor();
1382 int count = 0;
1383 visitor.onAccess = (SimpleIdentifier node, AccessSemantics semantics) {
1384 count++;
1385 expect(node.name, equals(expectedName));
1386 expect(semantics, new isInstanceOf<LocalVariableAccess>());
1387 if (semantics is LocalVariableAccess) {
1388 LocalVariableElement element = semantics.variable;
1389 expect(element.name, equals(expectedName));
1390 }
1391 expect(semantics.isRead, equals(expectedIsRead));
1392 expect(semantics.isWrite, equals(expectedIsWrite));
1393 };
1394 libraryElement.unit.accept(visitor);
1395 expect(count, equals(1));
1396 }
1397 }
1398
1399 typedef void MethodInvocationHandler(MethodInvocation node,
1400 MethodInvocationSemantics semantics);
1401 typedef void AccessHandler(Expression node, AccessSemantics semantics);
1402
1403 /**
1404 * Visitor class used to run the tests.
1405 */
1406 class TestVisitor extends RecursiveAstVisitor {
1407 MethodInvocationHandler onMethodInvocation;
1408 AccessHandler onAccess;
1409
1410 @override
1411 visitMethodInvocation(MethodInvocation node) {
1412 onMethodInvocation(node, classifyMethodInvocation(node));
1413 }
1414
1415 @override
1416 visitPrefixedIdentifier(PrefixedIdentifier node) {
1417 onAccess(node, classifyPrefixedIdentifier(node));
1418 }
1419
1420 @override
1421 visitPropertyAccess(PropertyAccess node) {
1422 onAccess(node, classifyPropertyAccess(node));
1423 }
1424
1425 @override
1426 visitSimpleIdentifier(SimpleIdentifier node) {
1427 AccessSemantics semantics = classifyBareIdentifier(node);
1428 if (semantics != null) {
1429 onAccess(node, semantics);
1430 }
1431 }
1432 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698