OLD | NEW |
| (Empty) |
1 // Copyright (c) 2015, 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 /// General type checking tests | |
6 library dev_compiler.test.checker_test; | |
7 | |
8 import 'package:test/test.dart'; | |
9 | |
10 import '../testing.dart'; | |
11 | |
12 void main() { | |
13 testChecker('ternary operator', { | |
14 '/main.dart': ''' | |
15 abstract class Comparable<T> { | |
16 int compareTo(T other); | |
17 static int compare(Comparable a, Comparable b) => a.compareTo(b); | |
18 } | |
19 typedef int Comparator<T>(T a, T b); | |
20 | |
21 typedef bool _Predicate<T>(T value); | |
22 | |
23 class SplayTreeMap<K, V> { | |
24 Comparator<K> _comparator; | |
25 _Predicate _validKey; | |
26 | |
27 // Initializing _comparator needs a cast, since K may not always be | |
28 // Comparable. | |
29 // Initializing _validKey shouldn't need a cast. Currently | |
30 // it requires inference to work because of dartbug.com/23381 | |
31 SplayTreeMap([int compare(K key1, K key2), | |
32 bool isValidKey(potentialKey)]) { | |
33 : _comparator = /*warning:DownCastComposite*/(compare == null) ? Com
parable.compare : compare, | |
34 _validKey = /*info:InferredType should be pass*/(isValidKey != nul
l) ? isValidKey : ((v) => true); | |
35 _Predicate<Object> _v = /*warning:DownCastComposite*/(isValidKey !
= null) ? isValidKey : ((v) => true); | |
36 _v = /*info:InferredType should be pass*/(isValidKey != null) ? _v
: ((v) => true); | |
37 } | |
38 } | |
39 void main() { | |
40 Object obj = 42; | |
41 dynamic dyn = 42; | |
42 int i = 42; | |
43 | |
44 // Check the boolean conversion of the condition. | |
45 print((/*severe:StaticTypeError*/i) ? false : true); | |
46 print((/*info:DownCastImplicit*/obj) ? false : true); | |
47 print((/*info:DynamicCast*/dyn) ? false : true); | |
48 } | |
49 ''' | |
50 }); | |
51 | |
52 testChecker('if/for/do/while statements use boolean conversion', { | |
53 '/main.dart': ''' | |
54 main() { | |
55 dynamic d = 42; | |
56 Object obj = 42; | |
57 int i = 42; | |
58 bool b = false; | |
59 | |
60 if (b) {} | |
61 if (/*info:DynamicCast*/dyn) {} | |
62 if (/*info:DownCastImplicit*/obj) {} | |
63 if (/*severe:StaticTypeError*/i) {} | |
64 | |
65 while (b) {} | |
66 while (/*info:DynamicCast*/dyn) {} | |
67 while (/*info:DownCastImplicit*/obj) {} | |
68 while (/*severe:StaticTypeError*/i) {} | |
69 | |
70 do {} while (b); | |
71 do {} while (/*info:DynamicCast*/dyn); | |
72 do {} while (/*info:DownCastImplicit*/obj); | |
73 do {} while (/*severe:StaticTypeError*/i); | |
74 | |
75 for (;b;) {} | |
76 for (;/*info:DynamicCast*/dyn;) {} | |
77 for (;/*info:DownCastImplicit*/obj;) {} | |
78 for (;/*severe:StaticTypeError*/i;) {} | |
79 } | |
80 ''' | |
81 }); | |
82 | |
83 testChecker('dynamic invocation', { | |
84 '/main.dart': ''' | |
85 | |
86 class A { | |
87 dynamic call(dynamic x) => x; | |
88 } | |
89 class B extends A { | |
90 int call(int x) => x; | |
91 double col(double x) => x; | |
92 } | |
93 void main() { | |
94 { | |
95 B f = new B(); | |
96 int x; | |
97 double y; | |
98 // The analyzer has what I believe is a bug (dartbug.com/23252) which | |
99 // causes the return type of calls to f to be treated as dynamic. | |
100 x = /*info:DynamicCast should be pass*/f(3); | |
101 x = /*severe:StaticTypeError*/f.col(3.0); | |
102 y = /*info:DynamicCast should be severe:StaticTypeError*/f(3); | |
103 y = f.col(3.0); | |
104 f(/*severe:StaticTypeError*/3.0); | |
105 f.col(/*severe:StaticTypeError*/3); | |
106 } | |
107 { | |
108 Function f = new B(); | |
109 int x; | |
110 double y; | |
111 x = /*info:DynamicCast, info:DynamicInvoke*/f(3); | |
112 x = /*info:DynamicCast, info:DynamicInvoke*/f.col(3.0); | |
113 y = /*info:DynamicCast, info:DynamicInvoke*/f(3); | |
114 y = /*info:DynamicCast, info:DynamicInvoke*/f.col(3.0); | |
115 (/*info:DynamicInvoke*/f(3.0)); | |
116 (/*info:DynamicInvoke*/f.col(3)); | |
117 } | |
118 { | |
119 A f = new B(); | |
120 int x; | |
121 double y; | |
122 x = /*info:DynamicCast, info:DynamicInvoke*/f(3); | |
123 y = /*info:DynamicCast, info:DynamicInvoke*/f(3); | |
124 (/*info:DynamicInvoke*/f(3.0)); | |
125 } | |
126 } | |
127 ''' | |
128 }); | |
129 | |
130 testChecker('conversion and dynamic invoke', { | |
131 '/helper.dart': ''' | |
132 dynamic toString = (int x) => x + 42; | |
133 dynamic hashCode = "hello"; | |
134 ''', | |
135 '/main.dart': ''' | |
136 import 'helper.dart' as helper; | |
137 | |
138 class A { | |
139 String x = "hello world"; | |
140 | |
141 void baz1(y) => x + /*info:DynamicCast*/y; | |
142 static baz2(y) => /*info:DynamicInvoke*/y + y; | |
143 } | |
144 | |
145 void foo(String str) { | |
146 print(str); | |
147 } | |
148 | |
149 class B { | |
150 String toString([int arg]) => arg.toString(); | |
151 } | |
152 | |
153 void bar(a) { | |
154 foo(/*info:DynamicCast,info:DynamicInvoke*/a.x); | |
155 } | |
156 | |
157 baz() => new B(); | |
158 | |
159 typedef DynFun(x); | |
160 typedef StrFun(String x); | |
161 | |
162 var bar1 = bar; | |
163 | |
164 void main() { | |
165 var a = new A(); | |
166 bar(a); | |
167 (/*info:DynamicInvoke*/bar1(a)); | |
168 var b = bar; | |
169 (/*info:DynamicInvoke*/b(a)); | |
170 var f1 = foo; | |
171 f1("hello"); | |
172 dynamic f2 = foo; | |
173 (/*info:DynamicInvoke*/f2("hello")); | |
174 DynFun f3 = foo; | |
175 (/*info:DynamicInvoke*/f3("hello")); | |
176 (/*info:DynamicInvoke*/f3(42)); | |
177 StrFun f4 = foo; | |
178 f4("hello"); | |
179 a.baz1("hello"); | |
180 var b1 = a.baz1; | |
181 (/*info:DynamicInvoke*/b1("hello")); | |
182 A.baz2("hello"); | |
183 var b2 = A.baz2; | |
184 (/*info:DynamicInvoke*/b2("hello")); | |
185 | |
186 dynamic a1 = new B(); | |
187 (/*info:DynamicInvoke*/a1.x); | |
188 a1.toString(); | |
189 (/*info:DynamicInvoke*/a1.toString(42)); | |
190 var toStringClosure = a1.toString; | |
191 (/*info:DynamicInvoke*/a1.toStringClosure()); | |
192 (/*info:DynamicInvoke*/a1.toStringClosure(42)); | |
193 (/*info:DynamicInvoke*/a1.toStringClosure("hello")); | |
194 a1.hashCode; | |
195 | |
196 dynamic toString = () => null; | |
197 (/*info:DynamicInvoke*/toString()); | |
198 | |
199 (/*info:DynamicInvoke*/helper.toString()); | |
200 var toStringClosure2 = helper.toString; | |
201 (/*info:DynamicInvoke*/toStringClosure2()); | |
202 int hashCode = /*info:DynamicCast*/helper.hashCode; | |
203 | |
204 baz().toString(); | |
205 baz().hashCode; | |
206 } | |
207 ''' | |
208 }); | |
209 | |
210 testChecker('Constructors', { | |
211 '/main.dart': ''' | |
212 const num z = 25; | |
213 Object obj = "world"; | |
214 | |
215 class A { | |
216 int x; | |
217 String y; | |
218 | |
219 A(this.x) : this.y = /*severe:StaticTypeError*/42; | |
220 | |
221 A.c1(p): this.x = /*info:DownCastImplicit*/z, this.y = /*info:DynamicCas
t*/p; | |
222 | |
223 A.c2(this.x, this.y); | |
224 | |
225 A.c3(/*severe:InvalidParameterDeclaration*/num this.x, String this.y); | |
226 } | |
227 | |
228 class B extends A { | |
229 B() : super(/*severe:StaticTypeError*/"hello"); | |
230 | |
231 B.c2(int x, String y) : super.c2(/*severe:StaticTypeError*/y, | |
232 /*severe:StaticTypeError*/x); | |
233 | |
234 B.c3(num x, Object y) : super.c3(x, /*info:DownCastImplicit*/y); | |
235 } | |
236 | |
237 void main() { | |
238 A a = new A.c2(/*info:DownCastImplicit*/z, /*severe:StaticTypeError*/z)
; | |
239 var b = new B.c2(/*severe:StaticTypeError*/"hello", /*info:DownCastImpl
icit*/obj); | |
240 } | |
241 ''' | |
242 }); | |
243 | |
244 testChecker('Unbound variable', { | |
245 '/main.dart': ''' | |
246 void main() { | |
247 dynamic y = /*pass should be severe:StaticTypeError*/unboundVariable; | |
248 } | |
249 ''' | |
250 }); | |
251 | |
252 testChecker('Unbound type name', { | |
253 '/main.dart': ''' | |
254 void main() { | |
255 /*pass should be severe:StaticTypeError*/AToB y; | |
256 } | |
257 ''' | |
258 }); | |
259 | |
260 testChecker('Ground type subtyping: dynamic is top', { | |
261 '/main.dart': ''' | |
262 | |
263 class A {} | |
264 class B extends A {} | |
265 | |
266 void main() { | |
267 dynamic y; | |
268 Object o; | |
269 int i = 0; | |
270 double d = 0.0; | |
271 num n; | |
272 A a; | |
273 B b; | |
274 y = o; | |
275 y = i; | |
276 y = d; | |
277 y = n; | |
278 y = a; | |
279 y = b; | |
280 } | |
281 ''' | |
282 }); | |
283 | |
284 testChecker('Ground type subtyping: dynamic downcasts', { | |
285 '/main.dart': ''' | |
286 | |
287 class A {} | |
288 class B extends A {} | |
289 | |
290 void main() { | |
291 dynamic y; | |
292 Object o; | |
293 int i = 0; | |
294 double d = 0.0; | |
295 num n; | |
296 A a; | |
297 B b; | |
298 o = y; | |
299 i = /*info:DynamicCast*/y; | |
300 d = /*info:DynamicCast*/y; | |
301 n = /*info:DynamicCast*/y; | |
302 a = /*info:DynamicCast*/y; | |
303 b = /*info:DynamicCast*/y; | |
304 } | |
305 ''' | |
306 }); | |
307 | |
308 testChecker('Ground type subtyping: assigning a class', { | |
309 '/main.dart': ''' | |
310 | |
311 class A {} | |
312 class B extends A {} | |
313 | |
314 void main() { | |
315 dynamic y; | |
316 Object o; | |
317 int i = 0; | |
318 double d = 0.0; | |
319 num n; | |
320 A a; | |
321 B b; | |
322 y = a; | |
323 o = a; | |
324 i = /*severe:StaticTypeError*/a; | |
325 d = /*severe:StaticTypeError*/a; | |
326 n = /*severe:StaticTypeError*/a; | |
327 a = a; | |
328 b = /*info:DownCastImplicit*/a; | |
329 } | |
330 ''' | |
331 }); | |
332 | |
333 testChecker('Ground type subtyping: assigning a subclass', { | |
334 '/main.dart': ''' | |
335 | |
336 class A {} | |
337 class B extends A {} | |
338 class C extends A {} | |
339 | |
340 void main() { | |
341 dynamic y; | |
342 Object o; | |
343 int i = 0; | |
344 double d = 0.0; | |
345 num n; | |
346 A a; | |
347 B b; | |
348 C c; | |
349 y = b; | |
350 o = b; | |
351 i = /*severe:StaticTypeError*/b; | |
352 d = /*severe:StaticTypeError*/b; | |
353 n = /*severe:StaticTypeError*/b; | |
354 a = b; | |
355 b = b; | |
356 c = /*severe:StaticTypeError*/b; | |
357 } | |
358 ''' | |
359 }); | |
360 | |
361 testChecker('Ground type subtyping: interfaces', { | |
362 '/main.dart': ''' | |
363 | |
364 class A {} | |
365 class B extends A {} | |
366 class C extends A {} | |
367 class D extends B implements C {} | |
368 | |
369 void main() { | |
370 A top; | |
371 B left; | |
372 C right; | |
373 D bot; | |
374 { | |
375 top = top; | |
376 top = left; | |
377 top = right; | |
378 top = bot; | |
379 } | |
380 { | |
381 left = /*info:DownCastImplicit*/top; | |
382 left = left; | |
383 left = /*severe:StaticTypeError*/right; | |
384 left = bot; | |
385 } | |
386 { | |
387 right = /*info:DownCastImplicit*/top; | |
388 right = /*severe:StaticTypeError*/left; | |
389 right = right; | |
390 right = bot; | |
391 } | |
392 { | |
393 bot = /*info:DownCastImplicit*/top; | |
394 bot = /*info:DownCastImplicit*/left; | |
395 bot = /*info:DownCastImplicit*/right; | |
396 bot = bot; | |
397 } | |
398 } | |
399 ''' | |
400 }); | |
401 | |
402 testChecker('Function typing and subtyping: int and object', { | |
403 '/main.dart': ''' | |
404 | |
405 typedef Object Top(int x); // Top of the lattice | |
406 typedef int Left(int x); // Left branch | |
407 typedef int Left2(int x); // Left branch | |
408 typedef Object Right(Object x); // Right branch | |
409 typedef int Bot(Object x); // Bottom of the lattice | |
410 | |
411 Object top(int x) => x; | |
412 int left(int x) => x; | |
413 Object right(Object x) => x; | |
414 int _bot(Object x) => /*info:DownCastImplicit*/x; | |
415 int bot(Object x) => x as int; | |
416 | |
417 void main() { | |
418 { // Check typedef equality | |
419 Left f = left; | |
420 Left2 g = f; | |
421 } | |
422 { | |
423 Top f; | |
424 f = top; | |
425 f = left; | |
426 f = right; | |
427 f = bot; | |
428 } | |
429 { | |
430 Left f; | |
431 f = /*warning:DownCastComposite*/top; | |
432 f = left; | |
433 f = /*warning:DownCastComposite*/right; // Should we reject this? | |
434 f = bot; | |
435 } | |
436 { | |
437 Right f; | |
438 f = /*warning:DownCastComposite*/top; | |
439 f = /*warning:DownCastComposite*/left; // Should we reject this? | |
440 f = right; | |
441 f = bot; | |
442 } | |
443 { | |
444 Bot f; | |
445 f = /*warning:DownCastComposite*/top; | |
446 f = /*warning:DownCastComposite*/left; | |
447 f = /*warning:DownCastComposite*/right; | |
448 f = bot; | |
449 } | |
450 } | |
451 ''' | |
452 }); | |
453 | |
454 testChecker('Function typing and subtyping: classes', { | |
455 '/main.dart': ''' | |
456 | |
457 class A {} | |
458 class B extends A {} | |
459 | |
460 typedef A Top(B x); // Top of the lattice | |
461 typedef B Left(B x); // Left branch | |
462 typedef B Left2(B x); // Left branch | |
463 typedef A Right(A x); // Right branch | |
464 typedef B Bot(A x); // Bottom of the lattice | |
465 | |
466 B left(B x) => x; | |
467 B _bot(A x) => /*info:DownCastImplicit*/x; | |
468 B bot(A x) => x as B; | |
469 A top(B x) => x; | |
470 A right(A x) => x; | |
471 | |
472 void main() { | |
473 { // Check typedef equality | |
474 Left f = left; | |
475 Left2 g = f; | |
476 } | |
477 { | |
478 Top f; | |
479 f = top; | |
480 f = left; | |
481 f = right; | |
482 f = bot; | |
483 } | |
484 { | |
485 Left f; | |
486 f = /*warning:DownCastComposite*/top; | |
487 f = left; | |
488 f = /*warning:DownCastComposite*/right; // Should we reject this? | |
489 f = bot; | |
490 } | |
491 { | |
492 Right f; | |
493 f = /*warning:DownCastComposite*/top; | |
494 f = /*warning:DownCastComposite*/left; // Should we reject this? | |
495 f = right; | |
496 f = bot; | |
497 } | |
498 { | |
499 Bot f; | |
500 f = /*warning:DownCastComposite*/top; | |
501 f = /*warning:DownCastComposite*/left; | |
502 f = /*warning:DownCastComposite*/right; | |
503 f = bot; | |
504 } | |
505 } | |
506 ''' | |
507 }); | |
508 | |
509 testChecker('Function typing and subtyping: dynamic', { | |
510 '/main.dart': ''' | |
511 | |
512 class A {} | |
513 | |
514 typedef dynamic Top(dynamic x); // Top of the lattice | |
515 typedef dynamic Left(A x); // Left branch | |
516 typedef A Right(dynamic x); // Right branch | |
517 typedef A Bottom(A x); // Bottom of the lattice | |
518 | |
519 dynamic left(A x) => x; | |
520 A bot(A x) => x; | |
521 dynamic top(dynamic x) => x; | |
522 A right(dynamic x) => /*info:DynamicCast*/x; | |
523 | |
524 void main() { | |
525 { | |
526 Top f; | |
527 f = top; | |
528 f = left; | |
529 f = right; | |
530 f = bot; | |
531 } | |
532 { | |
533 Left f; | |
534 f = /*warning:DownCastComposite*/top; | |
535 f = left; | |
536 f = /*warning:DownCastComposite*/right; | |
537 f = bot; | |
538 } | |
539 { | |
540 Right f; | |
541 f = /*warning:DownCastComposite*/top; | |
542 f = /*warning:DownCastComposite*/left; | |
543 f = right; | |
544 f = bot; | |
545 } | |
546 { | |
547 Bottom f; | |
548 f = /*warning:DownCastComposite*/top; | |
549 f = /*warning:DownCastComposite*/left; | |
550 f = /*warning:DownCastComposite*/right; | |
551 f = bot; | |
552 } | |
553 } | |
554 ''' | |
555 }); | |
556 | |
557 testChecker('Function typing and subtyping: function literal variance', { | |
558 '/main.dart': ''' | |
559 | |
560 class A {} | |
561 class B extends A {} | |
562 | |
563 typedef T Function2<S, T>(S z); | |
564 | |
565 A top(B x) => x; | |
566 B left(B x) => x; | |
567 A right(A x) => x; | |
568 B bot(A x) => x as B; | |
569 | |
570 void main() { | |
571 { | |
572 Function2<B, A> f; | |
573 f = top; | |
574 f = left; | |
575 f = right; | |
576 f = bot; | |
577 } | |
578 { | |
579 Function2<B, B> f; | |
580 f = /*warning:DownCastComposite*/top; | |
581 f = left; | |
582 f = /*warning:DownCastComposite*/right; // Should we reject this? | |
583 f = bot; | |
584 } | |
585 { | |
586 Function2<A, A> f; | |
587 f = /*warning:DownCastComposite*/top; | |
588 f = /*warning:DownCastComposite*/left; // Should we reject this? | |
589 f = right; | |
590 f = bot; | |
591 } | |
592 { | |
593 Function2<A, B> f; | |
594 f = /*warning:DownCastComposite*/top; | |
595 f = /*warning:DownCastComposite*/left; | |
596 f = /*warning:DownCastComposite*/right; | |
597 f = bot; | |
598 } | |
599 } | |
600 ''' | |
601 }); | |
602 | |
603 testChecker('Function typing and subtyping: function variable variance', { | |
604 '/main.dart': ''' | |
605 | |
606 class A {} | |
607 class B extends A {} | |
608 | |
609 typedef T Function2<S, T>(S z); | |
610 | |
611 void main() { | |
612 { | |
613 Function2<B, A> top; | |
614 Function2<B, B> left; | |
615 Function2<A, A> right; | |
616 Function2<A, B> bot; | |
617 | |
618 top = right; | |
619 top = bot; | |
620 top = top; | |
621 top = left; | |
622 | |
623 left = /*warning:DownCastComposite*/top; | |
624 left = left; | |
625 left = /*warning:DownCastComposite*/right; // Should we reject this? | |
626 left = bot; | |
627 | |
628 right = /*warning:DownCastComposite*/top; | |
629 right = /*warning:DownCastComposite*/left; // Should we reject this? | |
630 right = right; | |
631 right = bot; | |
632 | |
633 bot = /*warning:DownCastComposite*/top; | |
634 bot = /*warning:DownCastComposite*/left; | |
635 bot = /*warning:DownCastComposite*/right; | |
636 bot = bot; | |
637 } | |
638 } | |
639 ''' | |
640 }); | |
641 | |
642 testChecker('Function typing and subtyping: higher order function literals', { | |
643 '/main.dart': ''' | |
644 | |
645 class A {} | |
646 class B extends A {} | |
647 | |
648 typedef T Function2<S, T>(S z); | |
649 | |
650 typedef A BToA(B x); // Top of the base lattice | |
651 typedef B AToB(A x); // Bot of the base lattice | |
652 | |
653 BToA top(AToB f) => f; | |
654 AToB left(AToB f) => f; | |
655 BToA right(BToA f) => f; | |
656 AToB _bot(BToA f) => /*warning:DownCastComposite*/f; | |
657 AToB bot(BToA f) => f as AToB; | |
658 | |
659 Function2<B, A> top(AToB f) => f; | |
660 Function2<A, B> left(AToB f) => f; | |
661 Function2<B, A> right(BToA f) => f; | |
662 Function2<A, B> _bot(BToA f) => /*warning:DownCastComposite*/f; | |
663 Function2<A, B> bot(BToA f) => f as Function2<A, B>; | |
664 | |
665 | |
666 BToA top(Function2<A, B> f) => f; | |
667 AToB left(Function2<A, B> f) => f; | |
668 BToA right(Function2<B, A> f) => f; | |
669 AToB _bot(Function2<B, A> f) => /*warning:DownCastComposite*/f; | |
670 AToB bot(Function2<B, A> f) => f as AToB; | |
671 | |
672 void main() { | |
673 { | |
674 Function2<AToB, BToA> f; // Top | |
675 f = top; | |
676 f = left; | |
677 f = right; | |
678 f = bot; | |
679 } | |
680 { | |
681 Function2<AToB, AToB> f; // Left | |
682 f = /*warning:DownCastComposite*/top; | |
683 f = left; | |
684 f = /*warning:DownCastComposite*/right; // Should we reject this? | |
685 f = bot; | |
686 } | |
687 { | |
688 Function2<BToA, BToA> f; // Right | |
689 f = /*warning:DownCastComposite*/top; | |
690 f = /*warning:DownCastComposite*/left; // Should we reject this? | |
691 f = right; | |
692 f = bot; | |
693 } | |
694 { | |
695 Function2<BToA, AToB> f; // Bot | |
696 f = bot; | |
697 f = /*warning:DownCastComposite*/left; | |
698 f = /*warning:DownCastComposite*/top; | |
699 f = /*warning:DownCastComposite*/left; | |
700 } | |
701 } | |
702 ''' | |
703 }); | |
704 | |
705 testChecker( | |
706 'Function typing and subtyping: higher order function variables', { | |
707 '/main.dart': ''' | |
708 | |
709 class A {} | |
710 class B extends A {} | |
711 | |
712 typedef T Function2<S, T>(S z); | |
713 | |
714 void main() { | |
715 { | |
716 Function2<Function2<A, B>, Function2<B, A>> top; | |
717 Function2<Function2<B, A>, Function2<B, A>> right; | |
718 Function2<Function2<A, B>, Function2<A, B>> left; | |
719 Function2<Function2<B, A>, Function2<A, B>> bot; | |
720 | |
721 top = right; | |
722 top = bot; | |
723 top = top; | |
724 top = left; | |
725 | |
726 left = /*warning:DownCastComposite*/top; | |
727 left = left; | |
728 left = | |
729 /*warning:DownCastComposite should be severe:StaticTypeError*/right; | |
730 left = bot; | |
731 | |
732 right = /*warning:DownCastComposite*/top; | |
733 right = | |
734 /*warning:DownCastComposite should be severe:StaticTypeError*/left; | |
735 right = right; | |
736 right = bot; | |
737 | |
738 bot = /*warning:DownCastComposite*/top; | |
739 bot = /*warning:DownCastComposite*/left; | |
740 bot = /*warning:DownCastComposite*/right; | |
741 bot = bot; | |
742 } | |
743 } | |
744 ''' | |
745 }); | |
746 | |
747 testChecker('Function typing and subtyping: named and optional parameters', { | |
748 '/main.dart': ''' | |
749 | |
750 class A {} | |
751 | |
752 typedef A FR(A x); | |
753 typedef A FO([A x]); | |
754 typedef A FN({A x}); | |
755 typedef A FRR(A x, A y); | |
756 typedef A FRO(A x, [A y]); | |
757 typedef A FRN(A x, {A n}); | |
758 typedef A FOO([A x, A y]); | |
759 typedef A FNN({A x, A y}); | |
760 typedef A FNNN({A z, A y, A x}); | |
761 | |
762 void main() { | |
763 FR r; | |
764 FO o; | |
765 FN n; | |
766 FRR rr; | |
767 FRO ro; | |
768 FRN rn; | |
769 FOO oo; | |
770 FNN nn; | |
771 FNNN nnn; | |
772 | |
773 r = r; | |
774 r = o; | |
775 r = /*severe:StaticTypeError*/n; | |
776 r = /*severe:StaticTypeError*/rr; | |
777 r = ro; | |
778 r = rn; | |
779 r = oo; | |
780 r = /*severe:StaticTypeError*/nn; | |
781 r = /*severe:StaticTypeError*/nnn; | |
782 | |
783 o = /*warning:DownCastComposite*/r; | |
784 o = o; | |
785 o = /*severe:StaticTypeError*/n; | |
786 o = /*severe:StaticTypeError*/rr; | |
787 o = /*severe:StaticTypeError*/ro; | |
788 o = /*severe:StaticTypeError*/rn; | |
789 o = oo; | |
790 o = /*severe:StaticTypeError*/nn | |
791 o = /*severe:StaticTypeError*/nnn; | |
792 | |
793 n = /*severe:StaticTypeError*/r; | |
794 n = /*severe:StaticTypeError*/o; | |
795 n = n; | |
796 n = /*severe:StaticTypeError*/rr; | |
797 n = /*severe:StaticTypeError*/ro; | |
798 n = /*severe:StaticTypeError*/rn; | |
799 n = /*severe:StaticTypeError*/oo; | |
800 n = nn; | |
801 n = nnn; | |
802 | |
803 rr = /*severe:StaticTypeError*/r; | |
804 rr = /*severe:StaticTypeError*/o; | |
805 rr = /*severe:StaticTypeError*/n; | |
806 rr = rr; | |
807 rr = ro; | |
808 rr = /*severe:StaticTypeError*/rn; | |
809 rr = oo; | |
810 rr = /*severe:StaticTypeError*/nn; | |
811 rr = /*severe:StaticTypeError*/nnn; | |
812 | |
813 ro = /*warning:DownCastComposite*/r; | |
814 ro = /*severe:StaticTypeError*/o; | |
815 ro = /*severe:StaticTypeError*/n; | |
816 ro = /*warning:DownCastComposite*/rr; | |
817 ro = ro; | |
818 ro = /*severe:StaticTypeError*/rn; | |
819 ro = oo; | |
820 ro = /*severe:StaticTypeError*/nn; | |
821 ro = /*severe:StaticTypeError*/nnn; | |
822 | |
823 rn = /*warning:DownCastComposite*/r; | |
824 rn = /*severe:StaticTypeError*/o; | |
825 rn = /*severe:StaticTypeError*/n; | |
826 rn = /*severe:StaticTypeError*/rr; | |
827 rn = /*severe:StaticTypeError*/ro; | |
828 rn = rn; | |
829 rn = /*severe:StaticTypeError*/oo; | |
830 rn = /*severe:StaticTypeError*/nn; | |
831 rn = /*severe:StaticTypeError*/nnn; | |
832 | |
833 oo = /*warning:DownCastComposite*/r; | |
834 oo = /*warning:DownCastComposite*/o; | |
835 oo = /*severe:StaticTypeError*/n; | |
836 oo = /*warning:DownCastComposite*/rr; | |
837 oo = /*warning:DownCastComposite*/ro; | |
838 oo = /*severe:StaticTypeError*/rn; | |
839 oo = oo; | |
840 oo = /*severe:StaticTypeError*/nn; | |
841 oo = /*severe:StaticTypeError*/nnn; | |
842 | |
843 nn = /*severe:StaticTypeError*/r; | |
844 nn = /*severe:StaticTypeError*/o; | |
845 nn = /*warning:DownCastComposite*/n; | |
846 nn = /*severe:StaticTypeError*/rr; | |
847 nn = /*severe:StaticTypeError*/ro; | |
848 nn = /*severe:StaticTypeError*/rn; | |
849 nn = /*severe:StaticTypeError*/oo; | |
850 nn = nn; | |
851 nn = nnn; | |
852 | |
853 nnn = /*severe:StaticTypeError*/r; | |
854 nnn = /*severe:StaticTypeError*/o; | |
855 nnn = /*warning:DownCastComposite*/n; | |
856 nnn = /*severe:StaticTypeError*/rr; | |
857 nnn = /*severe:StaticTypeError*/ro; | |
858 nnn = /*severe:StaticTypeError*/rn; | |
859 nnn = /*severe:StaticTypeError*/oo; | |
860 nnn = /*warning:DownCastComposite*/nn; | |
861 nnn = nnn; | |
862 } | |
863 ''' | |
864 }); | |
865 | |
866 testChecker('Function subtyping: objects with call methods', { | |
867 '/main.dart': ''' | |
868 | |
869 typedef int I2I(int x); | |
870 typedef num N2N(num x); | |
871 class A { | |
872 int call(int x) => x; | |
873 } | |
874 class B { | |
875 num call(num x) => x; | |
876 } | |
877 int i2i(int x) => x; | |
878 num n2n(num x) => x; | |
879 void main() { | |
880 { | |
881 I2I f; | |
882 f = new A(); | |
883 f = /*severe:StaticTypeError*/new B(); | |
884 f = i2i; | |
885 f = /*warning:DownCastComposite*/n2n; | |
886 f = /*warning:DownCastComposite*/i2i as Object; | |
887 f = /*warning:DownCastComposite*/n2n as Function; | |
888 } | |
889 { | |
890 N2N f; | |
891 f = /*severe:StaticTypeError*/new A(); | |
892 f = new B(); | |
893 f = /*warning:DownCastComposite*/i2i; | |
894 f = n2n; | |
895 f = /*warning:DownCastComposite*/i2i as Object; | |
896 f = /*warning:DownCastComposite*/n2n as Function; | |
897 } | |
898 { | |
899 A f; | |
900 f = new A(); | |
901 f = /*severe:StaticTypeError*/new B(); | |
902 f = /*severe:StaticTypeError*/i2i; | |
903 f = /*severe:StaticTypeError*/n2n; | |
904 f = /*info:DownCastImplicit*/i2i as Object; | |
905 f = /*info:DownCastImplicit*/n2n as Function; | |
906 } | |
907 { | |
908 B f; | |
909 f = /*severe:StaticTypeError*/new A(); | |
910 f = new B(); | |
911 f = /*severe:StaticTypeError*/i2i; | |
912 f = /*severe:StaticTypeError*/n2n; | |
913 f = /*info:DownCastImplicit*/i2i as Object; | |
914 f = /*info:DownCastImplicit*/n2n as Function; | |
915 } | |
916 { | |
917 Function f; | |
918 f = new A(); | |
919 f = new B(); | |
920 f = i2i; | |
921 f = n2n; | |
922 f = /*info:DownCastImplicit*/i2i as Object; | |
923 f = (n2n as Function); | |
924 } | |
925 } | |
926 ''' | |
927 }); | |
928 | |
929 testChecker('Function typing and subtyping: void', { | |
930 '/main.dart': ''' | |
931 | |
932 class A { | |
933 void bar() => null; | |
934 void foo() => bar; // allowed | |
935 } | |
936 ''' | |
937 }); | |
938 | |
939 testChecker('Relaxed casts', { | |
940 '/main.dart': ''' | |
941 | |
942 class A {} | |
943 | |
944 class L<T> {} | |
945 class M<T> extends L<T> {} | |
946 // L<dynamic|Object> | |
947 // / \ | |
948 // M<dynamic|Object> L<A> | |
949 // \ / | |
950 // M<A> | |
951 // In normal Dart, there are additional edges | |
952 // from M<A> to M<dynamic> | |
953 // from L<A> to M<dynamic> | |
954 // from L<A> to L<dynamic> | |
955 void main() { | |
956 L lOfDs; | |
957 L<Object> lOfOs; | |
958 L<A> lOfAs; | |
959 | |
960 M mOfDs; | |
961 M<Object> mOfOs; | |
962 M<A> mOfAs; | |
963 | |
964 { | |
965 lOfDs = mOfDs; | |
966 lOfDs = mOfOs; | |
967 lOfDs = mOfAs; | |
968 lOfDs = lOfDs; | |
969 lOfDs = lOfOs; | |
970 lOfDs = lOfAs; | |
971 } | |
972 { | |
973 lOfOs = mOfDs; | |
974 lOfOs = mOfOs; | |
975 lOfOs = mOfAs; | |
976 lOfOs = lOfDs; | |
977 lOfOs = lOfOs; | |
978 lOfOs = lOfAs; | |
979 } | |
980 { | |
981 lOfAs = /*warning:DownCastComposite*/mOfDs; | |
982 lOfAs = /*severe:StaticTypeError*/mOfOs; | |
983 lOfAs = mOfAs; | |
984 lOfAs = /*warning:DownCastComposite*/lOfDs; | |
985 lOfAs = /*warning:DownCastComposite*/lOfOs; | |
986 lOfAs = lOfAs; | |
987 } | |
988 { | |
989 mOfDs = mOfDs; | |
990 mOfDs = mOfOs; | |
991 mOfDs = mOfAs; | |
992 mOfDs = /*info:DownCastImplicit*/lOfDs; | |
993 mOfDs = /*info:DownCastImplicit*/lOfOs; | |
994 mOfDs = /*info:DownCastImplicit*/lOfAs; | |
995 } | |
996 { | |
997 mOfOs = mOfDs; | |
998 mOfOs = mOfOs; | |
999 mOfOs = mOfAs; | |
1000 mOfOs = /*info:DownCastImplicit*/lOfDs; | |
1001 mOfOs = /*info:DownCastImplicit*/lOfOs; | |
1002 mOfOs = /*severe:StaticTypeError*/lOfAs; | |
1003 } | |
1004 { | |
1005 mOfAs = /*warning:DownCastComposite*/mOfDs; | |
1006 mOfAs = /*warning:DownCastComposite*/mOfOs; | |
1007 mOfAs = mOfAs; | |
1008 mOfAs = /*warning:DownCastComposite*/lOfDs; | |
1009 mOfAs = /*warning:DownCastComposite*/lOfOs; | |
1010 mOfAs = /*warning:DownCastComposite*/lOfAs; | |
1011 } | |
1012 | |
1013 } | |
1014 ''' | |
1015 }); | |
1016 | |
1017 testChecker('Type checking literals', { | |
1018 '/main.dart': ''' | |
1019 test() { | |
1020 num n = 3; | |
1021 int i = 3; | |
1022 String s = "hello"; | |
1023 { | |
1024 List<int> l = <int>[i]; | |
1025 l = <int>[/*severe:StaticTypeError*/s]; | |
1026 l = <int>[/*info:DownCastImplicit*/n]; | |
1027 l = <int>[i, /*info:DownCastImplicit*/n, /*severe:StaticTypeError
*/s]; | |
1028 } | |
1029 { | |
1030 List l = [i]; | |
1031 l = [s]; | |
1032 l = [n]; | |
1033 l = [i, n, s]; | |
1034 } | |
1035 { | |
1036 Map<String, int> m = <String, int>{s: i}; | |
1037 m = <String, int>{s: /*severe:StaticTypeError*/s}; | |
1038 m = <String, int>{s: /*info:DownCastImplicit*/n}; | |
1039 m = <String, int>{s: i, | |
1040 s: /*info:DownCastImplicit*/n, | |
1041 s: /*severe:StaticTypeError*/s}; | |
1042 } | |
1043 // TODO(leafp): We can't currently test for key errors since the | |
1044 // error marker binds to the entire entry. | |
1045 { | |
1046 Map m = {s: i}; | |
1047 m = {s: s}; | |
1048 m = {s: n}; | |
1049 m = {s: i, | |
1050 s: n, | |
1051 s: s}; | |
1052 m = {i: s, | |
1053 n: s, | |
1054 s: s}; | |
1055 } | |
1056 } | |
1057 ''' | |
1058 }); | |
1059 | |
1060 testChecker('casts in constant contexts', { | |
1061 '/main.dart': ''' | |
1062 class A { | |
1063 static const num n = 3.0; | |
1064 static const int i = /*info:AssignmentCast*/n; | |
1065 final int fi; | |
1066 const A(num a) : this.fi = /*info:DownCastImplicit*/a; | |
1067 } | |
1068 class B extends A { | |
1069 const B(Object a) : super(/*info:DownCastImplicit*/a); | |
1070 } | |
1071 void foo(Object o) { | |
1072 var a = const A(/*info:DownCastImplicit*/o); | |
1073 } | |
1074 ''' | |
1075 }); | |
1076 | |
1077 testChecker('casts in conditionals', { | |
1078 '/main.dart': ''' | |
1079 main() { | |
1080 bool b = true; | |
1081 num x = b ? 1 : 2.3; | |
1082 int y = /*info:AssignmentCast*/b ? 1 : 2.3; | |
1083 String z = !b ? "hello" : null; | |
1084 z = b ? null : "hello"; | |
1085 } | |
1086 ''' | |
1087 }); | |
1088 | |
1089 testChecker('redirecting constructor', { | |
1090 '/main.dart': ''' | |
1091 class A { | |
1092 A(A x) {} | |
1093 A.two() : this(/*severe:StaticTypeError*/3); | |
1094 } | |
1095 ''' | |
1096 }); | |
1097 | |
1098 testChecker('super constructor', { | |
1099 '/main.dart': ''' | |
1100 class A { A(A x) {} } | |
1101 class B extends A { | |
1102 B() : super(/*severe:StaticTypeError*/3); | |
1103 } | |
1104 ''' | |
1105 }); | |
1106 | |
1107 testChecker('field/field override', { | |
1108 '/main.dart': ''' | |
1109 class A {} | |
1110 class B extends A {} | |
1111 class C extends B {} | |
1112 | |
1113 class Base { | |
1114 B f1; | |
1115 B f2; | |
1116 B f3; | |
1117 B f4; | |
1118 } | |
1119 | |
1120 class Child extends Base { | |
1121 /*severe:InvalidMethodOverride*/A f1; // invalid for getter | |
1122 /*severe:InvalidMethodOverride*/C f2; // invalid for setter | |
1123 var f3; | |
1124 /*severe:InvalidMethodOverride,severe:InvalidMethodOverride*/dynamic
f4; | |
1125 } | |
1126 ''' | |
1127 }); | |
1128 | |
1129 testChecker('getter/getter override', { | |
1130 '/main.dart': ''' | |
1131 class A {} | |
1132 class B extends A {} | |
1133 class C extends B {} | |
1134 | |
1135 abstract class Base { | |
1136 B get f1; | |
1137 B get f2; | |
1138 B get f3; | |
1139 B get f4; | |
1140 } | |
1141 | |
1142 class Child extends Base { | |
1143 /*severe:InvalidMethodOverride*/A get f1 => null; | |
1144 C get f2 => null; | |
1145 get f3 => null; | |
1146 /*severe:InvalidMethodOverride*/dynamic get f4 => null; | |
1147 } | |
1148 ''' | |
1149 }); | |
1150 | |
1151 testChecker('field/getter override', { | |
1152 '/main.dart': ''' | |
1153 class A {} | |
1154 class B extends A {} | |
1155 class C extends B {} | |
1156 | |
1157 abstract class Base { | |
1158 B f1; | |
1159 B f2; | |
1160 B f3; | |
1161 B f4; | |
1162 } | |
1163 | |
1164 class Child extends Base { | |
1165 /*severe:InvalidMethodOverride*/A get f1 => null; | |
1166 C get f2 => null; | |
1167 get f3 => null; | |
1168 /*severe:InvalidMethodOverride*/dynamic get f4 => null; | |
1169 } | |
1170 ''' | |
1171 }); | |
1172 | |
1173 testChecker('setter/setter override', { | |
1174 '/main.dart': ''' | |
1175 class A {} | |
1176 class B extends A {} | |
1177 class C extends B {} | |
1178 | |
1179 abstract class Base { | |
1180 void set f1(B value); | |
1181 void set f2(B value); | |
1182 void set f3(B value); | |
1183 void set f4(B value); | |
1184 void set f5(B value); | |
1185 } | |
1186 | |
1187 class Child extends Base { | |
1188 void set f1(A value) {} | |
1189 /*severe:InvalidMethodOverride*/void set f2(C value) {} | |
1190 void set f3(value) {} | |
1191 /*severe:InvalidMethodOverride*/void set f4(dynamic value) {} | |
1192 set f5(B value) {} | |
1193 } | |
1194 ''' | |
1195 }); | |
1196 | |
1197 testChecker('field/setter override', { | |
1198 '/main.dart': ''' | |
1199 class A {} | |
1200 class B extends A {} | |
1201 class C extends B {} | |
1202 | |
1203 class Base { | |
1204 B f1; | |
1205 B f2; | |
1206 B f3; | |
1207 B f4; | |
1208 B f5; | |
1209 } | |
1210 | |
1211 class Child extends Base { | |
1212 B get f1 => null; | |
1213 B get f2 => null; | |
1214 B get f3 => null; | |
1215 B get f4 => null; | |
1216 B get f5 => null; | |
1217 | |
1218 void set f1(A value) {} | |
1219 /*severe:InvalidMethodOverride*/void set f2(C value) {} | |
1220 void set f3(value) {} | |
1221 /*severe:InvalidMethodOverride*/void set f4(dynamic value) {} | |
1222 set f5(B value) {} | |
1223 } | |
1224 ''' | |
1225 }); | |
1226 | |
1227 testChecker('method override', { | |
1228 '/main.dart': ''' | |
1229 class A {} | |
1230 class B extends A {} | |
1231 class C extends B {} | |
1232 | |
1233 class Base { | |
1234 B m1(B a); | |
1235 B m2(B a); | |
1236 B m3(B a); | |
1237 B m4(B a); | |
1238 B m5(B a); | |
1239 B m6(B a); | |
1240 } | |
1241 | |
1242 class Child extends Base { | |
1243 /*severe:InvalidMethodOverride*/A m1(A value) {} | |
1244 /*severe:InvalidMethodOverride*/C m2(C value) {} | |
1245 /*severe:InvalidMethodOverride*/A m3(C value) {} | |
1246 C m4(A value) {} | |
1247 m5(value) {} | |
1248 /*severe:InvalidMethodOverride*/dynamic m6(dynamic value) {} | |
1249 } | |
1250 ''' | |
1251 }); | |
1252 | |
1253 testChecker('unary operators', { | |
1254 '/main.dart': ''' | |
1255 class A { | |
1256 A operator ~() {} | |
1257 A operator +(int x) {} | |
1258 A operator -(int x) {} | |
1259 A operator -() {} | |
1260 } | |
1261 | |
1262 foo() => new A(); | |
1263 | |
1264 test() { | |
1265 A a = new A(); | |
1266 var c = foo(); | |
1267 | |
1268 ~a; | |
1269 (/*info:DynamicInvoke*/~d); | |
1270 | |
1271 !/*severe:StaticTypeError*/a; | |
1272 !/*info:DynamicCast*/d; | |
1273 | |
1274 -a; | |
1275 (/*info:DynamicInvoke*/-d); | |
1276 | |
1277 ++a; | |
1278 --a; | |
1279 (/*info:DynamicInvoke*/++d); | |
1280 (/*info:DynamicInvoke*/--d); | |
1281 | |
1282 a++; | |
1283 a--; | |
1284 (/*info:DynamicInvoke*/d++); | |
1285 (/*info:DynamicInvoke*/d--); | |
1286 }''' | |
1287 }); | |
1288 | |
1289 testChecker('binary and index operators', { | |
1290 '/main.dart': ''' | |
1291 class A { | |
1292 A operator *(B b) {} | |
1293 A operator /(B b) {} | |
1294 A operator ~/(B b) {} | |
1295 A operator %(B b) {} | |
1296 A operator +(B b) {} | |
1297 A operator -(B b) {} | |
1298 A operator <<(B b) {} | |
1299 A operator >>(B b) {} | |
1300 A operator &(B b) {} | |
1301 A operator ^(B b) {} | |
1302 A operator |(B b) {} | |
1303 A operator[](B b) {} | |
1304 } | |
1305 | |
1306 class B { | |
1307 A operator -(B b) {} | |
1308 } | |
1309 | |
1310 foo() => new A(); | |
1311 | |
1312 test() { | |
1313 A a = new A(); | |
1314 B b = new B(); | |
1315 var c = foo(); | |
1316 a = a * b; | |
1317 a = a * /*info:DynamicCast*/c; | |
1318 a = a / b; | |
1319 a = a ~/ b; | |
1320 a = a % b; | |
1321 a = a + b; | |
1322 a = a + /*severe:StaticTypeError*/a; | |
1323 a = a - b; | |
1324 b = /*severe:StaticTypeError*/b - b; | |
1325 a = a << b; | |
1326 a = a >> b; | |
1327 a = a & b; | |
1328 a = a ^ b; | |
1329 a = a | b; | |
1330 c = (/*info:DynamicInvoke*/c + b); | |
1331 | |
1332 String x = 'hello'; | |
1333 int y = 42; | |
1334 x = x + x; | |
1335 x = x + /*info:DynamicCast*/c; | |
1336 x = x + /*severe:StaticTypeError*/y; | |
1337 | |
1338 bool p = true; | |
1339 p = p && p; | |
1340 p = p && /*info:DynamicCast*/c; | |
1341 p = (/*info:DynamicCast*/c) && p; | |
1342 p = (/*info:DynamicCast*/c) && /*info:DynamicCast*/c; | |
1343 p = (/*severe:StaticTypeError*/y) && p; | |
1344 p = c == y; | |
1345 | |
1346 a = a[b]; | |
1347 a = a[/*info:DynamicCast*/c]; | |
1348 c = (/*info:DynamicInvoke*/c[b]); | |
1349 a[/*severe:StaticTypeError*/y]; | |
1350 } | |
1351 ''' | |
1352 }); | |
1353 | |
1354 testChecker('compound assignments', { | |
1355 '/main.dart': ''' | |
1356 class A { | |
1357 A operator *(B b) {} | |
1358 A operator /(B b) {} | |
1359 A operator ~/(B b) {} | |
1360 A operator %(B b) {} | |
1361 A operator +(B b) {} | |
1362 A operator -(B b) {} | |
1363 A operator <<(B b) {} | |
1364 A operator >>(B b) {} | |
1365 A operator &(B b) {} | |
1366 A operator ^(B b) {} | |
1367 A operator |(B b) {} | |
1368 D operator [](B index) {} | |
1369 void operator []=(B index, D value) {} | |
1370 } | |
1371 | |
1372 class B { | |
1373 A operator -(B b) {} | |
1374 } | |
1375 | |
1376 class D { | |
1377 D operator +(D d) {} | |
1378 } | |
1379 | |
1380 foo() => new A(); | |
1381 | |
1382 test() { | |
1383 int x = 0; | |
1384 x += 5; | |
1385 (/*severe:StaticTypeError*/x += 3.14); | |
1386 | |
1387 double y = 0.0; | |
1388 y += 5; | |
1389 y += 3.14; | |
1390 | |
1391 num z = 0; | |
1392 z += 5; | |
1393 z += 3.14; | |
1394 | |
1395 x = /*info:DownCastImplicit*/x + z; | |
1396 x += /*info:DownCastImplicit*/z; | |
1397 y = /*info:DownCastImplicit*/y + z; | |
1398 y += /*info:DownCastImplicit*/z; | |
1399 | |
1400 dynamic w = 42; | |
1401 x += /*info:DynamicCast*/w; | |
1402 y += /*info:DynamicCast*/w; | |
1403 z += /*info:DynamicCast*/w; | |
1404 | |
1405 A a = new A(); | |
1406 B b = new B(); | |
1407 var c = foo(); | |
1408 a = a * b; | |
1409 a *= b; | |
1410 a *= /*info:DynamicCast*/c; | |
1411 a /= b; | |
1412 a ~/= b; | |
1413 a %= b; | |
1414 a += b; | |
1415 a += /*severe:StaticTypeError*/a; | |
1416 a -= b; | |
1417 (/*severe:StaticTypeError*/b -= b); | |
1418 a <<= b; | |
1419 a >>= b; | |
1420 a &= b; | |
1421 a ^= b; | |
1422 a |= b; | |
1423 (/*info:DynamicInvoke*/c += b); | |
1424 | |
1425 var d = new D(); | |
1426 a[b] += d; | |
1427 a[/*info:DynamicCast*/c] += d; | |
1428 a[/*severe:StaticTypeError*/z] += d; | |
1429 a[b] += /*info:DynamicCast*/c; | |
1430 a[b] += /*severe:StaticTypeError*/z; | |
1431 (/*info:DynamicInvoke*/(/*info:DynamicInvoke*/c[b]) += d); | |
1432 } | |
1433 ''' | |
1434 }); | |
1435 | |
1436 testChecker('super call placement', { | |
1437 '/main.dart': ''' | |
1438 class Base { | |
1439 var x; | |
1440 Base() : x = print('Base.1') { print('Base.2'); } | |
1441 } | |
1442 | |
1443 class Derived extends Base { | |
1444 var y, z; | |
1445 Derived() | |
1446 : y = print('Derived.1'), | |
1447 /*severe:InvalidSuperInvocation*/super(), | |
1448 z = print('Derived.2') { | |
1449 print('Derived.3'); | |
1450 } | |
1451 } | |
1452 | |
1453 class Valid extends Base { | |
1454 var y, z; | |
1455 Valid() | |
1456 : y = print('Valid.1'), | |
1457 z = print('Valid.2'), | |
1458 super() { | |
1459 print('Valid.3'); | |
1460 } | |
1461 } | |
1462 | |
1463 class AlsoValid extends Base { | |
1464 AlsoValid() : super(); | |
1465 } | |
1466 | |
1467 main() => new Derived(); | |
1468 ''' | |
1469 }); | |
1470 | |
1471 testChecker('for loop variable', { | |
1472 '/main.dart': ''' | |
1473 foo() { | |
1474 for (int i = 0; i < 10; i++) { | |
1475 i = /*severe:StaticTypeError*/"hi"; | |
1476 } | |
1477 } | |
1478 bar() { | |
1479 for (var i = 0; i < 10; i++) { | |
1480 int j = i + 1; | |
1481 } | |
1482 } | |
1483 ''' | |
1484 }); | |
1485 | |
1486 group('invalid overrides', () { | |
1487 testChecker('child override', { | |
1488 '/main.dart': ''' | |
1489 class A {} | |
1490 class B {} | |
1491 | |
1492 class Base { | |
1493 A f; | |
1494 } | |
1495 | |
1496 class T1 extends Base { | |
1497 /*severe:InvalidMethodOverride*/B get f => null; | |
1498 } | |
1499 | |
1500 class T2 extends Base { | |
1501 /*severe:InvalidMethodOverride*/set f(B b) => null; | |
1502 } | |
1503 | |
1504 class T3 extends Base { | |
1505 /*severe:InvalidMethodOverride*/final B f; | |
1506 } | |
1507 class T4 extends Base { | |
1508 // two: one for the getter one for the setter. | |
1509 /*severe:InvalidMethodOverride,severe:InvalidMethodOverride*/B f; | |
1510 } | |
1511 ''' | |
1512 }); | |
1513 | |
1514 testChecker('child override 2', { | |
1515 '/main.dart': ''' | |
1516 class A {} | |
1517 class B {} | |
1518 | |
1519 class Base { | |
1520 m(A a) {} | |
1521 } | |
1522 | |
1523 class Test extends Base { | |
1524 /*severe:InvalidMethodOverride*/m(B a) {} | |
1525 } | |
1526 ''' | |
1527 }); | |
1528 testChecker('grandchild override', { | |
1529 '/main.dart': ''' | |
1530 class A {} | |
1531 class B {} | |
1532 | |
1533 class Grandparent { | |
1534 m(A a) {} | |
1535 } | |
1536 class Parent extends Grandparent { | |
1537 } | |
1538 | |
1539 class Test extends Parent { | |
1540 /*severe:InvalidMethodOverride*/m(B a) {} | |
1541 } | |
1542 ''' | |
1543 }); | |
1544 | |
1545 testChecker('double override', { | |
1546 '/main.dart': ''' | |
1547 class A {} | |
1548 class B {} | |
1549 | |
1550 class Grandparent { | |
1551 m(A a) {} | |
1552 } | |
1553 class Parent extends Grandparent { | |
1554 m(A a) {} | |
1555 } | |
1556 | |
1557 class Test extends Parent { | |
1558 // Reported only once | |
1559 /*severe:InvalidMethodOverride*/m(B a) {} | |
1560 } | |
1561 ''' | |
1562 }); | |
1563 | |
1564 testChecker('double override 2', { | |
1565 '/main.dart': ''' | |
1566 class A {} | |
1567 class B {} | |
1568 | |
1569 class Grandparent { | |
1570 m(A a) {} | |
1571 } | |
1572 class Parent extends Grandparent { | |
1573 /*severe:InvalidMethodOverride*/m(B a) {} | |
1574 } | |
1575 | |
1576 class Test extends Parent { | |
1577 m(B a) {} | |
1578 } | |
1579 ''' | |
1580 }); | |
1581 | |
1582 testChecker('mixin override to base', { | |
1583 '/main.dart': ''' | |
1584 class A {} | |
1585 class B {} | |
1586 | |
1587 class Base { | |
1588 m(A a) {} | |
1589 } | |
1590 | |
1591 class M1 { | |
1592 m(B a) {} | |
1593 } | |
1594 | |
1595 class M2 {} | |
1596 | |
1597 class T1 extends Base with /*severe:InvalidMethodOverride*/M1 {} | |
1598 class T2 extends Base with /*severe:InvalidMethodOverride*/M1, M2 {} | |
1599 class T3 extends Base with M2, /*severe:InvalidMethodOverride*/M1 {} | |
1600 ''' | |
1601 }); | |
1602 | |
1603 testChecker('mixin override to mixin', { | |
1604 '/main.dart': ''' | |
1605 class A {} | |
1606 class B {} | |
1607 | |
1608 class Base { | |
1609 } | |
1610 | |
1611 class M1 { | |
1612 m(B a) {} | |
1613 } | |
1614 | |
1615 class M2 { | |
1616 m(A a) {} | |
1617 } | |
1618 | |
1619 class T1 extends Base with M1, /*severe:InvalidMethodOverride*/M2 {} | |
1620 ''' | |
1621 }); | |
1622 | |
1623 // This is a regression test for a bug in an earlier implementation were | |
1624 // names were hiding errors if the first mixin override looked correct, | |
1625 // but subsequent ones did not. | |
1626 testChecker('no duplicate mixin override', { | |
1627 '/main.dart': ''' | |
1628 class A {} | |
1629 class B {} | |
1630 | |
1631 class Base { | |
1632 m(A a) {} | |
1633 } | |
1634 | |
1635 class M1 { | |
1636 m(A a) {} | |
1637 } | |
1638 | |
1639 class M2 { | |
1640 m(B a) {} | |
1641 } | |
1642 | |
1643 class M3 { | |
1644 m(B a) {} | |
1645 } | |
1646 | |
1647 class T1 extends Base | |
1648 with M1, /*severe:InvalidMethodOverride*/M2, M3 {} | |
1649 ''' | |
1650 }); | |
1651 | |
1652 testChecker('class override of interface', { | |
1653 '/main.dart': ''' | |
1654 class A {} | |
1655 class B {} | |
1656 | |
1657 abstract class I { | |
1658 m(A a); | |
1659 } | |
1660 | |
1661 class T1 implements I { | |
1662 /*severe:InvalidMethodOverride*/m(B a) {} | |
1663 } | |
1664 ''' | |
1665 }); | |
1666 | |
1667 testChecker('base class override to child interface', { | |
1668 '/main.dart': ''' | |
1669 class A {} | |
1670 class B {} | |
1671 | |
1672 abstract class I { | |
1673 m(A a); | |
1674 } | |
1675 | |
1676 class Base { | |
1677 m(B a) {} | |
1678 } | |
1679 | |
1680 | |
1681 class T1 /*severe:InvalidMethodOverride*/extends Base implements I { | |
1682 } | |
1683 ''' | |
1684 }); | |
1685 | |
1686 testChecker('mixin override of interface', { | |
1687 '/main.dart': ''' | |
1688 class A {} | |
1689 class B {} | |
1690 | |
1691 abstract class I { | |
1692 m(A a); | |
1693 } | |
1694 | |
1695 class M { | |
1696 m(B a) {} | |
1697 } | |
1698 | |
1699 class T1 extends Object with /*severe:InvalidMethodOverride*/M | |
1700 implements I {} | |
1701 ''' | |
1702 }); | |
1703 | |
1704 // This is a case were it is incorrect to say that the base class | |
1705 // incorrectly overrides the interface. | |
1706 testChecker( | |
1707 'no errors if subclass correctly overrides base and interface', { | |
1708 '/main.dart': ''' | |
1709 class A {} | |
1710 class B {} | |
1711 | |
1712 class Base { | |
1713 m(A a) {} | |
1714 } | |
1715 | |
1716 class I1 { | |
1717 m(B a) {} | |
1718 } | |
1719 | |
1720 class T1 /*severe:InvalidMethodOverride*/extends Base | |
1721 implements I1 {} | |
1722 | |
1723 class T2 extends Base implements I1 { | |
1724 /*severe:InvalidMethodOverride,severe:InvalidMethodOverride*/m(a
) {} | |
1725 } | |
1726 | |
1727 class T3 extends Object with /*severe:InvalidMethodOverride*/Base | |
1728 implements I1 {} | |
1729 | |
1730 class T4 extends Object with Base implements I1 { | |
1731 /*severe:InvalidMethodOverride,severe:InvalidMethodOverride*/m(a
) {} | |
1732 } | |
1733 ''' | |
1734 }); | |
1735 }); | |
1736 | |
1737 group('class override of grand interface', () { | |
1738 testChecker('interface of interface of child', { | |
1739 '/main.dart': ''' | |
1740 class A {} | |
1741 class B {} | |
1742 | |
1743 abstract class I1 { | |
1744 m(A a); | |
1745 } | |
1746 abstract class I2 implements I1 {} | |
1747 | |
1748 class T1 implements I2 { | |
1749 /*severe:InvalidMethodOverride*/m(B a) {} | |
1750 } | |
1751 ''' | |
1752 }); | |
1753 testChecker('superclass of interface of child', { | |
1754 '/main.dart': ''' | |
1755 class A {} | |
1756 class B {} | |
1757 | |
1758 abstract class I1 { | |
1759 m(A a); | |
1760 } | |
1761 abstract class I2 extends I1 {} | |
1762 | |
1763 class T1 implements I2 { | |
1764 /*severe:InvalidMethodOverride*/m(B a) {} | |
1765 } | |
1766 ''' | |
1767 }); | |
1768 testChecker('mixin of interface of child', { | |
1769 '/main.dart': ''' | |
1770 class A {} | |
1771 class B {} | |
1772 | |
1773 abstract class M1 { | |
1774 m(A a); | |
1775 } | |
1776 abstract class I2 extends Object with M1 {} | |
1777 | |
1778 class T1 implements I2 { | |
1779 /*severe:InvalidMethodOverride*/m(B a) {} | |
1780 } | |
1781 ''' | |
1782 }); | |
1783 testChecker('interface of abstract superclass', { | |
1784 '/main.dart': ''' | |
1785 class A {} | |
1786 class B {} | |
1787 | |
1788 abstract class I1 { | |
1789 m(A a); | |
1790 } | |
1791 abstract class Base implements I1 {} | |
1792 | |
1793 class T1 extends Base { | |
1794 /*severe:InvalidMethodOverride*/m(B a) {} | |
1795 } | |
1796 ''' | |
1797 }); | |
1798 testChecker('interface of concrete superclass', { | |
1799 '/main.dart': ''' | |
1800 class A {} | |
1801 class B {} | |
1802 | |
1803 abstract class I1 { | |
1804 m(A a); | |
1805 } | |
1806 | |
1807 // See issue #25 | |
1808 /*pass should be warning:AnalyzerError*/class Base implements I1 { | |
1809 } | |
1810 | |
1811 class T1 extends Base { | |
1812 // not reported technically because if the class is concrete, | |
1813 // it should implement all its interfaces and hence it is | |
1814 // sufficient to check overrides against it. | |
1815 m(B a) {} | |
1816 } | |
1817 ''' | |
1818 }); | |
1819 }); | |
1820 | |
1821 group('mixin override of grand interface', () { | |
1822 testChecker('interface of interface of child', { | |
1823 '/main.dart': ''' | |
1824 class A {} | |
1825 class B {} | |
1826 | |
1827 abstract class I1 { | |
1828 m(A a); | |
1829 } | |
1830 abstract class I2 implements I1 {} | |
1831 | |
1832 class M { | |
1833 m(B a) {} | |
1834 } | |
1835 | |
1836 class T1 extends Object with /*severe:InvalidMethodOverride*/M | |
1837 implements I2 { | |
1838 } | |
1839 ''' | |
1840 }); | |
1841 testChecker('superclass of interface of child', { | |
1842 '/main.dart': ''' | |
1843 class A {} | |
1844 class B {} | |
1845 | |
1846 abstract class I1 { | |
1847 m(A a); | |
1848 } | |
1849 abstract class I2 extends I1 {} | |
1850 | |
1851 class M { | |
1852 m(B a) {} | |
1853 } | |
1854 | |
1855 class T1 extends Object with /*severe:InvalidMethodOverride*/M | |
1856 implements I2 { | |
1857 } | |
1858 ''' | |
1859 }); | |
1860 testChecker('mixin of interface of child', { | |
1861 '/main.dart': ''' | |
1862 class A {} | |
1863 class B {} | |
1864 | |
1865 abstract class M1 { | |
1866 m(A a); | |
1867 } | |
1868 abstract class I2 extends Object with M1 {} | |
1869 | |
1870 class M { | |
1871 m(B a) {} | |
1872 } | |
1873 | |
1874 class T1 extends Object with /*severe:InvalidMethodOverride*/M | |
1875 implements I2 { | |
1876 } | |
1877 ''' | |
1878 }); | |
1879 testChecker('interface of abstract superclass', { | |
1880 '/main.dart': ''' | |
1881 class A {} | |
1882 class B {} | |
1883 | |
1884 abstract class I1 { | |
1885 m(A a); | |
1886 } | |
1887 abstract class Base implements I1 {} | |
1888 | |
1889 class M { | |
1890 m(B a) {} | |
1891 } | |
1892 | |
1893 class T1 extends Base with /*severe:InvalidMethodOverride*/M { | |
1894 } | |
1895 ''' | |
1896 }); | |
1897 testChecker('interface of concrete superclass', { | |
1898 '/main.dart': ''' | |
1899 class A {} | |
1900 class B {} | |
1901 | |
1902 abstract class I1 { | |
1903 m(A a); | |
1904 } | |
1905 | |
1906 // See issue #25 | |
1907 /*pass should be warning:AnalyzerError*/class Base implements I1 { | |
1908 } | |
1909 | |
1910 class M { | |
1911 m(B a) {} | |
1912 } | |
1913 | |
1914 class T1 extends Base with M { | |
1915 } | |
1916 ''' | |
1917 }); | |
1918 }); | |
1919 | |
1920 group('superclass override of grand interface', () { | |
1921 testChecker('interface of interface of child', { | |
1922 '/main.dart': ''' | |
1923 class A {} | |
1924 class B {} | |
1925 | |
1926 abstract class I1 { | |
1927 m(A a); | |
1928 } | |
1929 abstract class I2 implements I1 {} | |
1930 | |
1931 class Base { | |
1932 m(B a) {} | |
1933 } | |
1934 | |
1935 class T1 /*severe:InvalidMethodOverride*/extends Base | |
1936 implements I2 { | |
1937 } | |
1938 ''' | |
1939 }); | |
1940 testChecker('superclass of interface of child', { | |
1941 '/main.dart': ''' | |
1942 class A {} | |
1943 class B {} | |
1944 | |
1945 abstract class I1 { | |
1946 m(A a); | |
1947 } | |
1948 abstract class I2 extends I1 {} | |
1949 | |
1950 class Base { | |
1951 m(B a) {} | |
1952 } | |
1953 | |
1954 class T1 /*severe:InvalidMethodOverride*/extends Base | |
1955 implements I2 { | |
1956 } | |
1957 ''' | |
1958 }); | |
1959 testChecker('mixin of interface of child', { | |
1960 '/main.dart': ''' | |
1961 class A {} | |
1962 class B {} | |
1963 | |
1964 abstract class M1 { | |
1965 m(A a); | |
1966 } | |
1967 abstract class I2 extends Object with M1 {} | |
1968 | |
1969 class Base { | |
1970 m(B a) {} | |
1971 } | |
1972 | |
1973 class T1 /*severe:InvalidMethodOverride*/extends Base | |
1974 implements I2 { | |
1975 } | |
1976 ''' | |
1977 }); | |
1978 testChecker('interface of abstract superclass', { | |
1979 '/main.dart': ''' | |
1980 class A {} | |
1981 class B {} | |
1982 | |
1983 abstract class I1 { | |
1984 m(A a); | |
1985 } | |
1986 | |
1987 abstract class Base implements I1 { | |
1988 /*severe:InvalidMethodOverride*/m(B a) {} | |
1989 } | |
1990 | |
1991 class T1 extends Base { | |
1992 // we consider the base class incomplete because it is | |
1993 // abstract, so we report the error here too. | |
1994 // TODO(sigmund): consider tracking overrides in a fine-grain | |
1995 // manner, then this and the double-overrides would not be | |
1996 // reported. | |
1997 /*severe:InvalidMethodOverride*/m(B a) {} | |
1998 } | |
1999 ''' | |
2000 }); | |
2001 testChecker('interface of concrete superclass', { | |
2002 '/main.dart': ''' | |
2003 class A {} | |
2004 class B {} | |
2005 | |
2006 abstract class I1 { | |
2007 m(A a); | |
2008 } | |
2009 | |
2010 class Base implements I1 { | |
2011 /*severe:InvalidMethodOverride*/m(B a) {} | |
2012 } | |
2013 | |
2014 class T1 extends Base { | |
2015 m(B a) {} | |
2016 } | |
2017 ''' | |
2018 }); | |
2019 }); | |
2020 | |
2021 group('no duplicate reports from overriding interfaces', () { | |
2022 testChecker('type overrides same method in multiple interfaces', { | |
2023 '/main.dart': ''' | |
2024 class A {} | |
2025 class B {} | |
2026 | |
2027 abstract class I1 { | |
2028 m(A a); | |
2029 } | |
2030 abstract class I2 implements I1 { | |
2031 m(A a); | |
2032 } | |
2033 | |
2034 class Base { | |
2035 } | |
2036 | |
2037 class T1 implements I2 { | |
2038 /*severe:InvalidMethodOverride*/m(B a) {} | |
2039 } | |
2040 ''' | |
2041 }); | |
2042 | |
2043 testChecker('type and base type override same method in interface', { | |
2044 '/main.dart': ''' | |
2045 class A {} | |
2046 class B {} | |
2047 | |
2048 abstract class I1 { | |
2049 m(A a); | |
2050 } | |
2051 | |
2052 class Base { | |
2053 m(B a); | |
2054 } | |
2055 | |
2056 // Note: no error reported in `extends Base` to avoid duplicating | |
2057 // the error in T1. | |
2058 class T1 extends Base implements I1 { | |
2059 /*severe:InvalidMethodOverride*/m(B a) {} | |
2060 } | |
2061 | |
2062 // If there is no error in the class, we do report the error at | |
2063 // the base class: | |
2064 class T2 /*severe:InvalidMethodOverride*/extends Base | |
2065 implements I1 { | |
2066 } | |
2067 ''' | |
2068 }); | |
2069 | |
2070 testChecker('type and mixin override same method in interface', { | |
2071 '/main.dart': ''' | |
2072 class A {} | |
2073 class B {} | |
2074 | |
2075 abstract class I1 { | |
2076 m(A a); | |
2077 } | |
2078 | |
2079 class M { | |
2080 m(B a); | |
2081 } | |
2082 | |
2083 class T1 extends Object with M implements I1 { | |
2084 /*severe:InvalidMethodOverride*/m(B a) {} | |
2085 } | |
2086 | |
2087 class T2 extends Object with /*severe:InvalidMethodOverride*/M | |
2088 implements I1 { | |
2089 } | |
2090 ''' | |
2091 }); | |
2092 | |
2093 testChecker('two grand types override same method in interface', { | |
2094 '/main.dart': ''' | |
2095 class A {} | |
2096 class B {} | |
2097 | |
2098 abstract class I1 { | |
2099 m(A a); | |
2100 } | |
2101 | |
2102 class Grandparent { | |
2103 m(B a) {} | |
2104 } | |
2105 | |
2106 class Parent1 extends Grandparent { | |
2107 m(B a) {} | |
2108 } | |
2109 class Parent2 extends Grandparent { | |
2110 } | |
2111 | |
2112 // Note: otherwise both errors would be reported on this line | |
2113 class T1 /*severe:InvalidMethodOverride*/extends Parent1 | |
2114 implements I1 { | |
2115 } | |
2116 class T2 /*severe:InvalidMethodOverride*/extends Parent2 | |
2117 implements I1 { | |
2118 } | |
2119 ''' | |
2120 }); | |
2121 | |
2122 testChecker('two mixins override same method in interface', { | |
2123 '/main.dart': ''' | |
2124 class A {} | |
2125 class B {} | |
2126 | |
2127 abstract class I1 { | |
2128 m(A a); | |
2129 } | |
2130 | |
2131 class M1 { | |
2132 m(B a) {} | |
2133 } | |
2134 | |
2135 class M2 { | |
2136 m(B a) {} | |
2137 } | |
2138 | |
2139 // Here we want to report both, because the error location is | |
2140 // different. | |
2141 // TODO(sigmund): should we merge these as well? | |
2142 class T1 extends Object | |
2143 with /*severe:InvalidMethodOverride*/M1 | |
2144 with /*severe:InvalidMethodOverride*/M2 | |
2145 implements I1 { | |
2146 } | |
2147 ''' | |
2148 }); | |
2149 | |
2150 testChecker('base type and mixin override same method in interface', { | |
2151 '/main.dart': ''' | |
2152 class A {} | |
2153 class B {} | |
2154 | |
2155 abstract class I1 { | |
2156 m(A a); | |
2157 } | |
2158 | |
2159 class Base { | |
2160 m(B a) {} | |
2161 } | |
2162 | |
2163 class M { | |
2164 m(B a) {} | |
2165 } | |
2166 | |
2167 // Here we want to report both, because the error location is | |
2168 // different. | |
2169 // TODO(sigmund): should we merge these as well? | |
2170 class T1 /*severe:InvalidMethodOverride*/extends Base | |
2171 with /*severe:InvalidMethodOverride*/M | |
2172 implements I1 { | |
2173 } | |
2174 ''' | |
2175 }); | |
2176 }); | |
2177 | |
2178 testChecker('invalid runtime checks', { | |
2179 '/main.dart': ''' | |
2180 typedef int I2I(int x); | |
2181 typedef int D2I(x); | |
2182 typedef int II2I(int x, int y); | |
2183 typedef int DI2I(x, int y); | |
2184 typedef int ID2I(int x, y); | |
2185 typedef int DD2I(x, y); | |
2186 | |
2187 typedef I2D(int x); | |
2188 typedef D2D(x); | |
2189 typedef II2D(int x, int y); | |
2190 typedef DI2D(x, int y); | |
2191 typedef ID2D(int x, y); | |
2192 typedef DD2D(x, y); | |
2193 | |
2194 int foo(int x) => x; | |
2195 int bar(int x, int y) => x + y; | |
2196 | |
2197 void main() { | |
2198 bool b; | |
2199 b = /*info:NonGroundTypeCheckInfo*/foo is I2I; | |
2200 b = /*info:NonGroundTypeCheckInfo*/foo is D2I; | |
2201 b = /*info:NonGroundTypeCheckInfo*/foo is I2D; | |
2202 b = foo is D2D; | |
2203 | |
2204 b = /*info:NonGroundTypeCheckInfo*/bar is II2I; | |
2205 b = /*info:NonGroundTypeCheckInfo*/bar is DI2I; | |
2206 b = /*info:NonGroundTypeCheckInfo*/bar is ID2I; | |
2207 b = /*info:NonGroundTypeCheckInfo*/bar is II2D; | |
2208 b = /*info:NonGroundTypeCheckInfo*/bar is DD2I; | |
2209 b = /*info:NonGroundTypeCheckInfo*/bar is DI2D; | |
2210 b = /*info:NonGroundTypeCheckInfo*/bar is ID2D; | |
2211 b = bar is DD2D; | |
2212 | |
2213 // For as, the validity of checks is deferred to runtime. | |
2214 Function f; | |
2215 f = foo as I2I; | |
2216 f = foo as D2I; | |
2217 f = foo as I2D; | |
2218 f = foo as D2D; | |
2219 | |
2220 f = bar as II2I; | |
2221 f = bar as DI2I; | |
2222 f = bar as ID2I; | |
2223 f = bar as II2D; | |
2224 f = bar as DD2I; | |
2225 f = bar as DI2D; | |
2226 f = bar as ID2D; | |
2227 f = bar as DD2D; | |
2228 } | |
2229 ''' | |
2230 }); | |
2231 | |
2232 testChecker('custom URL mappings', { | |
2233 '/main.dart': ''' | |
2234 import 'dart:foobar' show Baz; | |
2235 main() { | |
2236 print(Baz.quux); | |
2237 }''' | |
2238 }, customUrlMappings: { | |
2239 'dart:foobar': '$testDirectory/checker/dart_foobar.dart' | |
2240 }); | |
2241 | |
2242 group('function modifiers', () { | |
2243 testChecker('async', { | |
2244 '/main.dart': ''' | |
2245 import 'dart:async'; | |
2246 import 'dart:math' show Random; | |
2247 | |
2248 dynamic x; | |
2249 | |
2250 foo1() async => x; | |
2251 Future foo2() async => x; | |
2252 Future<int> foo3() async => (/*info:DynamicCast*/x); | |
2253 Future<int> foo4() async => (/*severe:StaticTypeError*/new Future<int>.v
alue(/*info:DynamicCast*/x)); | |
2254 | |
2255 bar1() async { return x; } | |
2256 Future bar2() async { return x; } | |
2257 Future<int> bar3() async { return (/*info:DynamicCast*/x); } | |
2258 Future<int> bar4() async { return (/*severe:StaticTypeError*/new Future<
int>.value(/*info:DynamicCast*/x)); } | |
2259 | |
2260 int y; | |
2261 Future<int> z; | |
2262 | |
2263 void baz() async { | |
2264 int a = /*info:DynamicCast*/await x; | |
2265 int b = await y; | |
2266 int c = await z; | |
2267 String d = /*severe:StaticTypeError*/await z; | |
2268 } | |
2269 | |
2270 Future<bool> get issue_264 async { | |
2271 await 42; | |
2272 if (new Random().nextBool()) { | |
2273 return true; | |
2274 } else { | |
2275 return /*severe:StaticTypeError*/new Future<bool>.value(false); | |
2276 } | |
2277 } | |
2278 ''' | |
2279 }); | |
2280 | |
2281 testChecker('async*', { | |
2282 '/main.dart': ''' | |
2283 import 'dart:async'; | |
2284 | |
2285 dynamic x; | |
2286 | |
2287 bar1() async* { yield x; } | |
2288 Stream bar2() async* { yield x; } | |
2289 Stream<int> bar3() async* { yield (/*info:DynamicCast*/x); } | |
2290 Stream<int> bar4() async* { yield (/*severe:StaticTypeError*/new Stream<
int>()); } | |
2291 | |
2292 baz1() async* { yield* (/*info:DynamicCast*/x); } | |
2293 Stream baz2() async* { yield* (/*info:DynamicCast*/x); } | |
2294 Stream<int> baz3() async* { yield* (/*warning:DownCastComposite*/x); } | |
2295 Stream<int> baz4() async* { yield* new Stream<int>(); } | |
2296 Stream<int> baz5() async* { yield* (/*info:InferredTypeAllocation*/new S
tream()); } | |
2297 ''' | |
2298 }); | |
2299 | |
2300 testChecker('sync*', { | |
2301 '/main.dart': ''' | |
2302 import 'dart:async'; | |
2303 | |
2304 dynamic x; | |
2305 | |
2306 bar1() sync* { yield x; } | |
2307 Iterable bar2() sync* { yield x; } | |
2308 Iterable<int> bar3() sync* { yield (/*info:DynamicCast*/x); } | |
2309 Iterable<int> bar4() sync* { yield (/*severe:StaticTypeError*/new Iterab
le<int>()); } | |
2310 | |
2311 baz1() sync* { yield* (/*info:DynamicCast*/x); } | |
2312 Iterable baz2() sync* { yield* (/*info:DynamicCast*/x); } | |
2313 Iterable<int> baz3() sync* { yield* (/*warning:DownCastComposite*/x); } | |
2314 Iterable<int> baz4() sync* { yield* new Iterable<int>(); } | |
2315 Iterable<int> baz5() sync* { yield* (/*info:InferredTypeAllocation*/new
Iterable()); } | |
2316 ''' | |
2317 }); | |
2318 }); | |
2319 } | |
OLD | NEW |