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

Side by Side Diff: tests/compiler/dart2js/cpa_inference_test.dart

Issue 1376113002: dart2js: Remove ConcreteTypeInference (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « pkg/compiler/lib/src/use_unused_api.dart ('k') | tests/compiler/dart2js/mock_compiler.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012, 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 'dart:async';
6 import "package:expect/expect.dart";
7 import "package:async_helper/async_helper.dart";
8 import 'package:compiler/src/types/types.dart';
9 import 'package:compiler/src/inferrer/concrete_types_inferrer.dart';
10 import 'package:compiler/src/universe/call_structure.dart' show
11 CallStructure;
12 import 'package:compiler/src/universe/selector.dart' show
13 Selector;
14
15 import "compiler_helper.dart";
16 import "type_mask_test_helper.dart";
17
18 /**
19 * Finds the node corresponding to the last occurence of the substring
20 * [: identifier; :] in the program represented by the visited AST.
21 */
22 class VariableFinderVisitor extends Visitor {
23 final String identifier;
24 Node result;
25
26 VariableFinderVisitor(this.identifier);
27
28 visitSend(Send node) {
29 if (node.isPropertyAccess
30 && node.selector.asIdentifier().source == identifier) {
31 result = node;
32 } else {
33 node.visitChildren(this);
34 }
35 }
36
37 visitNode(Node node) {
38 node.visitChildren(this);
39 }
40 }
41
42 class AnalysisResult {
43 MockCompiler compiler;
44 ConcreteTypesInferrer inferrer;
45 Node ast;
46
47 BaseType int;
48 BaseType double;
49 BaseType num;
50 BaseType bool;
51 BaseType string;
52 BaseType list;
53 BaseType growableList;
54 BaseType map;
55 BaseType nullType;
56 BaseType functionType;
57
58 AnalysisResult(MockCompiler compiler) : this.compiler = compiler {
59 inferrer = compiler.typesTask.concreteTypesInferrer;
60 int = inferrer.baseTypes.intBaseType;
61 double = inferrer.baseTypes.doubleBaseType;
62 num = inferrer.baseTypes.numBaseType;
63 bool = inferrer.baseTypes.boolBaseType;
64 string = inferrer.baseTypes.stringBaseType;
65 list = inferrer.baseTypes.listBaseType;
66 growableList = inferrer.baseTypes.growableListBaseType;
67 map = inferrer.baseTypes.mapBaseType;
68 nullType = const NullBaseType();
69 functionType = inferrer.baseTypes.functionBaseType;
70 FunctionElement mainElement = compiler.mainApp.find('main');
71 ast = mainElement.node;
72 }
73
74 BaseType base(String className) {
75 final source = className;
76 return new ClassBaseType(compiler.mainApp.find(source));
77 }
78
79 /**
80 * Finds the [Node] corresponding to the last occurence of the substring
81 * [: identifier; :] in the program represented by the visited AST. For
82 * instance, returns the AST node representing [: foo; :] in
83 * [: main() { foo = 1; foo; } :].
84 */
85 Node findNode(String identifier) {
86 VariableFinderVisitor finder = new VariableFinderVisitor(identifier);
87 ast.accept(finder);
88 return finder.result;
89 }
90
91 /**
92 * Finds the [Element] corresponding to [: className#fieldName :].
93 */
94 Element findField(String className, String fieldName) {
95 ClassElement element = compiler.mainApp.find(className);
96 return element.lookupLocalMember(fieldName);
97 }
98
99 ConcreteType concreteFrom(List<BaseType> baseTypes) {
100 ConcreteType result = inferrer.emptyConcreteType;
101 for (final baseType in baseTypes) {
102 result = result.union(inferrer.singletonConcreteType(baseType));
103 }
104 // We make sure the concrete types expected by the tests don't default to
105 // dynamic because of widening.
106 assert(!result.isUnknown());
107 return result;
108 }
109
110 /**
111 * Checks that the inferred type of the node corresponding to the last
112 * occurence of [: variable; :] in the program is the concrete type
113 * made of [baseTypes].
114 */
115 void checkNodeHasType(String variable, List<BaseType> baseTypes) {
116 Expect.equals(
117 concreteFrom(baseTypes),
118 inferrer.inferredTypes[findNode(variable)]);
119 }
120
121 /**
122 * Checks that the inferred type of the node corresponding to the last
123 * occurence of [: variable; :] in the program is the unknown concrete type.
124 */
125 void checkNodeHasUnknownType(String variable) {
126 Expect.isTrue(inferrer.inferredTypes[findNode(variable)].isUnknown());
127 }
128
129 /**
130 * Checks that [: className#fieldName :]'s inferred type is the concrete type
131 * made of [baseTypes].
132 */
133 void checkFieldHasType(String className, String fieldName,
134 List<BaseType> baseTypes) {
135 Expect.equals(
136 concreteFrom(baseTypes),
137 inferrer.inferredFieldTypes[findField(className, fieldName)]);
138 }
139
140 /**
141 * Checks that [: className#fieldName :]'s inferred type is the unknown
142 * concrete type.
143 */
144 void checkFieldHasUknownType(String className, String fieldName) {
145 Expect.isTrue(
146 inferrer.inferredFieldTypes[findField(className, fieldName)]
147 .isUnknown());
148 }
149
150 /** Checks that the inferred type for [selector] is [mask]. */
151 void checkSelectorHasType(Selector selector,
152 TypeMask mask,
153 TypeMask expectedMask) {
154 Expect.equals(expectedMask, inferrer.getTypeOfSelector(selector, mask));
155 }
156 }
157
158 const String DYNAMIC = '"__dynamic_for_test"';
159
160 Future<AnalysisResult> analyze(String code, {int maxConcreteTypeSize: 1000}) {
161 Uri uri = new Uri(scheme: 'dart', path: 'test');
162 MockCompiler compiler = new MockCompiler.internal(
163 enableConcreteTypeInference: true,
164 maxConcreteTypeSize: maxConcreteTypeSize);
165 compiler.diagnosticHandler = createHandler(compiler, code);
166 compiler.registerSource(uri, code);
167 compiler.typesTask.concreteTypesInferrer.testMode = true;
168 return compiler.runCompiler(uri).then((_) {
169 return new AnalysisResult(compiler);
170 });
171 }
172
173 testDynamicBackDoor() {
174 final String source = """
175 main () {
176 var x = $DYNAMIC;
177 x;
178 }
179 """;
180 return analyze(source).then((result) {
181 result.checkNodeHasUnknownType('x');
182 });
183 }
184
185 testVariableDeclaration() {
186 final String source = r"""
187 main() {
188 var v1;
189 var v2;
190 v2 = 1;
191 v1; v2;
192 }
193 """;
194 return analyze(source).then((result) {
195 result.checkNodeHasType('v1', [result.nullType]);
196 result.checkNodeHasType('v2', [result.int]);
197 });
198 }
199
200 testLiterals() {
201 final String source = r"""
202 main() {
203 var v1 = 42;
204 var v2 = 42.1;
205 var v3 = 'abc';
206 var v4 = true;
207 var v5 = null;
208 v1; v2; v3; v4; v5;
209 }
210 """;
211 return analyze(source).then((result) {
212 result.checkNodeHasType('v1', [result.int]);
213 result.checkNodeHasType('v2', [result.double]);
214 result.checkNodeHasType('v3', [result.string]);
215 result.checkNodeHasType('v4', [result.bool]);
216 result.checkNodeHasType('v5', [result.nullType]);
217 });
218 }
219
220 testRedefinition() {
221 final String source = r"""
222 main() {
223 var foo = 42;
224 foo = 'abc';
225 foo;
226 }
227 """;
228 return analyze(source).then((result) {
229 result.checkNodeHasType('foo', [result.string]);
230 });
231 }
232
233 testIfThenElse() {
234 final String source = r"""
235 main() {
236 var foo = 42;
237 if (true) {
238 foo = 'abc';
239 } else {
240 foo = false;
241 }
242 foo;
243 }
244 """;
245 return analyze(source).then((result) {
246 result.checkNodeHasType('foo', [result.string, result.bool]);
247 });
248 }
249
250 testTernaryIf() {
251 final String source = r"""
252 main() {
253 var foo = 42;
254 foo = true ? 'abc' : false;
255 foo;
256 }
257 """;
258 return analyze(source).then((result) {
259 result.checkNodeHasType('foo', [result.string, result.bool]);
260 });
261 }
262
263 testWhile() {
264 final String source = r"""
265 class A { f() => new B(); }
266 class B { f() => new C(); }
267 class C { f() => new A(); }
268 main() {
269 var bar = null;
270 var foo = new A();
271 while(bar = 42) {
272 foo = foo.f();
273 }
274 foo; bar;
275 }
276 """;
277 return analyze(source).then((result) {
278 result.checkNodeHasType(
279 'foo',
280 [result.base('A'), result.base('B'), result.base('C')]);
281 // Check that the condition is evaluated.
282 // TODO(polux): bar's type could be inferred to be {int} here.
283 result.checkNodeHasType('bar', [result.int, result.nullType]);
284 });
285 }
286
287 testDoWhile() {
288 final String source = r"""
289 class A { f() => new B(); }
290 class B { f() => new C(); }
291 class C { f() => new A(); }
292 main() {
293 var bar = null;
294 var foo = new A();
295 do {
296 foo = foo.f();
297 } while (bar = 42);
298 foo; bar;
299 }
300 """;
301 return analyze(source).then((AnalysisResult result) {
302 result.checkNodeHasType(
303 'foo',
304 [result.base('A'), result.base('B'), result.base('C')]);
305 // Check that the condition is evaluated.
306 result.checkNodeHasType('bar', [result.int]);
307 });
308 }
309
310 testFor1() {
311 final String source = r"""
312 class A { f() => new B(); }
313 class B { f() => new C(); }
314 class C { f() => new A(); }
315 main() {
316 var foo = new A();
317 for(;;) {
318 foo = foo.f();
319 }
320 foo;
321 }
322 """;
323 return analyze(source).then((result) {
324 result.checkNodeHasType(
325 'foo',
326 [result.base('A'), result.base('B'), result.base('C')]);
327 });
328 }
329
330 testFor2() {
331 final String source = r"""
332 class A { f() => new B(); test() => true; }
333 class B { f() => new A(); test() => true; }
334 main() {
335 var bar = null;
336 var foo = new A();
337 for(var i = new A(); bar = 42; i = i.f()) {
338 foo = i;
339 }
340 foo; bar;
341 }
342 """;
343 return analyze(source).then((result) {
344 result.checkNodeHasType('foo', [result.base('A'), result.base('B')]);
345 // Check that the condition is evaluated.
346 // TODO(polux): bar's type could be inferred to be {int} here.
347 result.checkNodeHasType('bar', [result.int, result.nullType]);
348 });
349 }
350
351 testFor3() {
352 final String source = r"""
353 main() {
354 var i = 1;
355 for(;;) {
356 var x = 2;
357 i = x;
358 }
359 i;
360 }
361 """;
362 return analyze(source).then((result) {
363 result.checkNodeHasType('i', [result.int]);
364 });
365 }
366
367 testForIn() {
368 final String source = r"""
369 class MyIterator {
370 var counter = 0;
371
372 moveNext() {
373 if (counter == 0) {
374 counter = 1;
375 return true;
376 } else if (counter == 1) {
377 counter = 2;
378 return true;
379 } else {
380 return false;
381 }
382 }
383
384 get current => (counter == 1) ? "foo" : 42;
385 }
386
387 class MyIterable {
388 get iterator => new MyIterator();
389 }
390
391 main() {
392 var res;
393 for (var i in new MyIterable()) {
394 res = i;
395 }
396 res;
397 }
398 """;
399 return analyze(source).then((AnalysisResult result) {
400 result.checkNodeHasType('res',
401 [result.int, result.string, result.nullType]);
402 });
403 }
404
405 testToplevelVariable() {
406 final String source = r"""
407 final top = 'abc';
408 class A {
409 f() => top;
410 }
411 main() {
412 var foo = top;
413 var bar = new A().f();
414 foo; bar;
415 }
416 """;
417 return analyze(source).then((result) {
418 result.checkNodeHasType('foo', [result.string]);
419 result.checkNodeHasType('bar', [result.string]);
420 });
421 }
422
423 testToplevelVariable2() {
424 final String source = r"""
425 class A {
426 var x;
427 }
428 final top = new A().x;
429
430 main() {
431 var a = new A();
432 a.x = 42;
433 a.x = "abc";
434 var foo = top;
435 foo;
436 }
437 """;
438 return analyze(source).then((result) {
439 result.checkNodeHasType('foo', [result.nullType, result.int,
440 result.string]);
441 });
442 }
443
444 testToplevelVariable3() {
445 final String source = r"""
446 var top = "a";
447
448 f() => top;
449
450 main() {
451 var foo = f();
452 var bar = top;
453 top = 42;
454 var baz = top;
455 foo; bar; baz;
456 }
457 """;
458 return analyze(source).then((result) {
459 result.checkNodeHasType('foo', [result.int, result.string]);
460 result.checkNodeHasType('bar', [result.int, result.string]);
461 result.checkNodeHasType('baz', [result.int, result.string]);
462 });
463 }
464
465 testNonRecusiveFunction() {
466 final String source = r"""
467 f(x, y) => true ? x : y;
468 main() { var foo = f(42, "abc"); foo; }
469 """;
470 return analyze(source).then((result) {
471 result.checkNodeHasType('foo', [result.int, result.string]);
472 });
473 }
474
475 testMultipleReturns() {
476 final String source = r"""
477 f(x, y) {
478 if (true) return x;
479 else return y;
480 }
481 main() { var foo = f(42, "abc"); foo; }
482 """;
483 return analyze(source).then((result) {
484 result.checkNodeHasType('foo', [result.int, result.string]);
485 });
486 }
487
488 testRecusiveFunction() {
489 final String source = r"""
490 f(x) {
491 if (true) return x;
492 else return f(true ? x : "abc");
493 }
494 main() { var foo = f(42); foo; }
495 """;
496 return analyze(source).then((result) {
497 result.checkNodeHasType('foo', [result.int, result.string]);
498 });
499 }
500
501 testMutuallyRecusiveFunction() {
502 final String source = r"""
503 f() => true ? 42 : g();
504 g() => true ? "abc" : f();
505 main() { var foo = f(); foo; }
506 """;
507 return analyze(source).then((result) {
508 result.checkNodeHasType('foo', [result.int, result.string]);
509 });
510 }
511
512 testSimpleSend() {
513 final String source = """
514 class A {
515 f(x) => x;
516 }
517 class B {
518 f(x) => 'abc';
519 }
520 class C {
521 f(x) => 3.14;
522 }
523 class D {
524 var f; // we check that this field is ignored in calls to dynamic.f()
525 D(this.f);
526 }
527 main() {
528 new B(); new D(42); // we instantiate B and D but not C
529 var foo = new A().f(42);
530 var bar = $DYNAMIC.f(42);
531 foo; bar;
532 }
533 """;
534 return analyze(source).then((result) {
535 result.checkNodeHasType('foo', [result.int]);
536 result.checkNodeHasType('bar', [result.int, result.string]);
537 });
538 }
539
540 testSendToThis1() {
541 final String source = r"""
542 class A {
543 A();
544 f() => g();
545 g() => 42;
546 }
547 main() {
548 var foo = new A().f();
549 foo;
550 }
551 """;
552 return analyze(source).then((result) {
553 result.checkNodeHasType('foo', [result.int]);
554 });
555 }
556
557 testSendToThis2() {
558 final String source = r"""
559 class A {
560 foo() => this;
561 }
562 class B extends A {
563 bar() => foo();
564 }
565 main() {
566 var x = new B().bar();
567 x;
568 }
569 """;
570 return analyze(source).then((result) {
571 result.checkNodeHasType('x', [result.base('B')]);
572 });
573 }
574
575 testSendToThis3() {
576 final String source = r"""
577 class A {
578 bar() => 42;
579 foo() => bar();
580 }
581 class B extends A {
582 bar() => "abc";
583 }
584 main() {
585 var x = new B().foo();
586 x;
587 }
588 """;
589 return analyze(source).then((AnalysisResult result) {
590 result.checkNodeHasType('x', [result.string]);
591 });
592 }
593
594 testSendToThis4() {
595 final String source = """
596 class A {
597 bar() => 42;
598 foo() => bar();
599 }
600 class B extends A {
601 bar() => "abc";
602 }
603 main() {
604 new A(); new B(); // make A and B seen
605 var x = $DYNAMIC.foo();
606 x;
607 }
608 """;
609 return analyze(source).then((AnalysisResult result) {
610 result.checkNodeHasType('x', [result.int, result.string]);
611 });
612 }
613
614 testConstructor() {
615 final String source = r"""
616 class A {
617 var x, y, z;
618 A(this.x, a) : y = a { z = 'abc'; }
619 }
620 main() {
621 new A(42, 'abc');
622 new A(true, null);
623 }
624 """;
625 return analyze(source).then((result) {
626 result.checkFieldHasType('A', 'x', [result.int, result.bool]);
627 result.checkFieldHasType('A', 'y', [result.string, result.nullType]);
628 result.checkFieldHasType('A', 'z', [result.string]);
629 });
630 }
631
632 testGetters() {
633 final String source = """
634 class A {
635 var x;
636 A(this.x);
637 get y => x;
638 get z => y;
639 }
640 class B {
641 var x;
642 B(this.x);
643 }
644 main() {
645 var a = new A(42);
646 var b = new B('abc');
647 var foo = a.x;
648 var bar = a.y;
649 var baz = a.z;
650 var qux = null.x;
651 var quux = $DYNAMIC.x;
652 foo; bar; baz; qux; quux;
653 }
654 """;
655 return analyze(source).then((result) {
656 result.checkNodeHasType('foo', [result.int]);
657 result.checkNodeHasType('bar', [result.int]);
658 result.checkNodeHasType('baz', [result.int]);
659 result.checkNodeHasType('qux', []);
660 result.checkNodeHasType('quux', [result.int, result.string]);
661 });
662 }
663
664 testDynamicGetters() {
665 final String source = """
666 class A {
667 get x => f();
668 f() => 42;
669 }
670 class B extends A {
671 f() => "abc";
672 }
673 main() {
674 new A(); new B(); // make A and B seen
675 var x = $DYNAMIC.x;
676 x;
677 }
678 """;
679 return analyze(source).then((result) {
680 result.checkNodeHasType('x', [result.int, result.string]);
681 });
682 }
683
684 testToplevelGetters() {
685 final String source = """
686 int _x = 42;
687 get x => _x;
688
689 f() => x;
690
691 main() {
692 var foo = f();
693 var bar = x;
694 _x = "a";
695 var baz = x;
696 foo; bar; baz;
697 }
698 """;
699 return analyze(source).then((result) {
700 result.checkNodeHasType('foo', [result.int, result.string]);
701 result.checkNodeHasType('bar', [result.int, result.string]);
702 result.checkNodeHasType('baz', [result.int, result.string]);
703 });
704 }
705
706 testSetters() {
707 final String source = """
708 class A {
709 var x;
710 var w;
711 A(this.x, this.w);
712 set y(a) { x = a; z = a; }
713 set z(a) { w = a; }
714 }
715 class B {
716 var x;
717 B(this.x);
718 }
719 main() {
720 var a = new A(42, 42);
721 var b = new B(42);
722 a.x = 'abc';
723 a.y = true;
724 null.x = 42; // should be ignored
725 $DYNAMIC.x = null;
726 $DYNAMIC.y = 3.14;
727 }
728 """;
729 return analyze(source).then((result) {
730 result.checkFieldHasType('B', 'x',
731 [result.int, // new B(42)
732 result.nullType]); // dynamic.x = null
733 result.checkFieldHasType('A', 'x',
734 [result.int, // new A(42, ...)
735 result.string, // a.x = 'abc'
736 result.bool, // a.y = true
737 result.nullType, // dynamic.x = null
738 result.double]); // dynamic.y = 3.14
739 result.checkFieldHasType('A', 'w',
740 [result.int, // new A(..., 42)
741 result.bool, // a.y = true
742 result.double]); // dynamic.y = 3.14
743 });
744 }
745
746 testToplevelSetters() {
747 final String source = """
748 int _x = 42;
749 set x(y) => _x = y;
750
751 f(y) { x = y; }
752
753 main() {
754 var foo = _x;
755 x = "a";
756 var bar = _x;
757 f(true);
758 var baz = _x;
759 foo; bar; baz;
760 }
761 """;
762 return analyze(source).then((result) {
763 result.checkNodeHasType('foo', [result.int, result.string, result.bool]);
764 result.checkNodeHasType('bar', [result.int, result.string, result.bool]);
765 result.checkNodeHasType('baz', [result.int, result.string, result.bool]);
766 });
767 }
768
769
770 testOptionalNamedParameters() {
771 final String source = r"""
772 class A {
773 var x, y, z, w;
774 A(this.x, {this.y, this.z, this.w});
775 }
776 class B {
777 var x, y;
778 B(this.x, {this.y});
779 }
780 class C {
781 var x, y;
782 C(this.x, {this.y});
783 }
784 class Test {
785 var a, b, c, d;
786 var e, f;
787 var g, h;
788
789 Test(this.a, this.b, this.c, this.d,
790 this.e, this.f,
791 this.g, this.h);
792
793 f1(x, {y, z, w}) {
794 a = x;
795 b = y;
796 c = z;
797 d = w;
798 }
799 f2(x, {y}) {
800 e = x;
801 f = y;
802 }
803 f3(x, {y}) {
804 g = x;
805 h = y;
806 }
807 }
808 class Foo {
809 }
810 main() {
811 // We want to test expiclitely for null later so we initialize all the
812 // fields of Test with a placeholder type: Foo.
813 var foo = new Foo();
814 var test = new Test(foo, foo, foo, foo, foo, foo, foo, foo);
815
816 new A(42);
817 new A('abc', w: true, z: 42.1);
818 test.f1(42);
819 test.f1('abc', w: true, z: 42.1);
820
821 new B('abc', y: true);
822 new B(1, 2); // too many positional arguments
823 test.f2('abc', y: true);
824 test.f2(1, 2); // too many positional arguments
825
826 new C('abc', y: true);
827 new C(1, z: 2); // non-existing named parameter
828 test.f3('abc', y: true);
829 test.f3(1, z: 2); // non-existing named parameter
830 }
831 """;
832 return analyze(source).then((result) {
833
834 final foo = result.base('Foo');
835 final nil = result.nullType;
836
837 result.checkFieldHasType('A', 'x', [result.int, result.string]);
838 result.checkFieldHasType('A', 'y', [nil]);
839 result.checkFieldHasType('A', 'z', [nil, result.double]);
840 result.checkFieldHasType('A', 'w', [nil, result.bool]);
841 result.checkFieldHasType('Test', 'a', [foo, result.int, result.string]);
842 result.checkFieldHasType('Test', 'b', [foo, nil]);
843 result.checkFieldHasType('Test', 'c', [foo, nil, result.double]);
844 result.checkFieldHasType('Test', 'd', [foo, nil, result.bool]);
845
846 result.checkFieldHasType('B', 'x', [result.string]);
847 result.checkFieldHasType('B', 'y', [result.bool]);
848 result.checkFieldHasType('Test', 'e', [foo, result.string]);
849 result.checkFieldHasType('Test', 'f', [foo, result.bool]);
850
851 result.checkFieldHasType('C', 'x', [result.string]);
852 result.checkFieldHasType('C', 'y', [result.bool]);
853 result.checkFieldHasType('Test', 'g', [foo, result.string]);
854 result.checkFieldHasType('Test', 'h', [foo, result.bool]);
855 });
856 }
857
858 testOptionalPositionalParameters() {
859 final String source = r"""
860 class A {
861 var x, y, z, w;
862 A(this.x, [this.y, this.z, this.w]);
863 }
864 class B {
865 var x, y;
866 B(this.x, [this.y]);
867 }
868 class Test {
869 var a, b, c, d;
870 var e, f;
871
872 Test(this.a, this.b, this.c, this.d,
873 this.e, this.f);
874
875 f1(x, [y, z, w]) {
876 a = x;
877 b = y;
878 c = z;
879 d = w;
880 }
881 f2(x, [y]) {
882 e = x;
883 f = y;
884 }
885 }
886 class Foo {
887 }
888 main() {
889 // We want to test expiclitely for null later so we initialize all the
890 // fields of Test with a placeholder type: Foo.
891 var foo = new Foo();
892 var test = new Test(foo, foo, foo, foo, foo, foo);
893
894 new A(42);
895 new A('abc', true, 42.1);
896 test.f1(42);
897 test.f1('abc', true, 42.1);
898
899 new B('a', true);
900 new B(1, 2, 3); // too many arguments
901 test.f2('a', true);
902 test.f2(1, 2, 3); // too many arguments
903 }
904 """;
905 return analyze(source).then((result) {
906
907 final foo = result.base('Foo');
908 final nil = result.nullType;
909
910 result.checkFieldHasType('A', 'x', [result.int, result.string]);
911 result.checkFieldHasType('A', 'y', [nil, result.bool]);
912 result.checkFieldHasType('A', 'z', [nil, result.double]);
913 result.checkFieldHasType('A', 'w', [nil]);
914 result.checkFieldHasType('Test', 'a', [foo, result.int, result.string]);
915 result.checkFieldHasType('Test', 'b', [foo, nil, result.bool]);
916 result.checkFieldHasType('Test', 'c', [foo, nil, result.double]);
917 result.checkFieldHasType('Test', 'd', [foo, nil]);
918
919 result.checkFieldHasType('B', 'x', [result.string]);
920 result.checkFieldHasType('B', 'y', [result.bool]);
921 result.checkFieldHasType('Test', 'e', [foo, result.string]);
922 result.checkFieldHasType('Test', 'f', [foo, result.bool]);
923 });
924 }
925
926 testListLiterals() {
927 final String source = r"""
928 class A {
929 var x;
930 A(this.x);
931 }
932 main() {
933 var x = [];
934 var y = [1, "a", null, new A(42)];
935 x; y;
936 }
937 """;
938 return analyze(source).then((result) {
939 result.checkNodeHasType('x', [result.growableList]);
940 result.checkNodeHasType('y', [result.growableList]);
941 result.checkFieldHasType('A', 'x', [result.int]);
942 });
943 }
944
945 testMapLiterals() {
946 final String source = r"""
947 class A {
948 var x;
949 A(this.x);
950 }
951 main() {
952 var x = {};
953 var y = {'a': "foo", 'b': new A(42) };
954 x; y;
955 }
956 """;
957 return analyze(source).then((result) {
958 result.checkNodeHasType('x', [result.map]);
959 result.checkNodeHasType('y', [result.map]);
960 result.checkFieldHasType('A', 'x', [result.int]);
961 });
962 }
963
964 testReturn() {
965 final String source = r"""
966 f() { if (true) { return 1; }; return "a"; }
967 g() { f(); return; }
968 main() {
969 var x = f();
970 var y = g();
971 x; y;
972 }
973 """;
974 return analyze(source).then((result) {
975 result.checkNodeHasType('x', [result.int, result.string]);
976 result.checkNodeHasType('y', [result.nullType]);
977 });
978 }
979
980 testNoReturn() {
981 final String source = r"""
982 f() { if (true) { return 1; }; }
983 g() { f(); }
984 main() {
985 var x = f();
986 var y = g();
987 x; y;
988 }
989 """;
990 return analyze(source).then((result) {
991 result.checkNodeHasType('x', [result.int, result.nullType]);
992 result.checkNodeHasType('y', [result.nullType]);
993 });
994 }
995
996 testArithmeticOperators() {
997 String source(op) {
998 return """
999 main() {
1000 var a = 1 $op 2;
1001 var b = 1 $op 2.1;
1002 var c = 1.1 $op 2;
1003 var d = 1.1 $op 2.1;
1004 var e = (1 $op 2.1) $op 1;
1005 var f = 1 $op (1 $op 2.1);
1006 var g = (1 $op 2.1) $op 1.1;
1007 var h = 1.1 $op (1 $op 2);
1008 var i = (1 $op 2) $op 1;
1009 var j = 1 $op (1 $op 2);
1010 var k = (1.1 $op 2.1) $op 1.1;
1011 var l = 1.1 $op (1.1 $op 2.1);
1012 a; b; c; d; e; f; g; h; i; j; k; l;
1013 }""";
1014 }
1015 return Future.forEach(['+', '*', '-'], (String op) {
1016 return analyze(source(op)).then((result) {
1017 result.checkNodeHasType('a', [result.int]);
1018 result.checkNodeHasType('b', [result.num]);
1019 result.checkNodeHasType('c', [result.num]);
1020 result.checkNodeHasType('d', [result.double]);
1021 result.checkNodeHasType('e', [result.num]);
1022 result.checkNodeHasType('f', [result.num]);
1023 result.checkNodeHasType('g', [result.num]);
1024 result.checkNodeHasType('h', [result.num]);
1025 result.checkNodeHasType('i', [result.int]);
1026 result.checkNodeHasType('j', [result.int]);
1027 result.checkNodeHasType('k', [result.double]);
1028 result.checkNodeHasType('l', [result.double]);
1029 });
1030 });
1031 }
1032
1033 testBooleanOperators() {
1034 String source(op) {
1035 return """
1036 main() {
1037 var a = true $op null;
1038 var b = null $op true;
1039 var c = 1 $op true;
1040 var d = true $op "a";
1041 a; b; c; d;
1042 }""";
1043 }
1044 return Future.forEach(['&&', '||'], (String op) {
1045 return analyze(source(op)).then((result) {
1046 result.checkNodeHasType('a', [result.bool]);
1047 result.checkNodeHasType('b', [result.bool]);
1048 result.checkNodeHasType('c', [result.bool]);
1049 result.checkNodeHasType('d', [result.bool]);
1050 });
1051 });
1052 }
1053
1054 testBooleanOperatorsShortCirtcuit() {
1055 String source(op) {
1056 return """
1057 main() {
1058 var x = null;
1059 "foo" $op (x = 42);
1060 x;
1061 }""";
1062 }
1063 return Future.forEach(['&&', '||'], (String op) {
1064 return analyze(source(op)).then((AnalysisResult result) {
1065 result.checkNodeHasType('x', [result.nullType, result.int]);
1066 });
1067 });
1068 }
1069
1070 testOperators() {
1071 final String source = r"""
1072 class A {
1073 operator <(x) => 42;
1074 operator <<(x) => "a";
1075 }
1076 main() {
1077 var x = new A() < "foo";
1078 var y = new A() << "foo";
1079 x; y;
1080 }
1081 """;
1082 return analyze(source).then((result) {
1083 result.checkNodeHasType('x', [result.int]);
1084 result.checkNodeHasType('y', [result.string]);
1085 });
1086 }
1087
1088 testSetIndexOperator() {
1089 final String source = r"""
1090 class A {
1091 var witness1;
1092 var witness2;
1093 operator []=(i, x) { witness1 = i; witness2 = x; }
1094 }
1095 main() {
1096 var x = new A()[42] = "abc";
1097 x;
1098 }
1099 """;
1100 return analyze(source).then((result) {
1101 result.checkNodeHasType('x', [result.string]);
1102 result.checkFieldHasType('A', 'witness1', [result.int, result.nullType]);
1103 result.checkFieldHasType('A', 'witness2', [result.string, result.nullType]);
1104 });
1105 }
1106
1107 testCompoundOperators1() {
1108 final String source = r"""
1109 class A {
1110 operator +(x) => "foo";
1111 }
1112 main() {
1113 var x1 = 1;
1114 x1++;
1115 var x2 = 1;
1116 ++x2;
1117 var x3 = 1;
1118 x3 += 42;
1119 var x4 = new A();
1120 x4++;
1121 var x5 = new A();
1122 ++x5;
1123 var x6 = new A();
1124 x6 += true;
1125
1126 x1; x2; x3; x4; x5; x6;
1127 }
1128 """;
1129 return analyze(source).then((result) {
1130 result.checkNodeHasType('x1', [result.int]);
1131 result.checkNodeHasType('x2', [result.int]);
1132 result.checkNodeHasType('x3', [result.int]);
1133 result.checkNodeHasType('x4', [result.string]);
1134 result.checkNodeHasType('x5', [result.string]);
1135 result.checkNodeHasType('x6', [result.string]);
1136 });
1137 }
1138
1139
1140 testCompoundOperators2() {
1141 final String source = r"""
1142 class A {
1143 var xx;
1144 var yy;
1145 var witness1;
1146 var witness2;
1147 var witness3;
1148 var witness4;
1149
1150 A(this.xx, this.yy);
1151 get x { witness1 = "foo"; return xx; }
1152 set x(a) { witness2 = "foo"; xx = a; }
1153 get y { witness3 = "foo"; return yy; }
1154 set y(a) { witness4 = "foo"; yy = a; }
1155 }
1156 main () {
1157 var a = new A(1, 1);
1158 a.x++;
1159 a.y++;
1160 }
1161 """;
1162 return analyze(source).then((result) {
1163 result.checkFieldHasType('A', 'xx', [result.int]);
1164 result.checkFieldHasType('A', 'yy', [result.int]);
1165 result.checkFieldHasType('A', 'witness1', [result.string, result.nullType]);
1166 result.checkFieldHasType('A', 'witness2', [result.string, result.nullType]);
1167 result.checkFieldHasType('A', 'witness3', [result.string, result.nullType]);
1168 result.checkFieldHasType('A', 'witness4', [result.string, result.nullType]);
1169 });
1170 }
1171
1172 testInequality() {
1173 final String source = r"""
1174 class A {
1175 var witness;
1176 operator ==(x) { witness = "foo"; return "abc"; }
1177 }
1178 class B {
1179 operator ==(x) { throw "error"; }
1180 }
1181 main() {
1182 var foo = 1 != 2;
1183 var bar = (new A() != 2);
1184 var baz = (new B() != 2);
1185 foo; bar; baz;
1186 }
1187 """;
1188 return analyze(source).then((result) {
1189 result.checkNodeHasType('foo', [result.bool]);
1190 result.checkNodeHasType('bar', [result.bool]);
1191 // TODO(polux): could be even better: empty
1192 result.checkNodeHasType('baz', [result.bool]);
1193 result.checkFieldHasType('A', 'witness', [result.string, result.nullType]);
1194 });
1195 }
1196
1197 testFieldInitialization1() {
1198 final String source = r"""
1199 class A {
1200 var x;
1201 var y = 1;
1202 }
1203 class B extends A {
1204 var z = "foo";
1205 }
1206 main () {
1207 // we need to access y and z once to trigger their analysis
1208 new B().y;
1209 new B().z;
1210 }
1211 """;
1212 return analyze(source).then((result) {
1213 result.checkFieldHasType('A', 'x', [result.nullType]);
1214 result.checkFieldHasType('A', 'y', [result.int]);
1215 result.checkFieldHasType('B', 'z', [result.string]);
1216 });
1217 }
1218
1219 testFieldInitialization2() {
1220 final String source = r"""
1221 var top = 42;
1222 class A {
1223 var x = top;
1224 }
1225 main () {
1226 // we need to access X once to trigger its analysis
1227 new A().x;
1228 }
1229 """;
1230 return analyze(source).then((result) {
1231 result.checkFieldHasType('A', 'x', [result.int]);
1232 });
1233 }
1234
1235 testFieldInitialization3() {
1236 final String source = r"""
1237 class A {
1238 var x;
1239 }
1240 f() => new A().x;
1241 class B {
1242 var x = new A().x;
1243 var y = f();
1244 }
1245 main () {
1246 var foo = new B().x;
1247 var bar = new B().y;
1248 new A().x = "a";
1249 foo; bar;
1250 }
1251 """;
1252 return analyze(source).then((result) {
1253 // checks that B.B is set as a reader of A.x
1254 result.checkFieldHasType('B', 'x', [result.nullType, result.string]);
1255 // checks that B.B is set as a caller of f
1256 result.checkFieldHasType('B', 'y', [result.nullType, result.string]);
1257 // checks that readers of x are notified by changes in x's type
1258 result.checkNodeHasType('foo', [result.nullType, result.string]);
1259 // checks that readers of y are notified by changes in y's type
1260 result.checkNodeHasType('bar', [result.nullType, result.string]);
1261 });
1262 }
1263
1264 testLists() {
1265 final String source = """
1266 class A {}
1267 class B {}
1268 class C {}
1269 class D {}
1270 class E {}
1271 class F {}
1272 class G {}
1273
1274 main() {
1275 var l1 = [new A()];
1276 var l2 = [];
1277 l1['a'] = new B(); // raises an error, so B should not be recorded
1278 l1[1] = new C();
1279 l1.add(new D());
1280 l1.insert('a', new E()); // raises an error, so E should not be recorded
1281 l1.insert(1, new F());
1282 $DYNAMIC[1] = new G();
1283 var x1 = l1[1];
1284 var x2 = l2[1];
1285 var x3 = l1['foo']; // raises an error, should return empty
1286 var x4 = l1.removeAt(1);
1287 var x5 = l2.removeAt(1);
1288 var x6 = l1.removeAt('a'); // raises an error, should return empty
1289 var x7 = l1.removeLast();
1290 var x8 = l2.removeLast();
1291 x1; x2; x3; x4; x5; x6; x7; x8;
1292 }""";
1293 return analyze(source).then((result) {
1294 final expectedTypes = ['A', 'C', 'D', 'F', 'G'].map(result.base).toList();
1295 result.checkNodeHasType('x1', expectedTypes);
1296 result.checkNodeHasType('x2', expectedTypes);
1297 result.checkNodeHasType('x3', []);
1298 result.checkNodeHasType('x4', expectedTypes);
1299 result.checkNodeHasType('x5', expectedTypes);
1300 result.checkNodeHasType('x6', []);
1301 result.checkNodeHasType('x7', expectedTypes);
1302 result.checkNodeHasType('x8', expectedTypes);
1303 });
1304 }
1305
1306 testListWithCapacity() {
1307 final String source = r"""
1308 main() {
1309 var l = new List(10);
1310 var x = [][0];
1311 x;
1312 }""";
1313 return analyze(source).then((result) {
1314 result.checkNodeHasType('x', [result.nullType]);
1315 });
1316 }
1317
1318 testEmptyList() {
1319 final String source = r"""
1320 main() {
1321 var l = new List();
1322 var x = l[0];
1323 x;
1324 }""";
1325 return analyze(source).then((result) {
1326 result.checkNodeHasType('x', []);
1327 });
1328 }
1329
1330 testSendWithWrongArity() {
1331 final String source = r"""
1332 f(x) { }
1333 class A { g(x) { } }
1334 main () {
1335 var x = f();
1336 var y = f(1, 2);
1337 var z = new A().g();
1338 var w = new A().g(1, 2);
1339 x; y; z; w;
1340 }
1341 """;
1342 return analyze(source).then((result) {
1343 // TODO(polux): It would be better if x and y also had the empty type. This
1344 // requires a change in SimpleTypeInferrerVisitor.visitStaticSend which
1345 // would impact the default type inference and possibly break dart2js.
1346 // Keeping this change for a later CL.
1347 result.checkNodeHasUnknownType('x');
1348 result.checkNodeHasUnknownType('y');
1349 result.checkNodeHasType('z', []);
1350 result.checkNodeHasType('w', []);
1351 });
1352 }
1353
1354 testBigTypesWidening1() {
1355 final String source = r"""
1356 small() => true ? 1 : 'abc';
1357 big() => true ? 1 : (true ? 'abc' : false);
1358 main () {
1359 var x = small();
1360 var y = big();
1361 x; y;
1362 }
1363 """;
1364 return analyze(source, maxConcreteTypeSize: 2).then((result) {
1365 result.checkNodeHasType('x', [result.int, result.string]);
1366 result.checkNodeHasUnknownType('y');
1367 });
1368 }
1369
1370 testBigTypesWidening2() {
1371 final String source = r"""
1372 class A {
1373 var x, y;
1374 A(this.x, this.y);
1375 }
1376 main () {
1377 var a = new A(1, 1);
1378 a.x = 'abc';
1379 a.y = 'abc';
1380 a.y = true;
1381 }
1382 """;
1383 return analyze(source, maxConcreteTypeSize: 2).then((result) {
1384 result.checkFieldHasType('A', 'x', [result.int, result.string]);
1385 result.checkFieldHasUknownType('A', 'y');
1386 });
1387 }
1388
1389 testDynamicIsAbsorbing() {
1390 final String source = """
1391 main () {
1392 var x = 1;
1393 if (true) {
1394 x = $DYNAMIC;
1395 } else {
1396 x = 42;
1397 }
1398 x;
1399 }
1400 """;
1401 return analyze(source).then((result) {
1402 result.checkNodeHasUnknownType('x');
1403 });
1404 }
1405
1406 testJsCall() {
1407 final String source = r"""
1408 import 'dart:_foreign_helper';
1409 import 'dart:_interceptors';
1410
1411 abstract class AbstractA {}
1412 class A extends AbstractA {}
1413 class B extends A {}
1414 class BB extends B {}
1415 class C extends A {}
1416 class D implements A {}
1417 class E extends A {}
1418
1419 class X {}
1420
1421 main () {
1422 // we don't create any E on purpose
1423 new B(); new BB(); new C(); new D();
1424
1425 var a = JS('', '1');
1426 var b = JS('Object', '1');
1427 var c = JS('JSExtendableArray', '1');
1428 var cNull = JS('JSExtendableArray|Null', '1');
1429 var d = JS('String', '1');
1430 var dNull = JS('String|Null', '1');
1431 var e = JS('int', '1');
1432 var eNull = JS('int|Null', '1');
1433 var f = JS('double', '1');
1434 var fNull = JS('double|Null', '1');
1435 var g = JS('num', '1');
1436 var gNull = JS('num|Null', '1');
1437 var h = JS('bool', '1');
1438 var hNull = JS('bool|Null', '1');
1439 var i = JS('AbstractA', '1');
1440 var iNull = JS('AbstractA|Null', '1');
1441
1442 a; b; c; cNull; d; dNull; e; eNull; f; fNull; g; gNull; h; hNull; i;
1443 iNull;
1444 }
1445 """;
1446 return analyze(source, maxConcreteTypeSize: 6).then((result) {
1447 List maybe(List types) => new List.from(types)..add(result.nullType);
1448 // a and b have all the types seen by the resolver, which are more than 6
1449 result.checkNodeHasUnknownType('a');
1450 result.checkNodeHasUnknownType('b');
1451 final expectedCType = [result.growableList];
1452 result.checkNodeHasType('c', expectedCType);
1453 result.checkNodeHasType('cNull', maybe(expectedCType));
1454 final expectedDType = [result.string];
1455 result.checkNodeHasType('d', expectedDType);
1456 result.checkNodeHasType('dNull', maybe(expectedDType));
1457 final expectedEType = [result.int];
1458 result.checkNodeHasType('e', expectedEType);
1459 result.checkNodeHasType('eNull', maybe(expectedEType));
1460 final expectedFType = [result.num];
1461 result.checkNodeHasType('f', expectedFType);
1462 result.checkNodeHasType('fNull', maybe(expectedFType));
1463 final expectedGType = [result.num];
1464 result.checkNodeHasType('g', expectedGType);
1465 result.checkNodeHasType('gNull', maybe(expectedGType));
1466 final expectedType = [result.bool];
1467 result.checkNodeHasType('h', expectedType);
1468 result.checkNodeHasType('hNull', maybe(expectedType));
1469 final expectedIType = [result.base('B'),
1470 result.base('BB'),
1471 result.base('C'),
1472 result.base('D')];
1473 result.checkNodeHasType('i', expectedIType);
1474 result.checkNodeHasType('iNull', maybe(expectedIType));
1475 });
1476 }
1477
1478 testJsCallAugmentsSeenClasses() {
1479 final String source1 = """
1480 main () {
1481 var x = $DYNAMIC.truncate();
1482 x;
1483 }
1484 """;
1485 return analyze(source1).then((AnalysisResult result) {
1486 result.checkNodeHasType('x', []);
1487 }).whenComplete(() {
1488
1489 final String source2 = """
1490 import 'dart:_foreign_helper';
1491
1492 main () {
1493 var x = $DYNAMIC.truncate();
1494 JS('double', 'foo');
1495 x;
1496 }
1497 """;
1498 return analyze(source2).then((AnalysisResult result) {
1499 result.checkNodeHasType('x', [result.int]);
1500 });
1501 });
1502 }
1503
1504 testIsCheck() {
1505 final String source = r"""
1506 main () {
1507 var x = (1 is String);
1508 x;
1509 }
1510 """;
1511 return analyze(source).then((result) {
1512 result.checkNodeHasType('x', [result.bool]);
1513 });
1514 }
1515
1516 testSeenClasses() {
1517 final String source = """
1518 class A {
1519 witness() => 42;
1520 }
1521 class B {
1522 witness() => "string";
1523 }
1524 class AFactory {
1525 onlyCalledInAFactory() => new A();
1526 }
1527 class BFactory {
1528 onlyCalledInAFactory() => new B();
1529 }
1530
1531 main() {
1532 new AFactory().onlyCalledInAFactory();
1533 new BFactory();
1534 // should be of type {int} and not {int, String} since B is unreachable
1535 var foo = $DYNAMIC.witness();
1536 foo;
1537 }
1538 """;
1539 return analyze(source).then((result) {
1540 result.checkNodeHasType('foo', [result.int]);
1541 });
1542 }
1543
1544 testIntDoubleNum() {
1545 final String source = r"""
1546 main() {
1547 var a = 1;
1548 var b = 1.1;
1549 var c = true ? 1 : 1.1;
1550 a; b; c;
1551 }
1552 """;
1553 return analyze(source).then((result) {
1554 result.checkNodeHasType('a', [result.int]);
1555 result.checkNodeHasType('b', [result.double]);
1556 result.checkNodeHasType('c', [result.num]);
1557 });
1558 }
1559
1560 testConcreteTypeToTypeMask() {
1561 final String source = r"""
1562 class A {}
1563 class B extends A {}
1564 class C extends A {}
1565 class D implements A {}
1566 main() {
1567 new A();
1568 new B();
1569 new C();
1570 new D();
1571 }
1572 """;
1573 return analyze(source).then((result) {
1574
1575 convert(ConcreteType type) {
1576 return result.compiler.typesTask.concreteTypesInferrer
1577 .types.concreteTypeToTypeMask(type);
1578 }
1579
1580 final nullSingleton =
1581 result.compiler.typesTask.concreteTypesInferrer.singletonConcreteType(
1582 new NullBaseType());
1583
1584 singleton(ClassElement element) {
1585 return result.compiler.typesTask.concreteTypesInferrer
1586 .singletonConcreteType(new ClassBaseType(element));
1587 }
1588
1589 var world = result.compiler.world;
1590
1591 ClassElement a = findElement(result.compiler, 'A');
1592 ClassElement b = findElement(result.compiler, 'B');
1593 ClassElement c = findElement(result.compiler, 'C');
1594 ClassElement d = findElement(result.compiler, 'D');
1595
1596 for (ClassElement cls in [a, b, c, d]) {
1597 Expect.equals(convert(singleton(cls)),
1598 new TypeMask.nonNullExact(cls, world));
1599 }
1600
1601 for (ClassElement cls in [a, b, c, d]) {
1602 Expect.equals(convert(singleton(cls).union(nullSingleton)),
1603 new TypeMask.exact(cls, world));
1604 }
1605
1606 Expect.equals(convert(singleton(a).union(singleton(b))),
1607 new TypeMask.nonNullSubclass(a, world));
1608
1609 Expect.equals(
1610 convert(singleton(a).union(singleton(b)).union(nullSingleton)),
1611 new TypeMask.subclass(a, world));
1612
1613 Expect.equals(
1614 simplify(convert(singleton(b).union(singleton(d))), result.compiler),
1615 new TypeMask.nonNullSubtype(a, world));
1616 });
1617 }
1618
1619 testSelectors() {
1620 final String source = r"""
1621 // ABC <--- A
1622 // `- BC <--- B
1623 // `- C
1624
1625 class ABC {}
1626 class A extends ABC {}
1627 class BC extends ABC {}
1628 class B extends BC {}
1629 class C extends BC {}
1630
1631 class XY {}
1632 class X extends XY { foo() => new B(); }
1633 class Y extends XY { foo() => new C(); }
1634 class Z { foo() => new A(); }
1635
1636 main() {
1637 new X().foo();
1638 new Y().foo();
1639 new Z().foo();
1640 }
1641 """;
1642 return analyze(source).then((result) {
1643
1644 var world = result.compiler.world;
1645
1646 ClassElement a = findElement(result.compiler, 'A');
1647 ClassElement b = findElement(result.compiler, 'B');
1648 ClassElement c = findElement(result.compiler, 'C');
1649 ClassElement xy = findElement(result.compiler, 'XY');
1650 ClassElement x = findElement(result.compiler, 'X');
1651 ClassElement y = findElement(result.compiler, 'Y');
1652 ClassElement z = findElement(result.compiler, 'Z');
1653
1654 Selector foo =
1655 new Selector.call(const PublicName("foo"), CallStructure.NO_ARGS);
1656
1657 result.checkSelectorHasType(
1658 foo,
1659 null,
1660 new TypeMask.unionOf([a, b, c]
1661 .map((cls) => new TypeMask.nonNullExact(cls, world)),
1662 result.compiler.world));
1663 result.checkSelectorHasType(
1664 foo,
1665 new TypeMask.subclass(x, world),
1666 new TypeMask.nonNullExact(b, world));
1667 result.checkSelectorHasType(
1668 foo,
1669 new TypeMask.subclass(y, world),
1670 new TypeMask.nonNullExact(c, world));
1671 result.checkSelectorHasType(
1672 foo,
1673 new TypeMask.subclass(z, world),
1674 new TypeMask.nonNullExact(a, world));
1675 result.checkSelectorHasType(
1676 foo,
1677 new TypeMask.subclass(xy, world),
1678 new TypeMask.unionOf([b, c].map((cls) =>
1679 new TypeMask.nonNullExact(cls, world)), world));
1680
1681 result.checkSelectorHasType(
1682 new Selector.call(const PublicName("bar"), CallStructure.NO_ARGS),
1683 null, null);
1684 });
1685 }
1686
1687 testEqualsNullSelector() {
1688 final String source = r"""
1689 main() {
1690 1 == null;
1691 }
1692 """;
1693 return analyze(source).then((result) {
1694 ClassElement bool = result.compiler.backend.boolImplementation;
1695 result.checkSelectorHasType(new Selector.binaryOperator('=='),
1696 null,
1697 new TypeMask.nonNullExact(bool,
1698 result.compiler.world));
1699 });
1700 }
1701
1702 testMixins() {
1703 final String source = r"""
1704 class A {
1705 foo() => "abc";
1706 get x => 42;
1707 }
1708 class B extends Object with A {
1709 bar() => foo();
1710 baz() => x;
1711 }
1712 main() {
1713 var b = new B();
1714 var x = b.foo();
1715 var y = b.bar();
1716 var z = b.x;
1717 var w = b.baz();
1718 x; y; z; w;
1719 }
1720 """;
1721 return analyze(source).then((result) {
1722 result.checkNodeHasType('x', [result.string]);
1723 result.checkNodeHasType('y', [result.string]);
1724 result.checkNodeHasType('z', [result.int]);
1725 result.checkNodeHasType('w', [result.int]);
1726 });
1727 }
1728
1729 testClosures1() {
1730 final String source = r"""
1731 class A {
1732 final foo = 42;
1733 }
1734 class B {
1735 final foo = "abc";
1736 }
1737 class C {
1738 final foo = true;
1739 }
1740 main() {
1741 var a;
1742 var f = (x) {
1743 a = x.foo;
1744 };
1745 // We make sure that x doesn't have type dynamic by adding C to the
1746 // set of seen classes and by checking that a's type doesn't contain
1747 // bool.
1748 new C();
1749 f(new A());
1750 f(new B());
1751 a;
1752 }
1753 """;
1754 return analyze(source).then((AnalysisResult result) {
1755 result.checkNodeHasType('a', [result.nullType, result.int, result.string]);
1756 });
1757 }
1758
1759 testClosures2() {
1760 final String source = r"""
1761 class A {
1762 final foo = 42;
1763 }
1764 class B {
1765 final foo = "abc";
1766 }
1767 class C {
1768 final foo = true;
1769 }
1770 main() {
1771 // We make sure that x doesn't have type dynamic by adding C to the
1772 // set of seen classes and by checking that a's type doesn't contain
1773 // bool.
1774 new C();
1775
1776 var a;
1777 f(x) {
1778 a = x.foo;
1779 }
1780 f(new A());
1781 f(new B());
1782 a; f;
1783 }
1784 """;
1785 return analyze(source).then((AnalysisResult result) {
1786 result.checkNodeHasType('a', [result.nullType, result.int, result.string]);
1787 result.checkNodeHasType('f', [result.functionType]);
1788 });
1789 }
1790
1791 testClosures3() {
1792 final String source = r"""
1793 class A {
1794 var g;
1795 A(this.g);
1796 }
1797 main() {
1798 var foo = new A((x) => x).g(42);
1799 foo;
1800 }
1801 """;
1802 return analyze(source).then((result) {
1803 result.checkNodeHasType('foo', [result.int]);
1804 });
1805 }
1806
1807 testClosures4() {
1808 final String source = """
1809 class A {
1810 var f = $DYNAMIC;
1811 }
1812 main() {
1813 var f = (x) => x;
1814 var g = (x) => "a";
1815 var h = (x, y) => true;
1816
1817 var foo = $DYNAMIC(42);
1818 var bar = new A().f(1.2);
1819 var baz = $DYNAMIC.f(null);
1820
1821 foo; bar; baz;
1822 }
1823 """;
1824 return analyze(source).then((result) {
1825 result.checkNodeHasType('foo', [result.int, result.string]);
1826 result.checkNodeHasType('bar', [result.double, result.string]);
1827 result.checkNodeHasType('baz', [result.nullType, result.string]);
1828 });
1829 }
1830
1831 testClosures5() {
1832 final String source = r"""
1833 f(x) => x;
1834 class A {
1835 var g;
1836 A(this.g);
1837 }
1838 main() {
1839 var foo = new A(f).g(42);
1840 foo;
1841 }
1842 """;
1843 return analyze(source).then((result) {
1844 result.checkNodeHasType('foo', [result.int]);
1845 });
1846 }
1847
1848 testClosures6() {
1849 final String source = r"""
1850 class A {
1851 var g;
1852 A(this.g);
1853 }
1854 class B {
1855 f(x) => x;
1856 }
1857 main() {
1858 var foo = new A(new B().f).g(42);
1859 foo;
1860 }
1861 """;
1862 return analyze(source).then((result) {
1863 result.checkNodeHasType('foo', [result.int]);
1864 });
1865 }
1866
1867 testClosures7() {
1868 final String source = r"""
1869 class A {
1870 final x = 42;
1871 f() => () => x;
1872 }
1873 main() {
1874 var foo = new A().f()();
1875 foo;
1876 }
1877 """;
1878 return analyze(source).then((result) {
1879 result.checkNodeHasType('foo', [result.int]);
1880 });
1881 }
1882
1883 testClosures8() {
1884 final String source = r"""
1885 class A {
1886 final x = 42;
1887 f() => () => x;
1888 }
1889 class B extends A {
1890 get x => "a";
1891 }
1892 main() {
1893 var foo = new B().f()();
1894 foo;
1895 }
1896 """;
1897 return analyze(source).then((result) {
1898 result.checkNodeHasType('foo', [result.string]);
1899 });
1900 }
1901
1902 testClosures9() {
1903 final String source = r"""
1904 class A {
1905 g() => 42;
1906 f() => () => g();
1907 }
1908 class B extends A {
1909 g() => "a";
1910 }
1911 main() {
1912 var foo = new B().f()();
1913 foo;
1914 }
1915 """;
1916 return analyze(source).then((result) {
1917 result.checkNodeHasType('foo', [result.string]);
1918 });
1919 }
1920
1921 testClosures10() {
1922 final String source = r"""
1923 class A {
1924 f() => 42;
1925 }
1926 main() {
1927 var a = new A();
1928 g() => a.f();
1929 var foo = g();
1930 foo; a;
1931 }
1932 """;
1933 return analyze(source).then((result) {
1934 result.checkNodeHasType('foo', [result.int]);
1935 });
1936 }
1937
1938 testClosures11() {
1939 final String source = r"""
1940 class A {
1941 var x;
1942 f() => x;
1943 }
1944 main() {
1945 var a = new A();
1946 f() => a.f();
1947 a.x = 42;
1948 var foo = f();
1949 foo;
1950 }
1951 """;
1952 return analyze(source).then((result) {
1953 result.checkNodeHasType('foo', [result.nullType, result.int]);
1954 });
1955 }
1956
1957 testClosures12() {
1958 final String source = r"""
1959 var f = (x) => x;
1960 main() {
1961 var foo = f(1);
1962 foo;
1963 }
1964 """;
1965 return analyze(source).then((result) {
1966 result.checkNodeHasType('foo', [result.int]);
1967 });
1968 }
1969
1970 testRefinement() {
1971 final String source = """
1972 class A {
1973 f() => null;
1974 g() => 42;
1975 }
1976 class B {
1977 g() => "aa";
1978 }
1979 main() {
1980 var x = $DYNAMIC ? new A() : new B();
1981 x.f();
1982 var foo = x.g();
1983 foo;
1984 }
1985 """;
1986 return analyze(source).then((result) {
1987 result.checkNodeHasType('foo', [result.int]);
1988 });
1989 }
1990
1991 testDefaultArguments() {
1992 final String source = r"""
1993 f1([x = 42]) => x;
1994 g1([x]) => x;
1995
1996 f2({x: 42}) => x;
1997 g2({x}) => x;
1998
1999 main() {
2000 var xf1 = f1();
2001 var xg1 = g1();
2002 var xf2 = f2();
2003 var xg2 = g2();
2004 xf1; xg1; xf2; xg2;
2005 }
2006 """;
2007 return analyze(source).then((result) {
2008 result.checkNodeHasType('xf1', [result.int]);
2009 result.checkNodeHasType('xg1', [result.nullType]);
2010 result.checkNodeHasType('xf2', [result.int]);
2011 result.checkNodeHasType('xg2', [result.nullType]);
2012 });
2013 }
2014
2015 testSuperConstructorCall() {
2016 final String source = r"""
2017 class A {
2018 final x;
2019 A(this.x);
2020 }
2021
2022 class B extends A {
2023 B(x) : super(x);
2024 }
2025 main() {
2026 var b = new B(42);
2027 var foo = b.x;
2028 foo;
2029 }
2030 """;
2031 return analyze(source).then((result) {
2032 result.checkFieldHasType('A', 'x', [result.int]);
2033 result.checkNodeHasType('foo', [result.int]);
2034 });
2035 }
2036
2037 testSuperConstructorCall2() {
2038 final String source = r"""
2039 class A {
2040 var x;
2041 A() {
2042 x = 42;
2043 }
2044 }
2045 class B extends A {
2046 }
2047 main() {
2048 new B();
2049 }
2050 """;
2051 return analyze(source).then((result) {
2052 result.checkFieldHasType('A', 'x', [result.int]);
2053 });
2054 }
2055
2056 testSuperConstructorCall3() {
2057 final String source = r"""
2058 class A {
2059 var x;
2060 A() {
2061 x = 42;
2062 }
2063 }
2064 class B extends A {
2065 B(unused) {}
2066 }
2067 main() {
2068 new B("abc");
2069 }
2070 """;
2071 return analyze(source).then((result) {
2072 result.checkFieldHasType('A', 'x', [result.int]);
2073 });
2074 }
2075
2076 void main() {
2077 asyncTest(() => Future.forEach([
2078 testDynamicBackDoor,
2079 testVariableDeclaration,
2080 testLiterals,
2081 testRedefinition,
2082 testIfThenElse,
2083 testTernaryIf,
2084 testWhile,
2085 testDoWhile,
2086 testFor1,
2087 testFor2,
2088 testFor3,
2089 testForIn,
2090 testToplevelVariable,
2091 testToplevelVariable2,
2092 testToplevelVariable3,
2093 testNonRecusiveFunction,
2094 testMultipleReturns,
2095 testRecusiveFunction,
2096 testMutuallyRecusiveFunction,
2097 testSimpleSend,
2098 testSendToThis1,
2099 testSendToThis2,
2100 testSendToThis3,
2101 testSendToThis4,
2102 testConstructor,
2103 testGetters,
2104 testToplevelGetters,
2105 testDynamicGetters,
2106 testSetters,
2107 testToplevelSetters,
2108 testOptionalNamedParameters,
2109 testOptionalPositionalParameters,
2110 testListLiterals,
2111 testMapLiterals,
2112 testReturn,
2113 testNoReturn,
2114 testArithmeticOperators,
2115 testBooleanOperators,
2116 testBooleanOperatorsShortCirtcuit,
2117 testOperators,
2118 testCompoundOperators1,
2119 testCompoundOperators2,
2120 testSetIndexOperator,
2121 testInequality,
2122 testFieldInitialization1,
2123 testFieldInitialization2,
2124 testFieldInitialization3,
2125 testSendWithWrongArity,
2126 testBigTypesWidening1,
2127 testBigTypesWidening2,
2128 testDynamicIsAbsorbing,
2129 testLists,
2130 testListWithCapacity,
2131 testEmptyList,
2132 testJsCall,
2133 testJsCallAugmentsSeenClasses,
2134 testIsCheck,
2135 testSeenClasses,
2136 testIntDoubleNum,
2137 testConcreteTypeToTypeMask,
2138 testSelectors,
2139 // TODO(polux): this test is failing, see http://dartbug.com/16825.
2140 //testEqualsNullSelector,
2141 testMixins,
2142 testClosures1,
2143 testClosures2,
2144 testClosures3,
2145 testClosures4,
2146 testClosures5,
2147 testClosures6,
2148 testClosures7,
2149 testClosures8,
2150 testClosures9,
2151 testClosures10,
2152 testClosures11,
2153 testClosures12,
2154 testRefinement,
2155 testDefaultArguments,
2156 testSuperConstructorCall,
2157 testSuperConstructorCall2,
2158 testSuperConstructorCall3,
2159 ], (f) => f()));
2160 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/use_unused_api.dart ('k') | tests/compiler/dart2js/mock_compiler.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698