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 import 'package:analyzer/analyzer.dart'; | |
6 import 'package:analyzer/file_system/file_system.dart'; | |
7 import 'package:analyzer/file_system/memory_file_system.dart'; | |
8 import 'package:analyzer/src/generated/element.dart'; | |
9 import 'package:analyzer/src/generated/engine.dart'; | |
10 import 'package:analyzer/src/generated/sdk.dart'; | |
11 import 'package:analyzer/src/generated/source.dart'; | |
12 import 'package:analyzer/src/generated/source_io.dart'; | |
13 import 'package:analyzer2dart/src/identifier_semantics.dart'; | |
14 import 'package:unittest/unittest.dart'; | |
15 | |
16 import 'mock_sdk.dart'; | |
17 | |
18 main() { | |
19 test('Call function defined at top level', () { | |
20 Helper helper = new Helper(''' | |
21 g() {} | |
22 | |
23 f() { | |
24 g(); | |
25 } | |
26 '''); | |
27 helper.checkStaticMethod('g()', null, 'g', true, isInvoke: true); | |
28 }); | |
29 | |
30 test('Call function defined at top level via prefix', () { | |
31 Helper helper = new Helper(''' | |
32 import 'lib.dart' as l; | |
33 | |
34 f() { | |
35 l.g(); | |
36 } | |
37 '''); | |
38 helper.addFile('/lib.dart', ''' | |
39 library lib; | |
40 | |
41 g() {} | |
42 '''); | |
43 helper.checkStaticMethod('l.g()', null, 'g', true, isInvoke: true); | |
44 }); | |
45 | |
46 test('Call method defined statically in class from inside class', () { | |
47 Helper helper = new Helper(''' | |
48 class A { | |
49 static g() {} | |
50 | |
51 f() { | |
52 g(); | |
53 } | |
54 } | |
55 '''); | |
56 helper.checkStaticMethod('g()', 'A', 'g', true, isInvoke: true); | |
57 }); | |
58 | |
59 test('Call method defined statically in class from outside class', () { | |
60 Helper helper = new Helper(''' | |
61 class A { | |
62 static g() {} | |
63 } | |
64 f() { | |
65 A.g(); | |
66 } | |
67 '''); | |
68 helper.checkStaticMethod('A.g()', 'A', 'g', true, isInvoke: true); | |
69 }); | |
70 | |
71 test( | |
72 'Call method defined statically in class from outside class via prefix', | |
73 () { | |
74 Helper helper = new Helper(''' | |
75 import 'lib.dart' as l; | |
76 | |
77 f() { | |
78 l.A.g(); | |
79 } | |
80 '''); | |
81 helper.addFile('/lib.dart', ''' | |
82 library lib; | |
83 | |
84 class A { | |
85 static g() {} | |
86 } | |
87 '''); | |
88 helper.checkStaticMethod('l.A.g()', 'A', 'g', true, isInvoke: true); | |
89 }); | |
90 | |
91 test('Call method defined dynamically in class from inside class', () { | |
92 Helper helper = new Helper(''' | |
93 class A { | |
94 g() {} | |
95 | |
96 f() { | |
97 g(); | |
98 } | |
99 } | |
100 '''); | |
101 helper.checkDynamic('g()', null, 'g', isInvoke: true); | |
102 }); | |
103 | |
104 test( | |
105 'Call method defined dynamically in class from outside class via typed var
', | |
106 () { | |
107 Helper helper = new Helper(''' | |
108 class A { | |
109 g() {} | |
110 } | |
111 f(A a) { | |
112 a.g(); | |
113 } | |
114 '''); | |
115 helper.checkDynamic('a.g()', 'a', 'g', isInvoke: true); | |
116 }); | |
117 | |
118 test( | |
119 'Call method defined dynamically in class from outside class via typed exp
ression', | |
120 () { | |
121 Helper helper = new Helper(''' | |
122 class A { | |
123 g() {} | |
124 } | |
125 A h() => null; | |
126 f() { | |
127 h().g(); | |
128 } | |
129 '''); | |
130 helper.checkDynamic('h().g()', 'h()', 'g', isInvoke: true); | |
131 }); | |
132 | |
133 test( | |
134 'Call method defined dynamically in class from outside class via dynamic v
ar', | |
135 () { | |
136 Helper helper = new Helper(''' | |
137 f(a) { | |
138 a.g(); | |
139 } | |
140 '''); | |
141 helper.checkDynamic('a.g()', 'a', 'g', isInvoke: true); | |
142 }); | |
143 | |
144 test( | |
145 'Call method defined dynamically in class from outside class via dynamic e
xpression', | |
146 () { | |
147 Helper helper = new Helper(''' | |
148 h() => null; | |
149 f() { | |
150 h().g(); | |
151 } | |
152 '''); | |
153 helper.checkDynamic('h().g()', 'h()', 'g', isInvoke: true); | |
154 }); | |
155 | |
156 test('Call method defined locally', () { | |
157 Helper helper = new Helper(''' | |
158 f() { | |
159 g() {} | |
160 g(); | |
161 } | |
162 '''); | |
163 helper.checkLocalFunction('g()', 'g', isInvoke: true); | |
164 }); | |
165 | |
166 test('Call method undefined at top level', () { | |
167 Helper helper = new Helper(''' | |
168 f() { | |
169 g(); | |
170 } | |
171 '''); | |
172 // Undefined top level invocations are treated as dynamic. | |
173 // TODO(paulberry): not sure if this is a good idea. In general, when such | |
174 // a call appears inside an instance method, it is dynamic, because "this" | |
175 // might be an instance of a derived class that implements g(). However, | |
176 // in this case, we are not inside an instance method, so we know that the | |
177 // target is undefined. | |
178 helper.checkDynamic('g()', null, 'g', isInvoke: true); | |
179 }); | |
180 | |
181 test('Call method undefined at top level via prefix', () { | |
182 Helper helper = new Helper(''' | |
183 import 'lib.dart' as l; | |
184 | |
185 f() { | |
186 l.g(); | |
187 } | |
188 '''); | |
189 helper.addFile('/lib.dart', ''' | |
190 library lib; | |
191 '''); | |
192 // Undefined top level invocations are treated as dynamic. | |
193 // TODO(paulberry): not sure if this is a good idea, for similar reasons to | |
194 // the case above. | |
195 helper.checkDynamic('l.g()', null, 'g', isInvoke: true); | |
196 }); | |
197 | |
198 test('Call method undefined statically in class from outside class', () { | |
199 Helper helper = new Helper(''' | |
200 class A {} | |
201 | |
202 f() { | |
203 A.g(); | |
204 } | |
205 '''); | |
206 helper.checkStaticMethod('A.g()', 'A', 'g', false, isInvoke: true); | |
207 }); | |
208 | |
209 test( | |
210 'Call method undefined statically in class from outside class via prefix', | |
211 () { | |
212 Helper helper = new Helper(''' | |
213 import 'lib.dart' as l; | |
214 | |
215 f() { | |
216 l.A.g(); | |
217 } | |
218 '''); | |
219 helper.addFile('/lib.dart', ''' | |
220 library lib; | |
221 | |
222 class A {} | |
223 '''); | |
224 helper.checkStaticMethod('l.A.g()', 'A', 'g', false, isInvoke: true); | |
225 }); | |
226 | |
227 test('Call method undefined dynamically in class from inside class', () { | |
228 Helper helper = new Helper(''' | |
229 class A { | |
230 f() { | |
231 g(); | |
232 } | |
233 } | |
234 '''); | |
235 helper.checkDynamic('g()', null, 'g', isInvoke: true); | |
236 }); | |
237 | |
238 test( | |
239 'Call method undefined dynamically in class from outside class via typed v
ar', | |
240 () { | |
241 Helper helper = new Helper(''' | |
242 class A {} | |
243 | |
244 f(A a) { | |
245 a.g(); | |
246 } | |
247 '''); | |
248 helper.checkDynamic('a.g()', 'a', 'g', isInvoke: true); | |
249 }); | |
250 | |
251 test( | |
252 'Call method undefined dynamically in class from outside class via typed e
xpression', | |
253 () { | |
254 Helper helper = new Helper(''' | |
255 class A {} | |
256 | |
257 A h() => null; | |
258 | |
259 f() { | |
260 h().g(); | |
261 } | |
262 '''); | |
263 helper.checkDynamic('h().g()', 'h()', 'g', isInvoke: true); | |
264 }); | |
265 | |
266 test('Call variable defined at top level', () { | |
267 Helper helper = new Helper(''' | |
268 var x; | |
269 | |
270 f() { | |
271 x(); | |
272 } | |
273 '''); | |
274 helper.checkStaticField('x()', null, 'x', isInvoke: true); | |
275 }); | |
276 | |
277 test('Call variable defined at top level via prefix', () { | |
278 Helper helper = new Helper(''' | |
279 import 'lib.dart' as l; | |
280 | |
281 f() { | |
282 return l.x(); | |
283 } | |
284 '''); | |
285 helper.addFile('/lib.dart', ''' | |
286 library lib; | |
287 | |
288 var x; | |
289 '''); | |
290 helper.checkStaticField('l.x()', null, 'x', isInvoke: true); | |
291 }); | |
292 | |
293 test('Call field defined statically in class from inside class', () { | |
294 Helper helper = new Helper(''' | |
295 class A { | |
296 static var x; | |
297 | |
298 f() { | |
299 return x(); | |
300 } | |
301 } | |
302 '''); | |
303 helper.checkStaticField('x()', 'A', 'x', isInvoke: true); | |
304 }); | |
305 | |
306 test('Call field defined statically in class from outside class', () { | |
307 Helper helper = new Helper(''' | |
308 class A { | |
309 static var x; | |
310 } | |
311 | |
312 f() { | |
313 return A.x(); | |
314 } | |
315 '''); | |
316 helper.checkStaticField('A.x()', 'A', 'x', isInvoke: true); | |
317 }); | |
318 | |
319 test( | |
320 'Call field defined statically in class from outside class via prefix', | |
321 () { | |
322 Helper helper = new Helper(''' | |
323 import 'lib.dart' as l; | |
324 | |
325 f() { | |
326 return l.A.x(); | |
327 } | |
328 '''); | |
329 helper.addFile('/lib.dart', ''' | |
330 library lib; | |
331 | |
332 class A { | |
333 static var x; | |
334 } | |
335 '''); | |
336 helper.checkStaticField('l.A.x()', 'A', 'x', isInvoke: true); | |
337 }); | |
338 | |
339 test('Call field defined dynamically in class from inside class', () { | |
340 Helper helper = new Helper(''' | |
341 class A { | |
342 var x; | |
343 | |
344 f() { | |
345 return x(); | |
346 } | |
347 } | |
348 '''); | |
349 helper.checkDynamic('x()', null, 'x', isInvoke: true); | |
350 }); | |
351 | |
352 test( | |
353 'Call field defined dynamically in class from outside class via typed var'
, | |
354 () { | |
355 Helper helper = new Helper(''' | |
356 class A { | |
357 var x; | |
358 } | |
359 | |
360 f(A a) { | |
361 return a.x(); | |
362 } | |
363 '''); | |
364 helper.checkDynamic('a.x()', 'a', 'x', isInvoke: true); | |
365 }); | |
366 | |
367 test( | |
368 'Call field defined dynamically in class from outside class via typed expr
ession', | |
369 () { | |
370 Helper helper = new Helper(''' | |
371 class A { | |
372 var x; | |
373 } | |
374 | |
375 A h() => null; | |
376 | |
377 f() { | |
378 return h().x(); | |
379 } | |
380 '''); | |
381 helper.checkDynamic('h().x()', 'h()', 'x', isInvoke: true); | |
382 }); | |
383 | |
384 test( | |
385 'Call field defined dynamically in class from outside class via dynamic va
r', | |
386 () { | |
387 Helper helper = new Helper(''' | |
388 f(a) { | |
389 return a.x(); | |
390 } | |
391 '''); | |
392 helper.checkDynamic('a.x()', 'a', 'x', isInvoke: true); | |
393 }); | |
394 | |
395 test( | |
396 'Call field defined dynamically in class from outside class via dynamic ex
pression', | |
397 () { | |
398 Helper helper = new Helper(''' | |
399 h() => null; | |
400 | |
401 f() { | |
402 return h().x(); | |
403 } | |
404 '''); | |
405 helper.checkDynamic('h().x()', 'h()', 'x', isInvoke: true); | |
406 }); | |
407 | |
408 test('Call variable defined locally', () { | |
409 Helper helper = new Helper(''' | |
410 f() { | |
411 var x; | |
412 return x(); | |
413 } | |
414 '''); | |
415 helper.checkLocalVariable('x()', 'x', isInvoke: true); | |
416 }); | |
417 | |
418 test('Call variable defined in parameter', () { | |
419 Helper helper = new Helper(''' | |
420 f(x) { | |
421 return x(); | |
422 } | |
423 '''); | |
424 helper.checkParameter('x()', 'x', isInvoke: true); | |
425 }); | |
426 | |
427 test('Call accessor defined at top level', () { | |
428 Helper helper = new Helper(''' | |
429 get x => null; | |
430 | |
431 f() { | |
432 return x(); | |
433 } | |
434 '''); | |
435 helper.checkStaticProperty('x()', null, 'x', true, isInvoke: true); | |
436 }); | |
437 | |
438 test('Call accessor defined at top level via prefix', () { | |
439 Helper helper = new Helper(''' | |
440 import 'lib.dart' as l; | |
441 | |
442 f() { | |
443 return l.x(); | |
444 } | |
445 '''); | |
446 helper.addFile('/lib.dart', ''' | |
447 library lib; | |
448 | |
449 get x => null; | |
450 '''); | |
451 helper.checkStaticProperty('l.x()', null, 'x', true, isInvoke: true); | |
452 }); | |
453 | |
454 test('Call accessor defined statically in class from inside class', () { | |
455 Helper helper = new Helper(''' | |
456 class A { | |
457 static get x => null; | |
458 | |
459 f() { | |
460 return x(); | |
461 } | |
462 } | |
463 '''); | |
464 helper.checkStaticProperty('x()', 'A', 'x', true, isInvoke: true); | |
465 }); | |
466 | |
467 test('Call accessor defined statically in class from outside class', () { | |
468 Helper helper = new Helper(''' | |
469 class A { | |
470 static get x => null; | |
471 } | |
472 | |
473 f() { | |
474 return A.x(); | |
475 } | |
476 '''); | |
477 helper.checkStaticProperty('A.x()', 'A', 'x', true, isInvoke: true); | |
478 }); | |
479 | |
480 test( | |
481 'Call accessor defined statically in class from outside class via prefix', | |
482 () { | |
483 Helper helper = new Helper(''' | |
484 import 'lib.dart' as l; | |
485 | |
486 f() { | |
487 return l.A.x(); | |
488 } | |
489 '''); | |
490 helper.addFile('/lib.dart', ''' | |
491 library lib; | |
492 | |
493 class A { | |
494 static get x => null; | |
495 } | |
496 '''); | |
497 helper.checkStaticProperty('l.A.x()', 'A', 'x', true, isInvoke: true); | |
498 }); | |
499 | |
500 test('Call accessor defined dynamically in class from inside class', () { | |
501 Helper helper = new Helper(''' | |
502 class A { | |
503 get x => null; | |
504 | |
505 f() { | |
506 return x(); | |
507 } | |
508 } | |
509 '''); | |
510 helper.checkDynamic('x()', null, 'x', isInvoke: true); | |
511 }); | |
512 | |
513 test( | |
514 'Call accessor defined dynamically in class from outside class via typed v
ar', | |
515 () { | |
516 Helper helper = new Helper(''' | |
517 class A { | |
518 get x => null; | |
519 } | |
520 | |
521 f(A a) { | |
522 return a.x(); | |
523 } | |
524 '''); | |
525 helper.checkDynamic('a.x()', 'a', 'x', isInvoke: true); | |
526 }); | |
527 | |
528 test( | |
529 'Call accessor defined dynamically in class from outside class via typed e
xpression', | |
530 () { | |
531 Helper helper = new Helper(''' | |
532 class A { | |
533 get x => null; | |
534 } | |
535 | |
536 A h() => null; | |
537 | |
538 f() { | |
539 return h().x(); | |
540 } | |
541 '''); | |
542 helper.checkDynamic('h().x()', 'h()', 'x', isInvoke: true); | |
543 }); | |
544 | |
545 test( | |
546 'Call accessor defined dynamically in class from outside class via dynamic
var', | |
547 () { | |
548 Helper helper = new Helper(''' | |
549 f(a) { | |
550 return a.x(); | |
551 } | |
552 '''); | |
553 helper.checkDynamic('a.x()', 'a', 'x', isInvoke: true); | |
554 }); | |
555 | |
556 test( | |
557 'Call accessor defined dynamically in class from outside class via dynamic
expression', | |
558 () { | |
559 Helper helper = new Helper(''' | |
560 h() => null; | |
561 | |
562 f() { | |
563 return h().x(); | |
564 } | |
565 '''); | |
566 helper.checkDynamic('h().x()', 'h()', 'x', isInvoke: true); | |
567 }); | |
568 | |
569 test('Call class defined at top level', () { | |
570 Helper helper = new Helper(''' | |
571 class A {} | |
572 | |
573 f() { | |
574 A(); | |
575 } | |
576 '''); | |
577 helper.checkTypeReference( | |
578 'A()', | |
579 'A', | |
580 AccessKind.TOPLEVEL_TYPE, | |
581 isInvoke: true); | |
582 }); | |
583 | |
584 test('Call class defined at top level via prefix', () { | |
585 Helper helper = new Helper(''' | |
586 import 'lib.dart' as l; | |
587 | |
588 f() { | |
589 l.A(); | |
590 } | |
591 '''); | |
592 helper.addFile('/lib.dart', ''' | |
593 library lib; | |
594 | |
595 class A {} | |
596 '''); | |
597 helper.checkTypeReference( | |
598 'l.A()', | |
599 'A', | |
600 AccessKind.TOPLEVEL_TYPE, | |
601 isInvoke: true); | |
602 }); | |
603 | |
604 test('Call dynamic type undefined at toplevel', () { | |
605 Helper helper = new Helper(''' | |
606 f() { | |
607 dynamic(); | |
608 } | |
609 '''); | |
610 // Since it is legal to define a toplevel function or a class member called | |
611 // dynamic, "dynamic()" must be treated as a dynamic access to a function | |
612 // called "dynamic". | |
613 helper.checkDynamic('dynamic()', null, 'dynamic', isInvoke: true); | |
614 }); | |
615 | |
616 test('Call function typedef defined at top level', () { | |
617 Helper helper = new Helper(''' | |
618 typedef F(); | |
619 | |
620 f() { | |
621 F(); | |
622 } | |
623 '''); | |
624 helper.checkTypeReference( | |
625 'F()', | |
626 'F', | |
627 AccessKind.TOPLEVEL_TYPE, | |
628 isInvoke: true); | |
629 }); | |
630 | |
631 test('Call function typedef defined at top level via prefix', () { | |
632 Helper helper = new Helper(''' | |
633 import 'lib.dart' as l; | |
634 | |
635 f() { | |
636 l.F(); | |
637 } | |
638 '''); | |
639 helper.addFile('/lib.dart', ''' | |
640 library lib; | |
641 | |
642 typedef F(); | |
643 '''); | |
644 helper.checkTypeReference( | |
645 'l.F()', | |
646 'F', | |
647 AccessKind.TOPLEVEL_TYPE, | |
648 isInvoke: true); | |
649 }); | |
650 | |
651 test('Call mixin application defined at top level', () { | |
652 Helper helper = new Helper(''' | |
653 class A {} | |
654 class B {} | |
655 class C = A with B; | |
656 | |
657 f() { | |
658 C(); | |
659 } | |
660 '''); | |
661 helper.checkTypeReference( | |
662 'C()', | |
663 'C', | |
664 AccessKind.TOPLEVEL_TYPE, | |
665 isInvoke: true); | |
666 }); | |
667 | |
668 test('Call mixin application defined at top level via prefix', () { | |
669 Helper helper = new Helper(''' | |
670 import 'lib.dart' as l; | |
671 | |
672 f() { | |
673 l.C(); | |
674 } | |
675 '''); | |
676 helper.addFile('/lib.dart', ''' | |
677 library lib; | |
678 | |
679 class A {} | |
680 class B {} | |
681 class C = A with B; | |
682 '''); | |
683 helper.checkTypeReference( | |
684 'l.C()', | |
685 'C', | |
686 AccessKind.TOPLEVEL_TYPE, | |
687 isInvoke: true); | |
688 }); | |
689 | |
690 test('Call type parameter of enclosing class', () { | |
691 Helper helper = new Helper(''' | |
692 class A<T, U> { | |
693 f() { | |
694 U(); | |
695 } | |
696 } | |
697 '''); | |
698 helper.checkTypeReference( | |
699 'U()', | |
700 'U', | |
701 AccessKind.TYPE_PARAMETER, | |
702 isInvoke: true); | |
703 }); | |
704 | |
705 test('Get function defined at top level', () { | |
706 Helper helper = new Helper(''' | |
707 g() {} | |
708 | |
709 f() { | |
710 return g; | |
711 } | |
712 '''); | |
713 helper.checkStaticMethod('g', null, 'g', true, isRead: true); | |
714 }); | |
715 | |
716 test('Get function defined at top level via prefix', () { | |
717 Helper helper = new Helper(''' | |
718 import 'lib.dart' as l; | |
719 | |
720 f() { | |
721 return l.g; | |
722 } | |
723 '''); | |
724 helper.addFile('/lib.dart', ''' | |
725 library lib; | |
726 | |
727 g() {} | |
728 '''); | |
729 helper.checkStaticMethod('l.g', null, 'g', true, isRead: true); | |
730 }); | |
731 | |
732 test('Get method defined statically in class from inside class', () { | |
733 Helper helper = new Helper(''' | |
734 class A { | |
735 static g() {} | |
736 | |
737 f() { | |
738 return g; | |
739 } | |
740 } | |
741 '''); | |
742 helper.checkStaticMethod('g', 'A', 'g', true, isRead: true); | |
743 }); | |
744 | |
745 test('Get method defined statically in class from outside class', () { | |
746 Helper helper = new Helper(''' | |
747 class A { | |
748 static g() {} | |
749 } | |
750 f() { | |
751 return A.g; | |
752 } | |
753 '''); | |
754 helper.checkStaticMethod('A.g', 'A', 'g', true, isRead: true); | |
755 }); | |
756 | |
757 test( | |
758 'Get method defined statically in class from outside class via prefix', | |
759 () { | |
760 Helper helper = new Helper(''' | |
761 import 'lib.dart' as l; | |
762 | |
763 f() { | |
764 return l.A.g; | |
765 } | |
766 '''); | |
767 helper.addFile('/lib.dart', ''' | |
768 library lib; | |
769 | |
770 class A { | |
771 static g() {} | |
772 } | |
773 '''); | |
774 helper.checkStaticMethod('l.A.g', 'A', 'g', true, isRead: true); | |
775 }); | |
776 | |
777 test('Get method defined dynamically in class from inside class', () { | |
778 Helper helper = new Helper(''' | |
779 class A { | |
780 g() {} | |
781 | |
782 f() { | |
783 return g; | |
784 } | |
785 } | |
786 '''); | |
787 helper.checkDynamic('g', null, 'g', isRead: true); | |
788 }); | |
789 | |
790 test( | |
791 'Get method defined dynamically in class from outside class via typed var'
, | |
792 () { | |
793 Helper helper = new Helper(''' | |
794 class A { | |
795 g() {} | |
796 } | |
797 f(A a) { | |
798 return a.g; | |
799 } | |
800 '''); | |
801 helper.checkDynamic('a.g', 'a', 'g', isRead: true); | |
802 }); | |
803 | |
804 test( | |
805 'Get method defined dynamically in class from outside class via typed expr
ession', | |
806 () { | |
807 Helper helper = new Helper(''' | |
808 class A { | |
809 g() {} | |
810 } | |
811 A h() => null; | |
812 f() { | |
813 return h().g; | |
814 } | |
815 '''); | |
816 helper.checkDynamic('h().g', 'h()', 'g', isRead: true); | |
817 }); | |
818 | |
819 test('Get method defined locally', () { | |
820 Helper helper = new Helper(''' | |
821 f() { | |
822 g() {} | |
823 return g; | |
824 } | |
825 '''); | |
826 helper.checkLocalFunction('g', 'g', isRead: true); | |
827 }); | |
828 | |
829 test('Get variable defined at top level', () { | |
830 Helper helper = new Helper(''' | |
831 var x; | |
832 | |
833 f() { | |
834 return x; | |
835 } | |
836 '''); | |
837 helper.checkStaticField('x', null, 'x', isRead: true); | |
838 }); | |
839 | |
840 test('Get variable defined at top level via prefix', () { | |
841 Helper helper = new Helper(''' | |
842 import 'lib.dart' as l; | |
843 | |
844 f() { | |
845 return l.x; | |
846 } | |
847 '''); | |
848 helper.addFile('/lib.dart', ''' | |
849 library lib; | |
850 | |
851 var x; | |
852 '''); | |
853 helper.checkStaticField('l.x', null, 'x', isRead: true); | |
854 }); | |
855 | |
856 test('Get field defined statically in class from inside class', () { | |
857 Helper helper = new Helper(''' | |
858 class A { | |
859 static var x; | |
860 | |
861 f() { | |
862 return x; | |
863 } | |
864 } | |
865 '''); | |
866 helper.checkStaticField('x', 'A', 'x', isRead: true); | |
867 }); | |
868 | |
869 test('Get field defined statically in class from outside class', () { | |
870 Helper helper = new Helper(''' | |
871 class A { | |
872 static var x; | |
873 } | |
874 | |
875 f() { | |
876 return A.x; | |
877 } | |
878 '''); | |
879 helper.checkStaticField('A.x', 'A', 'x', isRead: true); | |
880 }); | |
881 | |
882 test( | |
883 'Get field defined statically in class from outside class via prefix', | |
884 () { | |
885 Helper helper = new Helper(''' | |
886 import 'lib.dart' as l; | |
887 | |
888 f() { | |
889 return l.A.x; | |
890 } | |
891 '''); | |
892 helper.addFile('/lib.dart', ''' | |
893 library lib; | |
894 | |
895 class A { | |
896 static var x; | |
897 } | |
898 '''); | |
899 helper.checkStaticField('l.A.x', 'A', 'x', isRead: true); | |
900 }); | |
901 | |
902 test('Get field defined dynamically in class from inside class', () { | |
903 Helper helper = new Helper(''' | |
904 class A { | |
905 var x; | |
906 | |
907 f() { | |
908 return x; | |
909 } | |
910 } | |
911 '''); | |
912 helper.checkDynamic('x', null, 'x', isRead: true); | |
913 }); | |
914 | |
915 test( | |
916 'Get field defined dynamically in class from outside class via typed var', | |
917 () { | |
918 Helper helper = new Helper(''' | |
919 class A { | |
920 var x; | |
921 } | |
922 | |
923 f(A a) { | |
924 return a.x; | |
925 } | |
926 '''); | |
927 helper.checkDynamic('a.x', 'a', 'x', isRead: true); | |
928 }); | |
929 | |
930 test( | |
931 'Get field defined dynamically in class from outside class via typed expre
ssion', | |
932 () { | |
933 Helper helper = new Helper(''' | |
934 class A { | |
935 var x; | |
936 } | |
937 | |
938 A h() => null; | |
939 | |
940 f() { | |
941 return h().x; | |
942 } | |
943 '''); | |
944 helper.checkDynamic('h().x', 'h()', 'x', isRead: true); | |
945 }); | |
946 | |
947 test( | |
948 'Get field defined dynamically in class from outside class via dynamic var
', | |
949 () { | |
950 Helper helper = new Helper(''' | |
951 f(a) { | |
952 return a.x; | |
953 } | |
954 '''); | |
955 helper.checkDynamic('a.x', 'a', 'x', isRead: true); | |
956 }); | |
957 | |
958 test( | |
959 'Get field defined dynamically in class from outside class via dynamic exp
ression', | |
960 () { | |
961 Helper helper = new Helper(''' | |
962 h() => null; | |
963 | |
964 f() { | |
965 return h().x; | |
966 } | |
967 '''); | |
968 helper.checkDynamic('h().x', 'h()', 'x', isRead: true); | |
969 }); | |
970 | |
971 test('Get variable defined locally', () { | |
972 Helper helper = new Helper(''' | |
973 f() { | |
974 var x; | |
975 return x; | |
976 } | |
977 '''); | |
978 helper.checkLocalVariable('x', 'x', isRead: true); | |
979 }); | |
980 | |
981 test('Get variable defined in parameter', () { | |
982 Helper helper = new Helper(''' | |
983 f(x) { | |
984 return x; | |
985 } | |
986 '''); | |
987 helper.checkParameter('x', 'x', isRead: true); | |
988 }); | |
989 | |
990 test('Get accessor defined at top level', () { | |
991 Helper helper = new Helper(''' | |
992 get x => null; | |
993 | |
994 f() { | |
995 return x; | |
996 } | |
997 '''); | |
998 helper.checkStaticProperty('x', null, 'x', true, isRead: true); | |
999 }); | |
1000 | |
1001 test('Get accessor defined at top level via prefix', () { | |
1002 Helper helper = new Helper(''' | |
1003 import 'lib.dart' as l; | |
1004 | |
1005 f() { | |
1006 return l.x; | |
1007 } | |
1008 '''); | |
1009 helper.addFile('/lib.dart', ''' | |
1010 library lib; | |
1011 | |
1012 get x => null; | |
1013 '''); | |
1014 helper.checkStaticProperty('l.x', null, 'x', true, isRead: true); | |
1015 }); | |
1016 | |
1017 test('Get accessor defined statically in class from inside class', () { | |
1018 Helper helper = new Helper(''' | |
1019 class A { | |
1020 static get x => null; | |
1021 | |
1022 f() { | |
1023 return x; | |
1024 } | |
1025 } | |
1026 '''); | |
1027 helper.checkStaticProperty('x', 'A', 'x', true, isRead: true); | |
1028 }); | |
1029 | |
1030 test('Get accessor defined statically in class from outside class', () { | |
1031 Helper helper = new Helper(''' | |
1032 class A { | |
1033 static get x => null; | |
1034 } | |
1035 | |
1036 f() { | |
1037 return A.x; | |
1038 } | |
1039 '''); | |
1040 helper.checkStaticProperty('A.x', 'A', 'x', true, isRead: true); | |
1041 }); | |
1042 | |
1043 test( | |
1044 'Get accessor defined statically in class from outside class via prefix', | |
1045 () { | |
1046 Helper helper = new Helper(''' | |
1047 import 'lib.dart' as l; | |
1048 | |
1049 f() { | |
1050 return l.A.x; | |
1051 } | |
1052 '''); | |
1053 helper.addFile('/lib.dart', ''' | |
1054 library lib; | |
1055 | |
1056 class A { | |
1057 static get x => null; | |
1058 } | |
1059 '''); | |
1060 helper.checkStaticProperty('l.A.x', 'A', 'x', true, isRead: true); | |
1061 }); | |
1062 | |
1063 test('Get accessor defined dynamically in class from inside class', () { | |
1064 Helper helper = new Helper(''' | |
1065 class A { | |
1066 get x => null; | |
1067 | |
1068 f() { | |
1069 return x; | |
1070 } | |
1071 } | |
1072 '''); | |
1073 helper.checkDynamic('x', null, 'x', isRead: true); | |
1074 }); | |
1075 | |
1076 test( | |
1077 'Get accessor defined dynamically in class from outside class via typed va
r', | |
1078 () { | |
1079 Helper helper = new Helper(''' | |
1080 class A { | |
1081 get x => null; | |
1082 } | |
1083 | |
1084 f(A a) { | |
1085 return a.x; | |
1086 } | |
1087 '''); | |
1088 helper.checkDynamic('a.x', 'a', 'x', isRead: true); | |
1089 }); | |
1090 | |
1091 test( | |
1092 'Get accessor defined dynamically in class from outside class via typed ex
pression', | |
1093 () { | |
1094 Helper helper = new Helper(''' | |
1095 class A { | |
1096 get x => null; | |
1097 } | |
1098 | |
1099 A h() => null; | |
1100 | |
1101 f() { | |
1102 return h().x; | |
1103 } | |
1104 '''); | |
1105 helper.checkDynamic('h().x', 'h()', 'x', isRead: true); | |
1106 }); | |
1107 | |
1108 test( | |
1109 'Get accessor defined dynamically in class from outside class via dynamic
var', | |
1110 () { | |
1111 Helper helper = new Helper(''' | |
1112 f(a) { | |
1113 return a.x; | |
1114 } | |
1115 '''); | |
1116 helper.checkDynamic('a.x', 'a', 'x', isRead: true); | |
1117 }); | |
1118 | |
1119 test( | |
1120 'Get accessor defined dynamically in class from outside class via dynamic
expression', | |
1121 () { | |
1122 Helper helper = new Helper(''' | |
1123 h() => null; | |
1124 | |
1125 f() { | |
1126 return h().x; | |
1127 } | |
1128 '''); | |
1129 helper.checkDynamic('h().x', 'h()', 'x', isRead: true); | |
1130 }); | |
1131 | |
1132 test('Get accessor undefined at top level', () { | |
1133 Helper helper = new Helper(''' | |
1134 f() { | |
1135 return x; | |
1136 } | |
1137 '''); | |
1138 // Undefined top level property accesses are treated as dynamic. | |
1139 // TODO(paulberry): not sure if this is a good idea. In general, when such | |
1140 // an access appears inside an instance method, it is dynamic, because | |
1141 // "this" might be an instance of a derived class that implements x. | |
1142 // However, in this case, we are not inside an instance method, so we know | |
1143 // that the target is undefined. | |
1144 helper.checkDynamic('x', null, 'x', isRead: true); | |
1145 }); | |
1146 | |
1147 test('Get accessor undefined at top level via prefix', () { | |
1148 Helper helper = new Helper(''' | |
1149 import 'lib.dart' as l; | |
1150 | |
1151 f() { | |
1152 return l.x; | |
1153 } | |
1154 '''); | |
1155 helper.addFile('/lib.dart', ''' | |
1156 library lib; | |
1157 '''); | |
1158 // Undefined top level property accesses are treated as dynamic. | |
1159 // TODO(paulberry): not sure if this is a good idea, for similar reasons to | |
1160 // the case above. | |
1161 helper.checkDynamic('l.x', null, 'x', isRead: true); | |
1162 }); | |
1163 | |
1164 test('Get accessor undefined statically in class from outside class', () { | |
1165 Helper helper = new Helper(''' | |
1166 class A {} | |
1167 | |
1168 f() { | |
1169 return A.x; | |
1170 } | |
1171 '''); | |
1172 helper.checkStaticProperty('A.x', 'A', 'x', false, isRead: true); | |
1173 }); | |
1174 | |
1175 test( | |
1176 'Get accessor undefined statically in class from outside class via prefix'
, | |
1177 () { | |
1178 Helper helper = new Helper(''' | |
1179 import 'lib.dart' as l; | |
1180 | |
1181 f() { | |
1182 return l.A.x; | |
1183 } | |
1184 '''); | |
1185 helper.addFile('/lib.dart', ''' | |
1186 library lib; | |
1187 | |
1188 class A {} | |
1189 '''); | |
1190 helper.checkStaticProperty('l.A.x', 'A', 'x', false, isRead: true); | |
1191 }); | |
1192 | |
1193 test('Get accessor undefined dynamically in class from inside class', () { | |
1194 Helper helper = new Helper(''' | |
1195 class A { | |
1196 f() { | |
1197 return x; | |
1198 } | |
1199 } | |
1200 '''); | |
1201 helper.checkDynamic('x', null, 'x', isRead: true); | |
1202 }); | |
1203 | |
1204 test( | |
1205 'Get accessor undefined dynamically in class from outside class via typed
var', | |
1206 () { | |
1207 Helper helper = new Helper(''' | |
1208 class A {} | |
1209 | |
1210 f(A a) { | |
1211 return a.x; | |
1212 } | |
1213 '''); | |
1214 helper.checkDynamic('a.x', 'a', 'x', isRead: true); | |
1215 }); | |
1216 | |
1217 test( | |
1218 'Get accessor undefined dynamically in class from outside class via typed
expression', | |
1219 () { | |
1220 Helper helper = new Helper(''' | |
1221 class A {} | |
1222 | |
1223 A h() => null; | |
1224 | |
1225 f() { | |
1226 return h().x; | |
1227 } | |
1228 '''); | |
1229 helper.checkDynamic('h().x', 'h()', 'x', isRead: true); | |
1230 }); | |
1231 | |
1232 test('Get class defined at top level', () { | |
1233 Helper helper = new Helper(''' | |
1234 class A {} | |
1235 var t = A; | |
1236 '''); | |
1237 helper.checkTypeReference('A', 'A', AccessKind.TOPLEVEL_TYPE, isRead: true); | |
1238 }); | |
1239 | |
1240 test('Get class defined at top level via prefix', () { | |
1241 Helper helper = new Helper(''' | |
1242 import 'lib.dart' as l; | |
1243 | |
1244 var t = l.A; | |
1245 '''); | |
1246 helper.addFile('/lib.dart', ''' | |
1247 library lib; | |
1248 | |
1249 class A {} | |
1250 '''); | |
1251 helper.checkTypeReference( | |
1252 'l.A', | |
1253 'A', | |
1254 AccessKind.TOPLEVEL_TYPE, | |
1255 isRead: true); | |
1256 }); | |
1257 | |
1258 test('Get dynamic type', () { | |
1259 Helper helper = new Helper(''' | |
1260 var t = dynamic; | |
1261 '''); | |
1262 helper.checkTypeReference( | |
1263 'dynamic', | |
1264 'dynamic', | |
1265 AccessKind.TOPLEVEL_TYPE, | |
1266 isRead: true); | |
1267 }); | |
1268 | |
1269 test('Get function typedef defined at top level', () { | |
1270 Helper helper = new Helper(''' | |
1271 typedef F(); | |
1272 var t = F; | |
1273 '''); | |
1274 helper.checkTypeReference('F', 'F', AccessKind.TOPLEVEL_TYPE, isRead: true); | |
1275 }); | |
1276 | |
1277 test('Get function typedef defined at top level via prefix', () { | |
1278 Helper helper = new Helper(''' | |
1279 import 'lib.dart' as l; | |
1280 | |
1281 var t = l.F; | |
1282 '''); | |
1283 helper.addFile('/lib.dart', ''' | |
1284 library lib; | |
1285 | |
1286 typedef F(); | |
1287 '''); | |
1288 helper.checkTypeReference( | |
1289 'l.F', | |
1290 'F', | |
1291 AccessKind.TOPLEVEL_TYPE, | |
1292 isRead: true); | |
1293 }); | |
1294 | |
1295 test('Get mixin application defined at top level', () { | |
1296 Helper helper = new Helper(''' | |
1297 class A {} | |
1298 class B {} | |
1299 class C = A with B; | |
1300 var t = C; | |
1301 '''); | |
1302 helper.checkTypeReference('C', 'C', AccessKind.TOPLEVEL_TYPE, isRead: true); | |
1303 }); | |
1304 | |
1305 test('Get mixin application defined at top level via prefix', () { | |
1306 Helper helper = new Helper(''' | |
1307 import 'lib.dart' as l; | |
1308 | |
1309 var t = l.C; | |
1310 '''); | |
1311 helper.addFile('/lib.dart', ''' | |
1312 library lib; | |
1313 | |
1314 class A {} | |
1315 class B {} | |
1316 class C = A with B; | |
1317 '''); | |
1318 helper.checkTypeReference( | |
1319 'l.C', | |
1320 'C', | |
1321 AccessKind.TOPLEVEL_TYPE, | |
1322 isRead: true); | |
1323 }); | |
1324 | |
1325 test('Get type parameter of enclosing class', () { | |
1326 Helper helper = new Helper(''' | |
1327 class A<T, U> { | |
1328 f() { | |
1329 var t = U; | |
1330 } | |
1331 } | |
1332 '''); | |
1333 helper.checkTypeReference( | |
1334 'U', | |
1335 'U', | |
1336 AccessKind.TYPE_PARAMETER, | |
1337 isRead: true); | |
1338 }); | |
1339 | |
1340 test('Set variable defined at top level', () { | |
1341 Helper helper = new Helper(''' | |
1342 var x; | |
1343 | |
1344 f() { | |
1345 x = 1; | |
1346 } | |
1347 '''); | |
1348 helper.checkStaticField('x', null, 'x', isWrite: true); | |
1349 }); | |
1350 | |
1351 test('Set variable defined at top level in foreach loop', () { | |
1352 Helper helper = new Helper(''' | |
1353 var x; | |
1354 | |
1355 f() { | |
1356 for (x in []) {} | |
1357 } | |
1358 '''); | |
1359 helper.checkStaticField('x', null, 'x', isWrite: true); | |
1360 }); | |
1361 | |
1362 test('Set variable defined at top level via prefix', () { | |
1363 Helper helper = new Helper(''' | |
1364 import 'lib.dart' as l; | |
1365 | |
1366 f() { | |
1367 l.x = 1; | |
1368 } | |
1369 '''); | |
1370 helper.addFile('/lib.dart', ''' | |
1371 library lib; | |
1372 | |
1373 var x; | |
1374 '''); | |
1375 helper.checkStaticField('l.x', null, 'x', isWrite: true); | |
1376 }); | |
1377 | |
1378 test('Set field defined statically in class from inside class', () { | |
1379 Helper helper = new Helper(''' | |
1380 class A { | |
1381 static var x; | |
1382 | |
1383 f() { | |
1384 x = 1; | |
1385 } | |
1386 } | |
1387 '''); | |
1388 helper.checkStaticField('x', 'A', 'x', isWrite: true); | |
1389 }); | |
1390 | |
1391 test( | |
1392 'Set field defined statically in class from inside class in foreach' + ' l
oop', | |
1393 () { | |
1394 Helper helper = new Helper(''' | |
1395 class A { | |
1396 static var x; | |
1397 | |
1398 f() { | |
1399 for (x in []) {} | |
1400 } | |
1401 } | |
1402 '''); | |
1403 helper.checkStaticField('x', 'A', 'x', isWrite: true); | |
1404 }); | |
1405 | |
1406 test('Set field defined statically in class from outside class', () { | |
1407 Helper helper = new Helper(''' | |
1408 class A { | |
1409 static var x; | |
1410 } | |
1411 | |
1412 f() { | |
1413 A.x = 1; | |
1414 } | |
1415 '''); | |
1416 helper.checkStaticField('A.x', 'A', 'x', isWrite: true); | |
1417 }); | |
1418 | |
1419 test( | |
1420 'Set field defined statically in class from outside class via prefix', | |
1421 () { | |
1422 Helper helper = new Helper(''' | |
1423 import 'lib.dart' as l; | |
1424 | |
1425 f() { | |
1426 l.A.x = 1; | |
1427 } | |
1428 '''); | |
1429 helper.addFile('/lib.dart', ''' | |
1430 library lib; | |
1431 | |
1432 class A { | |
1433 static var x; | |
1434 } | |
1435 '''); | |
1436 helper.checkStaticField('l.A.x', 'A', 'x', isWrite: true); | |
1437 }); | |
1438 | |
1439 test('Set field defined dynamically in class from inside class', () { | |
1440 Helper helper = new Helper(''' | |
1441 class A { | |
1442 var x; | |
1443 | |
1444 f() { | |
1445 x = 1; | |
1446 } | |
1447 } | |
1448 '''); | |
1449 helper.checkDynamic('x', null, 'x', isWrite: true); | |
1450 }); | |
1451 | |
1452 test( | |
1453 'Set field defined dynamically in class from inside class in foreach' + '
loop', | |
1454 () { | |
1455 Helper helper = new Helper(''' | |
1456 class A { | |
1457 var x; | |
1458 | |
1459 f() { | |
1460 for (x in []) {} | |
1461 } | |
1462 } | |
1463 '''); | |
1464 helper.checkDynamic('x', null, 'x', isWrite: true); | |
1465 }); | |
1466 | |
1467 test( | |
1468 'Set field defined dynamically in class from outside class via typed var', | |
1469 () { | |
1470 Helper helper = new Helper(''' | |
1471 class A { | |
1472 var x; | |
1473 } | |
1474 | |
1475 f(A a) { | |
1476 a.x = 1; | |
1477 } | |
1478 '''); | |
1479 helper.checkDynamic('a.x', 'a', 'x', isWrite: true); | |
1480 }); | |
1481 | |
1482 test( | |
1483 'Set field defined dynamically in class from outside class via typed expre
ssion', | |
1484 () { | |
1485 Helper helper = new Helper(''' | |
1486 class A { | |
1487 var x; | |
1488 } | |
1489 | |
1490 A h() => null; | |
1491 | |
1492 f() { | |
1493 h().x = 1; | |
1494 } | |
1495 '''); | |
1496 helper.checkDynamic('h().x', 'h()', 'x', isWrite: true); | |
1497 }); | |
1498 | |
1499 test('Set variable defined locally', () { | |
1500 Helper helper = new Helper(''' | |
1501 f() { | |
1502 var x; | |
1503 x = 1; | |
1504 } | |
1505 '''); | |
1506 helper.checkLocalVariable('x', 'x', isWrite: true); | |
1507 }); | |
1508 | |
1509 test('Set variable defined locally in foreach loop', () { | |
1510 Helper helper = new Helper(''' | |
1511 f() { | |
1512 var x; | |
1513 for (x in []) {} | |
1514 } | |
1515 '''); | |
1516 helper.checkLocalVariable('x', 'x', isWrite: true); | |
1517 }); | |
1518 | |
1519 test('Set variable defined in parameter', () { | |
1520 Helper helper = new Helper(''' | |
1521 f(x) { | |
1522 x = 1; | |
1523 } | |
1524 '''); | |
1525 helper.checkParameter('x', 'x', isWrite: true); | |
1526 }); | |
1527 | |
1528 test('Set variable defined in parameter in foreach loop', () { | |
1529 Helper helper = new Helper(''' | |
1530 f(x) { | |
1531 for (x in []) {} | |
1532 } | |
1533 '''); | |
1534 helper.checkParameter('x', 'x', isWrite: true); | |
1535 }); | |
1536 | |
1537 test('Set accessor defined at top level', () { | |
1538 Helper helper = new Helper(''' | |
1539 set x(value) {}; | |
1540 | |
1541 f() { | |
1542 x = 1; | |
1543 } | |
1544 '''); | |
1545 helper.checkStaticProperty('x', null, 'x', true, isWrite: true); | |
1546 }); | |
1547 | |
1548 test('Set accessor defined at top level in foreach loop', () { | |
1549 Helper helper = new Helper(''' | |
1550 set x(value) {}; | |
1551 | |
1552 f() { | |
1553 for (x in []) {} | |
1554 } | |
1555 '''); | |
1556 helper.checkStaticProperty('x', null, 'x', true, isWrite: true); | |
1557 }); | |
1558 | |
1559 test('Set accessor defined at top level via prefix', () { | |
1560 Helper helper = new Helper(''' | |
1561 import 'lib.dart' as l; | |
1562 | |
1563 f() { | |
1564 l.x = 1; | |
1565 } | |
1566 '''); | |
1567 helper.addFile('/lib.dart', ''' | |
1568 library lib; | |
1569 | |
1570 set x(value) {}; | |
1571 '''); | |
1572 helper.checkStaticProperty('l.x', null, 'x', true, isWrite: true); | |
1573 }); | |
1574 | |
1575 test('Set accessor defined statically in class from inside class', () { | |
1576 Helper helper = new Helper(''' | |
1577 class A { | |
1578 static set x(value) {} | |
1579 | |
1580 f() { | |
1581 x = 1; | |
1582 } | |
1583 } | |
1584 '''); | |
1585 helper.checkStaticProperty('x', 'A', 'x', true, isWrite: true); | |
1586 }); | |
1587 | |
1588 test( | |
1589 'Set accessor defined statically in class from inside class in' + | |
1590 ' foreach loop', | |
1591 () { | |
1592 Helper helper = new Helper(''' | |
1593 class A { | |
1594 static set x(value) {} | |
1595 | |
1596 f() { | |
1597 for (x in []) {} | |
1598 } | |
1599 } | |
1600 '''); | |
1601 helper.checkStaticProperty('x', 'A', 'x', true, isWrite: true); | |
1602 }); | |
1603 | |
1604 test('Set accessor defined statically in class from outside class', () { | |
1605 Helper helper = new Helper(''' | |
1606 class A { | |
1607 static set x(value) {} | |
1608 } | |
1609 | |
1610 f() { | |
1611 A.x = 1; | |
1612 } | |
1613 '''); | |
1614 helper.checkStaticProperty('A.x', 'A', 'x', true, isWrite: true); | |
1615 }); | |
1616 | |
1617 test( | |
1618 'Set accessor defined statically in class from outside class via prefix', | |
1619 () { | |
1620 Helper helper = new Helper(''' | |
1621 import 'lib.dart' as l; | |
1622 | |
1623 f() { | |
1624 l.A.x = 1; | |
1625 } | |
1626 '''); | |
1627 helper.addFile('/lib.dart', ''' | |
1628 library lib; | |
1629 | |
1630 class A { | |
1631 static set x(value) {} | |
1632 } | |
1633 '''); | |
1634 helper.checkStaticProperty('l.A.x', 'A', 'x', true, isWrite: true); | |
1635 }); | |
1636 | |
1637 test('Set accessor defined dynamically in class from inside class', () { | |
1638 Helper helper = new Helper(''' | |
1639 class A { | |
1640 set x(value) {} | |
1641 | |
1642 f() { | |
1643 x = 1; | |
1644 } | |
1645 } | |
1646 '''); | |
1647 helper.checkDynamic('x', null, 'x', isWrite: true); | |
1648 }); | |
1649 | |
1650 test( | |
1651 'Set accessor defined dynamically in class from inside class in' + | |
1652 ' foreach loop', | |
1653 () { | |
1654 Helper helper = new Helper(''' | |
1655 class A { | |
1656 set x(value) {} | |
1657 | |
1658 f() { | |
1659 for (x in []) {} | |
1660 } | |
1661 } | |
1662 '''); | |
1663 helper.checkDynamic('x', null, 'x', isWrite: true); | |
1664 }); | |
1665 | |
1666 test( | |
1667 'Set accessor defined dynamically in class from outside class via typed va
r', | |
1668 () { | |
1669 Helper helper = new Helper(''' | |
1670 class A { | |
1671 set x(value) {} | |
1672 } | |
1673 | |
1674 f(A a) { | |
1675 a.x = 1; | |
1676 } | |
1677 '''); | |
1678 helper.checkDynamic('a.x', 'a', 'x', isWrite: true); | |
1679 }); | |
1680 | |
1681 test( | |
1682 'Set accessor defined dynamically in class from outside class via typed ex
pression', | |
1683 () { | |
1684 Helper helper = new Helper(''' | |
1685 class A { | |
1686 set x(value) {} | |
1687 } | |
1688 | |
1689 A h() => null; | |
1690 | |
1691 f() { | |
1692 h().x = 1; | |
1693 } | |
1694 '''); | |
1695 helper.checkDynamic('h().x', 'h()', 'x', isWrite: true); | |
1696 }); | |
1697 | |
1698 test( | |
1699 'Set accessor defined dynamically in class from outside class via dynamic
var', | |
1700 () { | |
1701 Helper helper = new Helper(''' | |
1702 f(a) { | |
1703 a.x = 1; | |
1704 } | |
1705 '''); | |
1706 helper.checkDynamic('a.x', 'a', 'x', isWrite: true); | |
1707 }); | |
1708 | |
1709 test( | |
1710 'Set accessor defined dynamically in class from outside class via dynamic
expression', | |
1711 () { | |
1712 Helper helper = new Helper(''' | |
1713 h() => null; | |
1714 | |
1715 f() { | |
1716 h().x = 1; | |
1717 } | |
1718 '''); | |
1719 helper.checkDynamic('h().x', 'h()', 'x', isWrite: true); | |
1720 }); | |
1721 | |
1722 test('Set accessor undefined at top level', () { | |
1723 Helper helper = new Helper(''' | |
1724 f() { | |
1725 x = 1; | |
1726 } | |
1727 '''); | |
1728 helper.checkDynamic('x', null, 'x', isWrite: true); | |
1729 }); | |
1730 | |
1731 test('Set accessor undefined at top level in foreach loop', () { | |
1732 Helper helper = new Helper(''' | |
1733 f() { | |
1734 for (x in []) {} | |
1735 } | |
1736 '''); | |
1737 helper.checkDynamic('x', null, 'x', isWrite: true); | |
1738 }); | |
1739 | |
1740 test('Set accessor undefined at top level via prefix', () { | |
1741 Helper helper = new Helper(''' | |
1742 import 'lib.dart' as l; | |
1743 | |
1744 f() { | |
1745 l.x = 1; | |
1746 } | |
1747 '''); | |
1748 helper.addFile('/lib.dart', ''' | |
1749 library lib; | |
1750 '''); | |
1751 helper.checkDynamic('l.x', null, 'x', isWrite: true); | |
1752 }); | |
1753 | |
1754 test('Set accessor undefined statically in class from outside class', () { | |
1755 Helper helper = new Helper(''' | |
1756 class A {} | |
1757 | |
1758 f() { | |
1759 A.x = 1; | |
1760 } | |
1761 '''); | |
1762 helper.checkStaticProperty('A.x', 'A', 'x', false, isWrite: true); | |
1763 }); | |
1764 | |
1765 test( | |
1766 'Set accessor undefined statically in class from outside class via prefix'
, | |
1767 () { | |
1768 Helper helper = new Helper(''' | |
1769 import 'lib.dart' as l; | |
1770 | |
1771 f() { | |
1772 l.A.x = 1; | |
1773 } | |
1774 '''); | |
1775 helper.addFile('/lib.dart', ''' | |
1776 library lib; | |
1777 | |
1778 class A {} | |
1779 '''); | |
1780 helper.checkStaticProperty('l.A.x', 'A', 'x', false, isWrite: true); | |
1781 }); | |
1782 | |
1783 test('Set accessor undefined dynamically in class from inside class', () { | |
1784 Helper helper = new Helper(''' | |
1785 class A { | |
1786 f() { | |
1787 x = 1; | |
1788 } | |
1789 } | |
1790 '''); | |
1791 helper.checkDynamic('x', null, 'x', isWrite: true); | |
1792 }); | |
1793 | |
1794 test( | |
1795 'Set accessor undefined dynamically in class from inside class in' + | |
1796 ' foreach loop', | |
1797 () { | |
1798 Helper helper = new Helper(''' | |
1799 class A { | |
1800 f() { | |
1801 for (x in []) {} | |
1802 } | |
1803 } | |
1804 '''); | |
1805 helper.checkDynamic('x', null, 'x', isWrite: true); | |
1806 }); | |
1807 | |
1808 test( | |
1809 'Set accessor undefined dynamically in class from outside class via typed
var', | |
1810 () { | |
1811 Helper helper = new Helper(''' | |
1812 class A {} | |
1813 | |
1814 f(A a) { | |
1815 a.x = 1; | |
1816 } | |
1817 '''); | |
1818 helper.checkDynamic('a.x', 'a', 'x', isWrite: true); | |
1819 }); | |
1820 | |
1821 test( | |
1822 'Set accessor undefined dynamically in class from outside class via typed
expression', | |
1823 () { | |
1824 Helper helper = new Helper(''' | |
1825 class A {} | |
1826 | |
1827 A h() => null; | |
1828 | |
1829 f() { | |
1830 h().x = 1; | |
1831 } | |
1832 '''); | |
1833 helper.checkDynamic('h().x', 'h()', 'x', isWrite: true); | |
1834 }); | |
1835 | |
1836 test('RMW variable defined at top level', () { | |
1837 Helper helper = new Helper(''' | |
1838 var x; | |
1839 | |
1840 f() { | |
1841 x += 1; | |
1842 } | |
1843 '''); | |
1844 helper.checkStaticField('x', null, 'x', isRead: true, isWrite: true); | |
1845 }); | |
1846 | |
1847 test('RMW variable defined at top level via prefix', () { | |
1848 Helper helper = new Helper(''' | |
1849 import 'lib.dart' as l; | |
1850 | |
1851 f() { | |
1852 l.x += 1; | |
1853 } | |
1854 '''); | |
1855 helper.addFile('/lib.dart', ''' | |
1856 library lib; | |
1857 | |
1858 var x; | |
1859 '''); | |
1860 helper.checkStaticField('l.x', null, 'x', isRead: true, isWrite: true); | |
1861 }); | |
1862 | |
1863 test('RMW field defined statically in class from inside class', () { | |
1864 Helper helper = new Helper(''' | |
1865 class A { | |
1866 static var x; | |
1867 | |
1868 f() { | |
1869 x += 1; | |
1870 } | |
1871 } | |
1872 '''); | |
1873 helper.checkStaticField('x', 'A', 'x', isRead: true, isWrite: true); | |
1874 }); | |
1875 | |
1876 test('RMW field defined statically in class from outside class', () { | |
1877 Helper helper = new Helper(''' | |
1878 class A { | |
1879 static var x; | |
1880 } | |
1881 | |
1882 f() { | |
1883 A.x += 1; | |
1884 } | |
1885 '''); | |
1886 helper.checkStaticField('A.x', 'A', 'x', isRead: true, isWrite: true); | |
1887 }); | |
1888 | |
1889 test( | |
1890 'RMW field defined statically in class from outside class via prefix', | |
1891 () { | |
1892 Helper helper = new Helper(''' | |
1893 import 'lib.dart' as l; | |
1894 | |
1895 f() { | |
1896 l.A.x += 1; | |
1897 } | |
1898 '''); | |
1899 helper.addFile('/lib.dart', ''' | |
1900 library lib; | |
1901 | |
1902 class A { | |
1903 static var x; | |
1904 } | |
1905 '''); | |
1906 helper.checkStaticField('l.A.x', 'A', 'x', isRead: true, isWrite: true); | |
1907 }); | |
1908 | |
1909 test('RMW field defined dynamically in class from inside class', () { | |
1910 Helper helper = new Helper(''' | |
1911 class A { | |
1912 var x; | |
1913 | |
1914 f() { | |
1915 x += 1; | |
1916 } | |
1917 } | |
1918 '''); | |
1919 helper.checkDynamic('x', null, 'x', isRead: true, isWrite: true); | |
1920 }); | |
1921 | |
1922 test( | |
1923 'RMW field defined dynamically in class from outside class via typed var', | |
1924 () { | |
1925 Helper helper = new Helper(''' | |
1926 class A { | |
1927 var x; | |
1928 } | |
1929 | |
1930 f(A a) { | |
1931 a.x += 1; | |
1932 } | |
1933 '''); | |
1934 helper.checkDynamic('a.x', 'a', 'x', isRead: true, isWrite: true); | |
1935 }); | |
1936 | |
1937 test( | |
1938 'RMW field defined dynamically in class from outside class via typed expre
ssion', | |
1939 () { | |
1940 Helper helper = new Helper(''' | |
1941 class A { | |
1942 var x; | |
1943 } | |
1944 | |
1945 A h() => null; | |
1946 | |
1947 f() { | |
1948 h().x += 1; | |
1949 } | |
1950 '''); | |
1951 helper.checkDynamic('h().x', 'h()', 'x', isRead: true, isWrite: true); | |
1952 }); | |
1953 | |
1954 test('RMW variable defined locally', () { | |
1955 Helper helper = new Helper(''' | |
1956 f() { | |
1957 var x; | |
1958 x += 1; | |
1959 } | |
1960 '''); | |
1961 helper.checkLocalVariable('x', 'x', isRead: true, isWrite: true); | |
1962 }); | |
1963 | |
1964 test('RMW variable defined in parameter', () { | |
1965 Helper helper = new Helper(''' | |
1966 f(x) { | |
1967 x += 1; | |
1968 } | |
1969 '''); | |
1970 helper.checkParameter('x', 'x', isRead: true, isWrite: true); | |
1971 }); | |
1972 | |
1973 test('RMW accessor defined at top level', () { | |
1974 Helper helper = new Helper(''' | |
1975 set x(value) {}; | |
1976 | |
1977 f() { | |
1978 x += 1; | |
1979 } | |
1980 '''); | |
1981 helper.checkStaticProperty( | |
1982 'x', | |
1983 null, | |
1984 'x', | |
1985 true, | |
1986 isRead: true, | |
1987 isWrite: true); | |
1988 }); | |
1989 | |
1990 test('RMW accessor defined at top level via prefix', () { | |
1991 Helper helper = new Helper(''' | |
1992 import 'lib.dart' as l; | |
1993 | |
1994 f() { | |
1995 l.x += 1; | |
1996 } | |
1997 '''); | |
1998 helper.addFile('/lib.dart', ''' | |
1999 library lib; | |
2000 | |
2001 set x(value) {}; | |
2002 '''); | |
2003 helper.checkStaticProperty( | |
2004 'l.x', | |
2005 null, | |
2006 'x', | |
2007 true, | |
2008 isRead: true, | |
2009 isWrite: true); | |
2010 }); | |
2011 | |
2012 test('RMW accessor defined statically in class from inside class', () { | |
2013 Helper helper = new Helper(''' | |
2014 class A { | |
2015 static set x(value) {} | |
2016 | |
2017 f() { | |
2018 x += 1; | |
2019 } | |
2020 } | |
2021 '''); | |
2022 helper.checkStaticProperty( | |
2023 'x', | |
2024 'A', | |
2025 'x', | |
2026 true, | |
2027 isRead: true, | |
2028 isWrite: true); | |
2029 }); | |
2030 | |
2031 test('RMW accessor defined statically in class from outside class', () { | |
2032 Helper helper = new Helper(''' | |
2033 class A { | |
2034 static set x(value) {} | |
2035 } | |
2036 | |
2037 f() { | |
2038 A.x += 1; | |
2039 } | |
2040 '''); | |
2041 helper.checkStaticProperty( | |
2042 'A.x', | |
2043 'A', | |
2044 'x', | |
2045 true, | |
2046 isRead: true, | |
2047 isWrite: true); | |
2048 }); | |
2049 | |
2050 test( | |
2051 'RMW accessor defined statically in class from outside class via prefix', | |
2052 () { | |
2053 Helper helper = new Helper(''' | |
2054 import 'lib.dart' as l; | |
2055 | |
2056 f() { | |
2057 l.A.x += 1; | |
2058 } | |
2059 '''); | |
2060 helper.addFile('/lib.dart', ''' | |
2061 library lib; | |
2062 | |
2063 class A { | |
2064 static set x(value) {} | |
2065 } | |
2066 '''); | |
2067 helper.checkStaticProperty( | |
2068 'l.A.x', | |
2069 'A', | |
2070 'x', | |
2071 true, | |
2072 isRead: true, | |
2073 isWrite: true); | |
2074 }); | |
2075 | |
2076 test('RMW accessor defined dynamically in class from inside class', () { | |
2077 Helper helper = new Helper(''' | |
2078 class A { | |
2079 set x(value) {} | |
2080 | |
2081 f() { | |
2082 x += 1; | |
2083 } | |
2084 } | |
2085 '''); | |
2086 helper.checkDynamic('x', null, 'x', isRead: true, isWrite: true); | |
2087 }); | |
2088 | |
2089 test( | |
2090 'RMW accessor defined dynamically in class from outside class via typed va
r', | |
2091 () { | |
2092 Helper helper = new Helper(''' | |
2093 class A { | |
2094 set x(value) {} | |
2095 } | |
2096 | |
2097 f(A a) { | |
2098 a.x += 1; | |
2099 } | |
2100 '''); | |
2101 helper.checkDynamic('a.x', 'a', 'x', isRead: true, isWrite: true); | |
2102 }); | |
2103 | |
2104 test( | |
2105 'RMW accessor defined dynamically in class from outside class via typed ex
pression', | |
2106 () { | |
2107 Helper helper = new Helper(''' | |
2108 class A { | |
2109 set x(value) {} | |
2110 } | |
2111 | |
2112 A h() => null; | |
2113 | |
2114 f() { | |
2115 h().x += 1; | |
2116 } | |
2117 '''); | |
2118 helper.checkDynamic('h().x', 'h()', 'x', isRead: true, isWrite: true); | |
2119 }); | |
2120 | |
2121 test( | |
2122 'RMW accessor defined dynamically in class from outside class via dynamic
var', | |
2123 () { | |
2124 Helper helper = new Helper(''' | |
2125 f(a) { | |
2126 a.x += 1; | |
2127 } | |
2128 '''); | |
2129 helper.checkDynamic('a.x', 'a', 'x', isRead: true, isWrite: true); | |
2130 }); | |
2131 | |
2132 test( | |
2133 'RMW accessor defined dynamically in class from outside class via dynamic
expression', | |
2134 () { | |
2135 Helper helper = new Helper(''' | |
2136 h() => null; | |
2137 | |
2138 f() { | |
2139 h().x += 1; | |
2140 } | |
2141 '''); | |
2142 helper.checkDynamic('h().x', 'h()', 'x', isRead: true, isWrite: true); | |
2143 }); | |
2144 | |
2145 test('RMW accessor undefined at top level', () { | |
2146 Helper helper = new Helper(''' | |
2147 f() { | |
2148 x += 1; | |
2149 } | |
2150 '''); | |
2151 helper.checkDynamic('x', null, 'x', isRead: true, isWrite: true); | |
2152 }); | |
2153 | |
2154 test('RMW accessor undefined at top level via prefix', () { | |
2155 Helper helper = new Helper(''' | |
2156 import 'lib.dart' as l; | |
2157 | |
2158 f() { | |
2159 l.x += 1; | |
2160 } | |
2161 '''); | |
2162 helper.addFile('/lib.dart', ''' | |
2163 library lib; | |
2164 '''); | |
2165 helper.checkDynamic('l.x', null, 'x', isRead: true, isWrite: true); | |
2166 }); | |
2167 | |
2168 test('RMW accessor undefined statically in class from outside class', () { | |
2169 Helper helper = new Helper(''' | |
2170 class A {} | |
2171 | |
2172 f() { | |
2173 A.x += 1; | |
2174 } | |
2175 '''); | |
2176 helper.checkStaticProperty( | |
2177 'A.x', | |
2178 'A', | |
2179 'x', | |
2180 false, | |
2181 isRead: true, | |
2182 isWrite: true); | |
2183 }); | |
2184 | |
2185 test( | |
2186 'RMW accessor undefined statically in class from outside class via prefix'
, | |
2187 () { | |
2188 Helper helper = new Helper(''' | |
2189 import 'lib.dart' as l; | |
2190 | |
2191 f() { | |
2192 l.A.x += 1; | |
2193 } | |
2194 '''); | |
2195 helper.addFile('/lib.dart', ''' | |
2196 library lib; | |
2197 | |
2198 class A {} | |
2199 '''); | |
2200 helper.checkStaticProperty( | |
2201 'l.A.x', | |
2202 'A', | |
2203 'x', | |
2204 false, | |
2205 isRead: true, | |
2206 isWrite: true); | |
2207 }); | |
2208 | |
2209 test('RMW accessor undefined dynamically in class from inside class', () { | |
2210 Helper helper = new Helper(''' | |
2211 class A { | |
2212 f() { | |
2213 x += 1; | |
2214 } | |
2215 } | |
2216 '''); | |
2217 helper.checkDynamic('x', null, 'x', isRead: true, isWrite: true); | |
2218 }); | |
2219 | |
2220 test( | |
2221 'RMW accessor undefined dynamically in class from outside class via typed
var', | |
2222 () { | |
2223 Helper helper = new Helper(''' | |
2224 class A {} | |
2225 | |
2226 f(A a) { | |
2227 a.x += 1; | |
2228 } | |
2229 '''); | |
2230 helper.checkDynamic('a.x', 'a', 'x', isRead: true, isWrite: true); | |
2231 }); | |
2232 | |
2233 test( | |
2234 'RMW accessor undefined dynamically in class from outside class via typed
expression', | |
2235 () { | |
2236 Helper helper = new Helper(''' | |
2237 class A {} | |
2238 | |
2239 A h() => null; | |
2240 | |
2241 f() { | |
2242 h().x += 1; | |
2243 } | |
2244 '''); | |
2245 helper.checkDynamic('h().x', 'h()', 'x', isRead: true, isWrite: true); | |
2246 }); | |
2247 } | |
2248 | |
2249 typedef void AccessHandler(Expression node, AccessSemantics semantics); | |
2250 | |
2251 class Helper { | |
2252 final MemoryResourceProvider provider = new MemoryResourceProvider(); | |
2253 Source rootSource; | |
2254 AnalysisContext context; | |
2255 | |
2256 Helper(String rootContents) { | |
2257 DartSdk sdk = new MockSdk(); | |
2258 String rootFile = '/root.dart'; | |
2259 File file = provider.newFile(rootFile, rootContents); | |
2260 rootSource = file.createSource(); | |
2261 context = AnalysisEngine.instance.createAnalysisContext(); | |
2262 // Set up the source factory. | |
2263 List<UriResolver> uriResolvers = [ | |
2264 new ResourceUriResolver(provider), | |
2265 new DartUriResolver(sdk)]; | |
2266 context.sourceFactory = new SourceFactory(uriResolvers); | |
2267 // add the Source | |
2268 ChangeSet changeSet = new ChangeSet(); | |
2269 changeSet.addedSource(rootSource); | |
2270 context.applyChanges(changeSet); | |
2271 } | |
2272 | |
2273 LibraryElement get libraryElement { | |
2274 return context.computeLibraryElement(rootSource); | |
2275 } | |
2276 | |
2277 void addFile(String path, String contents) { | |
2278 provider.newFile(path, contents); | |
2279 } | |
2280 | |
2281 /** | |
2282 * Verify that the node represented by [expectedSource] is classified as | |
2283 * a dynamic method invocation. | |
2284 */ | |
2285 void checkDynamic(String expectedSource, String expectedTarget, | |
2286 String expectedName, {bool isRead: false, bool isWrite: false, bool isInvo
ke: | |
2287 false}) { | |
2288 TestVisitor visitor = new TestVisitor(); | |
2289 int count = 0; | |
2290 visitor.onAccess = (AstNode node, AccessSemantics semantics) { | |
2291 count++; | |
2292 expect(node.toSource(), equals(expectedSource)); | |
2293 expect(semantics.kind, equals(AccessKind.DYNAMIC)); | |
2294 if (expectedTarget == null) { | |
2295 expect(semantics.target, isNull); | |
2296 } else { | |
2297 expect(semantics.target.toSource(), equals(expectedTarget)); | |
2298 } | |
2299 expect(semantics.identifier.name, equals(expectedName)); | |
2300 expect(semantics.element, isNull); | |
2301 expect(semantics.classElement, isNull); | |
2302 expect(semantics.isRead, equals(isRead)); | |
2303 expect(semantics.isWrite, equals(isWrite)); | |
2304 expect(semantics.isInvoke, equals(isInvoke)); | |
2305 }; | |
2306 libraryElement.unit.accept(visitor); | |
2307 expect(count, equals(1)); | |
2308 } | |
2309 | |
2310 /** | |
2311 * Verify that the node represented by [expectedSource] is classified as | |
2312 * a local function invocation. | |
2313 */ | |
2314 void checkLocalFunction(String expectedSource, String expectedName, | |
2315 {bool isRead: false, bool isWrite: false, bool isInvoke: false}) { | |
2316 TestVisitor visitor = new TestVisitor(); | |
2317 int count = 0; | |
2318 visitor.onAccess = (AstNode node, AccessSemantics semantics) { | |
2319 count++; | |
2320 expect(node.toSource(), equals(expectedSource)); | |
2321 expect(semantics.kind, equals(AccessKind.LOCAL_FUNCTION)); | |
2322 expect(semantics.identifier.name, equals(expectedName)); | |
2323 expect(semantics.element.displayName, equals(expectedName)); | |
2324 expect(semantics.classElement, isNull); | |
2325 expect(semantics.target, isNull); | |
2326 expect(semantics.isRead, equals(isRead)); | |
2327 expect(semantics.isWrite, equals(isWrite)); | |
2328 expect(semantics.isInvoke, equals(isInvoke)); | |
2329 }; | |
2330 libraryElement.unit.accept(visitor); | |
2331 expect(count, equals(1)); | |
2332 } | |
2333 | |
2334 /** | |
2335 * Verify that the node represented by [expectedSource] is classified as | |
2336 * a local variable access. | |
2337 */ | |
2338 void checkLocalVariable(String expectedSource, String expectedName, | |
2339 {bool isRead: false, bool isWrite: false, bool isInvoke: false}) { | |
2340 TestVisitor visitor = new TestVisitor(); | |
2341 int count = 0; | |
2342 visitor.onAccess = (AstNode node, AccessSemantics semantics) { | |
2343 count++; | |
2344 expect(node.toSource(), equals(expectedSource)); | |
2345 expect(semantics.kind, equals(AccessKind.LOCAL_VARIABLE)); | |
2346 expect(semantics.element.name, equals(expectedName)); | |
2347 expect(semantics.classElement, isNull); | |
2348 expect(semantics.target, isNull); | |
2349 expect(semantics.isRead, equals(isRead)); | |
2350 expect(semantics.isWrite, equals(isWrite)); | |
2351 expect(semantics.isInvoke, equals(isInvoke)); | |
2352 }; | |
2353 libraryElement.unit.accept(visitor); | |
2354 expect(count, equals(1)); | |
2355 } | |
2356 | |
2357 /** | |
2358 * Verify that the node represented by [expectedSource] is classified as a | |
2359 * parameter access. | |
2360 */ | |
2361 void checkParameter(String expectedSource, String expectedName, {bool isRead: | |
2362 false, bool isWrite: false, bool isInvoke: false}) { | |
2363 TestVisitor visitor = new TestVisitor(); | |
2364 int count = 0; | |
2365 visitor.onAccess = (AstNode node, AccessSemantics semantics) { | |
2366 count++; | |
2367 expect(node.toSource(), equals(expectedSource)); | |
2368 expect(semantics.kind, equals(AccessKind.PARAMETER)); | |
2369 expect(semantics.element.name, equals(expectedName)); | |
2370 expect(semantics.classElement, isNull); | |
2371 expect(semantics.target, isNull); | |
2372 expect(semantics.isRead, equals(isRead)); | |
2373 expect(semantics.isWrite, equals(isWrite)); | |
2374 expect(semantics.isInvoke, equals(isInvoke)); | |
2375 }; | |
2376 libraryElement.unit.accept(visitor); | |
2377 expect(count, equals(1)); | |
2378 } | |
2379 | |
2380 /** | |
2381 * Verify that the node represented by [expectedSource] is classified as | |
2382 * a static field element reference. | |
2383 */ | |
2384 void checkStaticField(String expectedSource, String expectedClass, | |
2385 String expectedName, {bool isRead: false, bool isWrite: false, bool isInvo
ke: | |
2386 false}) { | |
2387 TestVisitor visitor = new TestVisitor(); | |
2388 int count = 0; | |
2389 visitor.onAccess = (Expression node, AccessSemantics semantics) { | |
2390 count++; | |
2391 expect(node.toSource(), equals(expectedSource)); | |
2392 expect(semantics.kind, equals(AccessKind.STATIC_FIELD)); | |
2393 expect(semantics.identifier.name, equals(expectedName)); | |
2394 expect(semantics.element.displayName, equals(expectedName)); | |
2395 if (expectedClass == null) { | |
2396 expect(semantics.classElement, isNull); | |
2397 } else { | |
2398 expect(semantics.classElement, isNotNull); | |
2399 expect(semantics.classElement.displayName, equals(expectedClass)); | |
2400 } | |
2401 expect(semantics.target, isNull); | |
2402 expect(semantics.isRead, equals(isRead)); | |
2403 expect(semantics.isWrite, equals(isWrite)); | |
2404 expect(semantics.isInvoke, equals(isInvoke)); | |
2405 }; | |
2406 libraryElement.unit.accept(visitor); | |
2407 expect(count, equals(1)); | |
2408 } | |
2409 | |
2410 /** | |
2411 * Verify that the node represented by [expectedSource] is classified as | |
2412 * a static method. | |
2413 */ | |
2414 void checkStaticMethod(String expectedSource, String expectedClass, | |
2415 String expectedName, bool defined, {bool isRead: false, bool isWrite: fals
e, | |
2416 bool isInvoke: false}) { | |
2417 TestVisitor visitor = new TestVisitor(); | |
2418 int count = 0; | |
2419 visitor.onAccess = (AstNode node, AccessSemantics semantics) { | |
2420 count++; | |
2421 expect(node.toSource(), equals(expectedSource)); | |
2422 expect(semantics.kind, equals(AccessKind.STATIC_METHOD)); | |
2423 expect(semantics.identifier.name, equals(expectedName)); | |
2424 if (expectedClass == null) { | |
2425 expect(semantics.classElement, isNull); | |
2426 if (defined) { | |
2427 expect(semantics.element, new isInstanceOf<FunctionElement>()); | |
2428 } | |
2429 } else { | |
2430 expect(semantics.classElement, isNotNull); | |
2431 expect(semantics.classElement.displayName, equals(expectedClass)); | |
2432 if (defined) { | |
2433 expect(semantics.element, new isInstanceOf<MethodElement>()); | |
2434 } | |
2435 } | |
2436 if (defined) { | |
2437 expect(semantics.element.displayName, equals(expectedName)); | |
2438 } else { | |
2439 expect(semantics.element, isNull); | |
2440 } | |
2441 expect(semantics.target, isNull); | |
2442 expect(semantics.isRead, equals(isRead)); | |
2443 expect(semantics.isWrite, equals(isWrite)); | |
2444 expect(semantics.isInvoke, equals(isInvoke)); | |
2445 }; | |
2446 libraryElement.unit.accept(visitor); | |
2447 expect(count, equals(1)); | |
2448 } | |
2449 | |
2450 /** | |
2451 * Verify that the node represented by [expectedSource] is classified as | |
2452 * a static property access. | |
2453 */ | |
2454 void checkStaticProperty(String expectedSource, String expectedClass, | |
2455 String expectedName, bool defined, {bool isRead: false, bool isWrite: fals
e, | |
2456 bool isInvoke: false}) { | |
2457 TestVisitor visitor = new TestVisitor(); | |
2458 int count = 0; | |
2459 visitor.onAccess = (Expression node, AccessSemantics semantics) { | |
2460 count++; | |
2461 expect(node.toSource(), equals(expectedSource)); | |
2462 expect(semantics.kind, equals(AccessKind.STATIC_PROPERTY)); | |
2463 expect(semantics.identifier.name, equals(expectedName)); | |
2464 if (expectedClass == null) { | |
2465 expect(semantics.classElement, isNull); | |
2466 } else { | |
2467 expect(semantics.classElement, isNotNull); | |
2468 expect(semantics.classElement.displayName, equals(expectedClass)); | |
2469 } | |
2470 if (defined) { | |
2471 expect(semantics.element.displayName, equals(expectedName)); | |
2472 } else { | |
2473 expect(semantics.element, isNull); | |
2474 } | |
2475 expect(semantics.target, isNull); | |
2476 expect(semantics.isRead, equals(isRead)); | |
2477 expect(semantics.isWrite, equals(isWrite)); | |
2478 expect(semantics.isInvoke, equals(isInvoke)); | |
2479 }; | |
2480 libraryElement.unit.accept(visitor); | |
2481 expect(count, equals(1)); | |
2482 } | |
2483 | |
2484 /** | |
2485 * Verify that the node represented by [expectedSource] is classified as a | |
2486 * reference to a toplevel class or a type parameter. | |
2487 */ | |
2488 void checkTypeReference(String expectedSource, String expectedName, | |
2489 AccessKind expectedKind, {bool isRead: false, bool isInvoke: false}) { | |
2490 TestVisitor visitor = new TestVisitor(); | |
2491 int count = 0; | |
2492 visitor.onAccess = (AstNode node, AccessSemantics semantics) { | |
2493 count++; | |
2494 expect(node.toSource(), equals(expectedSource)); | |
2495 expect(semantics.kind, equals(expectedKind)); | |
2496 expect(semantics.element.name, equals(expectedName)); | |
2497 expect(semantics.classElement, isNull); | |
2498 expect(semantics.target, isNull); | |
2499 expect(semantics.isRead, equals(isRead)); | |
2500 expect(semantics.isWrite, isFalse); | |
2501 expect(semantics.isInvoke, equals(isInvoke)); | |
2502 }; | |
2503 libraryElement.unit.accept(visitor); | |
2504 expect(count, equals(1)); | |
2505 } | |
2506 } | |
2507 | |
2508 /** | |
2509 * Visitor class used to run the tests. | |
2510 */ | |
2511 class TestVisitor extends RecursiveAstVisitor { | |
2512 AccessHandler onAccess; | |
2513 | |
2514 @override | |
2515 visitMethodInvocation(MethodInvocation node) { | |
2516 onAccess(node, node.accept(ACCESS_SEMANTICS_VISITOR)); | |
2517 } | |
2518 | |
2519 @override | |
2520 visitPrefixedIdentifier(PrefixedIdentifier node) { | |
2521 onAccess(node, node.accept(ACCESS_SEMANTICS_VISITOR)); | |
2522 } | |
2523 | |
2524 @override | |
2525 visitPropertyAccess(PropertyAccess node) { | |
2526 onAccess(node, node.accept(ACCESS_SEMANTICS_VISITOR)); | |
2527 } | |
2528 | |
2529 @override | |
2530 visitSimpleIdentifier(SimpleIdentifier node) { | |
2531 AccessSemantics semantics = node.accept(ACCESS_SEMANTICS_VISITOR); | |
2532 if (semantics != null) { | |
2533 onAccess(node, semantics); | |
2534 } | |
2535 } | |
2536 } | |
OLD | NEW |