| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 import "dart:uri"; | 5 import "dart:uri"; |
| 6 import "../../../sdk/lib/_internal/compiler/implementation/elements/elements.dar
t"; | 6 import "../../../sdk/lib/_internal/compiler/implementation/elements/elements.dar
t"; |
| 7 import '../../../sdk/lib/_internal/compiler/implementation/scanner/scannerlib.da
rt'; | 7 import '../../../sdk/lib/_internal/compiler/implementation/scanner/scannerlib.da
rt'; |
| 8 import '../../../sdk/lib/_internal/compiler/implementation/source_file.dart'; | 8 import '../../../sdk/lib/_internal/compiler/implementation/source_file.dart'; |
| 9 import '../../../sdk/lib/_internal/compiler/implementation/types/types.dart'; | 9 import '../../../sdk/lib/_internal/compiler/implementation/types/types.dart'; |
| 10 import '../../../sdk/lib/_internal/compiler/implementation/tree/tree.dart'; | 10 import '../../../sdk/lib/_internal/compiler/implementation/tree/tree.dart'; |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 * occurence of [: variable; :] in the program is the concrete type | 104 * occurence of [: variable; :] in the program is the concrete type |
| 105 * made of [baseTypes]. | 105 * made of [baseTypes]. |
| 106 */ | 106 */ |
| 107 void checkNodeHasType(String variable, List<BaseType> baseTypes) { | 107 void checkNodeHasType(String variable, List<BaseType> baseTypes) { |
| 108 return Expect.equals( | 108 return Expect.equals( |
| 109 concreteFrom(baseTypes), | 109 concreteFrom(baseTypes), |
| 110 inferrer.inferredTypes[findNode(variable)]); | 110 inferrer.inferredTypes[findNode(variable)]); |
| 111 } | 111 } |
| 112 | 112 |
| 113 /** | 113 /** |
| 114 * Checks that the inferred type of the node corresponding to the last |
| 115 * occurence of [: variable; :] in the program is the unknown concrete type. |
| 116 */ |
| 117 void checkNodeHasUnknownType(String variable) { |
| 118 return Expect.isTrue(inferrer.inferredTypes[findNode(variable)].isUnkown()); |
| 119 } |
| 120 |
| 121 /** |
| 114 * Checks that [: className#fieldName :]'s inferred type is the concrete type | 122 * Checks that [: className#fieldName :]'s inferred type is the concrete type |
| 115 * made of [baseTypes]. | 123 * made of [baseTypes]. |
| 116 */ | 124 */ |
| 117 void checkFieldHasType(String className, String fieldName, | 125 void checkFieldHasType(String className, String fieldName, |
| 118 List<BaseType> baseTypes) { | 126 List<BaseType> baseTypes) { |
| 119 return Expect.equals( | 127 return Expect.equals( |
| 120 concreteFrom(baseTypes), | 128 concreteFrom(baseTypes), |
| 121 inferrer.inferredFieldTypes[findField(className, fieldName)]); | 129 inferrer.inferredFieldTypes[findField(className, fieldName)]); |
| 122 } | 130 } |
| 131 |
| 132 /** |
| 133 * Checks that [: className#fieldName :]'s inferred type is the unknown |
| 134 * concrete type. |
| 135 */ |
| 136 void checkFieldHasUknownType(String className, String fieldName) { |
| 137 return Expect.isTrue( |
| 138 inferrer.inferredFieldTypes[findField(className, fieldName)] |
| 139 .isUnkown()); |
| 140 } |
| 123 } | 141 } |
| 124 | 142 |
| 125 const String CORELIB = r''' | 143 const String CORELIB = r''' |
| 126 print(var obj) {} | 144 print(var obj) {} |
| 127 abstract class num { operator +(x); operator *(x); operator -(x); } | 145 abstract class num { operator +(x); operator *(x); operator -(x); } |
| 128 abstract class int extends num { } | 146 abstract class int extends num { } |
| 129 abstract class double extends num { } | 147 abstract class double extends num { } |
| 130 class bool {} | 148 class bool {} |
| 131 class String {} | 149 class String {} |
| 132 class Object {} | 150 class Object {} |
| 133 class Function {} | 151 class Function {} |
| 134 abstract class List {} | 152 abstract class List {} |
| 135 abstract class Map {} | 153 abstract class Map {} |
| 136 class Closure {} | 154 class Closure {} |
| 137 class Null {} | 155 class Null {} |
| 138 class Type {} | 156 class Type {} |
| 139 class Dynamic_ {} | 157 class Dynamic_ {} |
| 140 bool identical(Object a, Object b) {}'''; | 158 bool identical(Object a, Object b) {}'''; |
| 141 | 159 |
| 142 AnalysisResult analyze(String code) { | 160 AnalysisResult analyze(String code) { |
| 143 Uri uri = new Uri.fromComponents(scheme: 'source'); | 161 Uri uri = new Uri.fromComponents(scheme: 'source'); |
| 144 MockCompiler compiler = new MockCompiler(coreSource: CORELIB, | 162 MockCompiler compiler = new MockCompiler(coreSource: CORELIB, |
| 145 enableConcreteTypeInference: true); | 163 enableConcreteTypeInference: true); |
| 146 compiler.sourceFiles[uri.toString()] = new SourceFile(uri.toString(), code); | 164 compiler.sourceFiles[uri.toString()] = new SourceFile(uri.toString(), code); |
| 165 compiler.typesTask.concreteTypesInferrer.testMode = true; |
| 147 compiler.runCompiler(uri); | 166 compiler.runCompiler(uri); |
| 148 return new AnalysisResult(compiler); | 167 return new AnalysisResult(compiler); |
| 149 } | 168 } |
| 150 | 169 |
| 170 testDynamicBackDoor() { |
| 171 final String source = r""" |
| 172 main () { |
| 173 var x = "__dynamic_for_test"; |
| 174 x; |
| 175 } |
| 176 """; |
| 177 AnalysisResult result = analyze(source); |
| 178 result.checkNodeHasUnknownType('x'); |
| 179 } |
| 180 |
| 151 testLiterals() { | 181 testLiterals() { |
| 152 final String source = r""" | 182 final String source = r""" |
| 153 main() { | 183 main() { |
| 154 var v1 = 42; | 184 var v1 = 42; |
| 155 var v2 = 42.0; | 185 var v2 = 42.0; |
| 156 var v3 = 'abc'; | 186 var v3 = 'abc'; |
| 157 var v4 = true; | 187 var v4 = true; |
| 158 var v5 = null; | 188 var v5 = null; |
| 159 v1; v2; v3; v4; v5; | 189 v1; v2; v3; v4; v5; |
| 160 } | 190 } |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 260 } | 290 } |
| 261 foo; bar; | 291 foo; bar; |
| 262 } | 292 } |
| 263 """; | 293 """; |
| 264 AnalysisResult result = analyze(source); | 294 AnalysisResult result = analyze(source); |
| 265 result.checkNodeHasType('foo', [result.base('A'), result.base('B')]); | 295 result.checkNodeHasType('foo', [result.base('A'), result.base('B')]); |
| 266 // Check that the condition is evaluated. | 296 // Check that the condition is evaluated. |
| 267 result.checkNodeHasType('bar', [result.int]); | 297 result.checkNodeHasType('bar', [result.int]); |
| 268 } | 298 } |
| 269 | 299 |
| 300 testToplevelVariable() { |
| 301 final String source = r""" |
| 302 final top = 'abc'; |
| 303 main() { var foo = top; foo; } |
| 304 """; |
| 305 AnalysisResult result = analyze(source); |
| 306 result.checkNodeHasType('foo', [result.string]); |
| 307 } |
| 308 |
| 270 testNonRecusiveFunction() { | 309 testNonRecusiveFunction() { |
| 271 final String source = r""" | 310 final String source = r""" |
| 272 f(x, y) => true ? x : y; | 311 f(x, y) => true ? x : y; |
| 273 main() { var foo = f(42, "abc"); foo; } | 312 main() { var foo = f(42, "abc"); foo; } |
| 274 """; | 313 """; |
| 275 AnalysisResult result = analyze(source); | 314 AnalysisResult result = analyze(source); |
| 276 result.checkNodeHasType('foo', [result.int, result.string]); | 315 result.checkNodeHasType('foo', [result.int, result.string]); |
| 277 } | 316 } |
| 278 | 317 |
| 279 testRecusiveFunction() { | 318 testRecusiveFunction() { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 291 testMutuallyRecusiveFunction() { | 330 testMutuallyRecusiveFunction() { |
| 292 final String source = r""" | 331 final String source = r""" |
| 293 f() => true ? 42 : g(); | 332 f() => true ? 42 : g(); |
| 294 g() => true ? "abc" : f(); | 333 g() => true ? "abc" : f(); |
| 295 main() { var foo = f(); foo; } | 334 main() { var foo = f(); foo; } |
| 296 """; | 335 """; |
| 297 AnalysisResult result = analyze(source); | 336 AnalysisResult result = analyze(source); |
| 298 result.checkNodeHasType('foo', [result.int, result.string]); | 337 result.checkNodeHasType('foo', [result.int, result.string]); |
| 299 } | 338 } |
| 300 | 339 |
| 340 testSimpleSend() { |
| 341 final String source = r""" |
| 342 class A { |
| 343 f(x) => x; |
| 344 } |
| 345 class B { |
| 346 f(x) => 'abc'; |
| 347 } |
| 348 class C { |
| 349 f(x) => 3.14; |
| 350 } |
| 351 class D { |
| 352 var f; // we check that this field is ignored in calls to dynamic.f() |
| 353 D(this.f); |
| 354 } |
| 355 main() { |
| 356 new B(); new D(42); // we instantiate B and D but not C |
| 357 var foo = new A().f(42); |
| 358 var bar = "__dynamic_for_test".f(42); |
| 359 foo; bar; |
| 360 } |
| 361 """; |
| 362 AnalysisResult result = analyze(source); |
| 363 result.checkNodeHasType('foo', [result.int]); |
| 364 result.checkNodeHasType('bar', [result.int, result.string]); |
| 365 } |
| 366 |
| 367 testSendToClosureField() { |
| 368 final String source = r""" |
| 369 f(x) => x; |
| 370 class A { |
| 371 var g; |
| 372 A(this.g); |
| 373 } |
| 374 main() { |
| 375 var foo = new A(f).g(42); |
| 376 foo; |
| 377 } |
| 378 """; |
| 379 AnalysisResult result = analyze(source); |
| 380 result.checkNodeHasType('foo', [result.int]); |
| 381 } |
| 382 |
| 301 testSendToThis1() { | 383 testSendToThis1() { |
| 302 final String source = r""" | 384 final String source = r""" |
| 303 class A { | 385 class A { |
| 304 A(); | 386 A(); |
| 305 f() => g(); | 387 f() => g(); |
| 306 g() => 42; | 388 g() => 42; |
| 307 } | 389 } |
| 308 main() { | 390 main() { |
| 309 var foo = new A().f(); | 391 var foo = new A().f(); |
| 310 foo; | 392 foo; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 349 } | 431 } |
| 350 | 432 |
| 351 testGetters() { | 433 testGetters() { |
| 352 final String source = r""" | 434 final String source = r""" |
| 353 class A { | 435 class A { |
| 354 var x; | 436 var x; |
| 355 A(this.x); | 437 A(this.x); |
| 356 get y => x; | 438 get y => x; |
| 357 get z => y; | 439 get z => y; |
| 358 } | 440 } |
| 441 class B { |
| 442 var x; |
| 443 B(this.x); |
| 444 } |
| 359 main() { | 445 main() { |
| 360 var a = new A(42); | 446 var a = new A(42); |
| 447 var b = new B('abc'); |
| 361 var foo = a.x; | 448 var foo = a.x; |
| 362 var bar = a.y; | 449 var bar = a.y; |
| 363 var baz = a.z; | 450 var baz = a.z; |
| 364 var qux = null.x; | 451 var qux = null.x; |
| 365 foo; bar; baz; qux; | 452 var quux = "__dynamic_for_test".x; |
| 453 foo; bar; baz; qux; quux; |
| 366 } | 454 } |
| 367 """; | 455 """; |
| 368 AnalysisResult result = analyze(source); | 456 AnalysisResult result = analyze(source); |
| 369 result.checkNodeHasType('foo', [result.int]); | 457 result.checkNodeHasType('foo', [result.int]); |
| 370 result.checkNodeHasType('bar', [result.int]); | 458 result.checkNodeHasType('bar', [result.int]); |
| 371 result.checkNodeHasType('baz', [result.int]); | 459 result.checkNodeHasType('baz', [result.int]); |
| 372 result.checkNodeHasType('qux', []); | 460 result.checkNodeHasType('qux', []); |
| 461 result.checkNodeHasType('quux', [result.int, result.string]); |
| 373 } | 462 } |
| 374 | 463 |
| 375 testSetters() { | 464 testSetters() { |
| 376 final String source = r""" | 465 final String source = r""" |
| 377 class A { | 466 class A { |
| 378 var x; | 467 var x; |
| 379 var w; | 468 var w; |
| 380 A(this.x, this.w); | 469 A(this.x, this.w); |
| 381 set y(a) { x = a; z = a; } | 470 set y(a) { x = a; z = a; } |
| 382 set z(a) { w = a; } | 471 set z(a) { w = a; } |
| 383 } | 472 } |
| 473 class B { |
| 474 var x; |
| 475 B(this.x); |
| 476 } |
| 384 main() { | 477 main() { |
| 385 var a = new A(42, 42); | 478 var a = new A(42, 42); |
| 479 var b = new B(42); |
| 386 a.x = 'abc'; | 480 a.x = 'abc'; |
| 387 a.y = true; | 481 a.y = true; |
| 388 null.x = 42; // should be ignored | 482 null.x = 42; // should be ignored |
| 483 "__dynamic_for_test".x = null; |
| 484 "__dynamic_for_test".y = 3.14; |
| 389 } | 485 } |
| 390 """; | 486 """; |
| 391 AnalysisResult result = analyze(source); | 487 AnalysisResult result = analyze(source); |
| 392 result.checkFieldHasType('A', 'x', [result.int, result.string, result.bool]); | 488 result.checkFieldHasType('B', 'x', |
| 393 result.checkFieldHasType('A', 'w', [result.int, result.bool]); | 489 [result.int, // new B(42) |
| 490 result.nullType]); // dynamic.x = null |
| 491 result.checkFieldHasType('A', 'x', |
| 492 [result.int, // new A(42, ...) |
| 493 result.string, // a.x = 'abc' |
| 494 result.bool, // a.y = true |
| 495 result.nullType, // dynamic.x = null |
| 496 result.double]); // dynamic.y = 3.14 |
| 497 result.checkFieldHasType('A', 'w', |
| 498 [result.int, // new A(..., 42) |
| 499 result.bool, // a.y = true |
| 500 result.double]); // dynamic.y = double |
| 394 } | 501 } |
| 395 | 502 |
| 396 testNamedParameters() { | 503 testNamedParameters() { |
| 397 final String source = r""" | 504 final String source = r""" |
| 398 class A { | 505 class A { |
| 399 var x, y, z, w; | 506 var x, y, z, w; |
| 400 A(this.x, {this.y, this.z, this.w}); | 507 A(this.x, {this.y, this.z, this.w}); |
| 401 } | 508 } |
| 402 main() { | 509 main() { |
| 403 new A(42); | 510 new A(42); |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 603 x; y; z; w; | 710 x; y; z; w; |
| 604 } | 711 } |
| 605 """; | 712 """; |
| 606 AnalysisResult result = analyze(source); | 713 AnalysisResult result = analyze(source); |
| 607 result.checkNodeHasType('x', []); | 714 result.checkNodeHasType('x', []); |
| 608 result.checkNodeHasType('y', []); | 715 result.checkNodeHasType('y', []); |
| 609 result.checkNodeHasType('z', []); | 716 result.checkNodeHasType('z', []); |
| 610 result.checkNodeHasType('w', []); | 717 result.checkNodeHasType('w', []); |
| 611 } | 718 } |
| 612 | 719 |
| 720 testDynamicIsAbsorbing() { |
| 721 final String source = r""" |
| 722 main () { |
| 723 var x = 1; |
| 724 if (true) { |
| 725 x = "__dynamic_for_test"; |
| 726 } else { |
| 727 x = 42; |
| 728 } |
| 729 x; |
| 730 } |
| 731 """; |
| 732 AnalysisResult result = analyze(source); |
| 733 result.checkNodeHasUnknownType('x'); |
| 734 } |
| 735 |
| 613 void main() { | 736 void main() { |
| 737 testDynamicBackDoor(); |
| 614 testLiterals(); | 738 testLiterals(); |
| 615 testRedefinition(); | 739 testRedefinition(); |
| 616 testIfThenElse(); | 740 testIfThenElse(); |
| 617 testTernaryIf(); | 741 testTernaryIf(); |
| 618 testWhile(); | 742 testWhile(); |
| 619 testFor1(); | 743 testFor1(); |
| 620 testFor2(); | 744 testFor2(); |
| 745 // testToplevelVariable(); // toplevel variables are not yet supported |
| 621 testNonRecusiveFunction(); | 746 testNonRecusiveFunction(); |
| 622 testRecusiveFunction(); | 747 testRecusiveFunction(); |
| 623 testMutuallyRecusiveFunction(); | 748 testMutuallyRecusiveFunction(); |
| 749 testSimpleSend(); |
| 750 // testSendToClosureField(); // closures are not yet supported |
| 624 testSendToThis1(); | 751 testSendToThis1(); |
| 625 testSendToThis2(); | 752 testSendToThis2(); |
| 626 testConstructor(); | 753 testConstructor(); |
| 627 testGetters(); | 754 testGetters(); |
| 628 testSetters(); | 755 testSetters(); |
| 629 testNamedParameters(); | 756 testNamedParameters(); |
| 630 testListLiterals(); | 757 testListLiterals(); |
| 631 testMapLiterals(); | 758 testMapLiterals(); |
| 632 testReturn(); | 759 testReturn(); |
| 633 // testNoReturn(); // right now we infer the empty type instead of null | 760 // testNoReturn(); // right now we infer the empty type instead of null |
| 634 testArithmeticOperators(); | 761 testArithmeticOperators(); |
| 635 testOperators(); | 762 testOperators(); |
| 636 testCompoundOperators1(); | 763 testCompoundOperators1(); |
| 637 testCompoundOperators2(); | 764 testCompoundOperators2(); |
| 638 // testFieldInitialization(); // TODO(polux) | 765 // testFieldInitialization(); // TODO(polux) |
| 639 testSendWithWrongArity(); | 766 testSendWithWrongArity(); |
| 767 testDynamicIsAbsorbing(); |
| 640 } | 768 } |
| OLD | NEW |