| // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| import '../../../sdk/lib/_internal/compiler/implementation/types/types.dart' |
| show TypeMask; |
| |
| import 'compiler_helper.dart'; |
| import 'parser_helper.dart'; |
| |
| void compileAndFind(String code, |
| String className, |
| String memberName, |
| bool disableInlining, |
| check(compiler, element)) { |
| Uri uri = new Uri.fromComponents(scheme: 'source'); |
| var compiler = compilerFor(code, uri); |
| compiler.disableInlining = disableInlining; |
| compiler.runCompiler(uri); |
| var cls = findElement(compiler, className); |
| var member = cls.lookupLocalMember(buildSourceString(memberName)); |
| return check(compiler.typesTask.typesInferrer, member); |
| } |
| |
| const String TEST_1 = r""" |
| class A { |
| x(p) => p; |
| } |
| main() { new A().x("s"); } |
| """; |
| |
| const String TEST_2 = r""" |
| class A { |
| x(p) => p; |
| } |
| main() { new A().x(1); } |
| """; |
| |
| const String TEST_3 = r""" |
| class A { |
| x(p) => x(p - 1); |
| } |
| main() { new A().x(1); } |
| """; |
| |
| const String TEST_4 = r""" |
| class A { |
| x(p) => x(p - 1); |
| } |
| main() { new A().x(1.5); } |
| """; |
| |
| const String TEST_5 = r""" |
| class A { |
| x(p) => p; |
| } |
| main() { |
| new A().x(1); |
| new A().x(1.5); |
| } |
| """; |
| |
| const String TEST_6 = r""" |
| class A { |
| x(p) => p; |
| } |
| main() { |
| new A().x(1.5); |
| new A().x(1); |
| } |
| """; |
| |
| const String TEST_7 = r""" |
| class A { |
| x(p) => x("x"); |
| } |
| main() { |
| new A().x(1); |
| } |
| """; |
| |
| const String TEST_8 = r""" |
| class A { |
| x(p1, p2) => x(p1, "x"); |
| } |
| main() { |
| new A().x(1, 2); |
| } |
| """; |
| |
| const String TEST_9 = r""" |
| class A { |
| x(p1, p2) => x(p1, p2); |
| } |
| main() { |
| new A().x(1, 2); |
| } |
| """; |
| |
| const String TEST_10 = r""" |
| class A { |
| x(p1, p2) => x(p1, p2); |
| } |
| void f(p) { |
| p.x("x", "y"); |
| } |
| main() { |
| f(null); |
| new A().x(1, 2); |
| } |
| """; |
| |
| const String TEST_11 = r""" |
| class A { |
| x(p1, p2) => x(1, 2); |
| } |
| main() { |
| new A().x("x", "y"); |
| } |
| """; |
| |
| const String TEST_12 = r""" |
| class A { |
| x(p1, [p2 = 1]) => 1; |
| } |
| main() { |
| new A().x("x", 1); |
| new A().x("x"); |
| } |
| """; |
| |
| const String TEST_13 = r""" |
| class A { |
| x(p) => 1; |
| } |
| f(p) => p.x(2.2); |
| main() { |
| new A().x(1); |
| f(new A()); |
| } |
| """; |
| |
| const String TEST_14 = r""" |
| class A { |
| x(p1, [p2 = "s"]) => 1; |
| } |
| main() { |
| new A().x(1); |
| } |
| """; |
| |
| const String TEST_15 = r""" |
| class A { |
| x(p1, [p2 = true]) => 1; |
| } |
| f(p) => p.a("x"); |
| main() { |
| new A().x("x"); |
| new A().x("x", false); |
| f(null); |
| } |
| """; |
| |
| const String TEST_16 = r""" |
| class A { |
| x(p1, [p2 = 1, p3 = "s"]) => 1; |
| } |
| main() { |
| new A().x(1); |
| new A().x(1, 2); |
| new A().x(1, 2, "x"); |
| new A().x(1, p2: 2); |
| new A().x(1, p3: "x"); |
| new A().x(1, p3: "x", p2: 2); |
| new A().x(1, p2: 2, p3: "x"); |
| } |
| """; |
| |
| const String TEST_17 = r""" |
| class A { |
| x(p1, [p2 = 1, p3 = "s"]) => 1; |
| } |
| main() { |
| new A().x(1, true, 1.1); |
| new A().x(1, false, 2.2); |
| new A().x(1, p3: 3.3, p2: true); |
| new A().x(1, p2: false, p3: 4.4); |
| } |
| """; |
| |
| const String TEST_18 = r""" |
| class A { |
| x(p1, p2) => x(p1, p2); |
| } |
| class B extends A { |
| } |
| main() { |
| new B().x("a", "b"); |
| new A().x(1, 2); |
| } |
| """; |
| |
| void doTest(String test, bool enableInlining, Function f) { |
| compileAndFind( |
| test, |
| 'A', |
| 'x', |
| enableInlining, |
| (inferrer, element) { |
| var expectedTypes = f(inferrer); |
| var signature = element.computeSignature(inferrer.compiler); |
| int index = 0; |
| signature.forEachParameter((Element element) { |
| Expect.equals(expectedTypes[index++], inferrer.typeOf[element]); |
| }); |
| Expect.equals(index, expectedTypes.length); |
| }); |
| } |
| |
| void runTest(String test, Function f) { |
| doTest(test, false, f); |
| doTest(test, true, f); |
| } |
| |
| void test() { |
| runTest(TEST_1, (inferrer) => [inferrer.stringType]); |
| runTest(TEST_2, (inferrer) => [inferrer.intType]); |
| runTest(TEST_3, (inferrer) => [inferrer.numType]); |
| runTest(TEST_4, (inferrer) => [inferrer.numType]); |
| runTest(TEST_5, (inferrer) => [inferrer.numType]); |
| runTest(TEST_6, (inferrer) => [inferrer.numType]); |
| runTest(TEST_7, (inferrer) => [inferrer.dynamicType]); |
| |
| // In the following tests, we can't infer the right types because we |
| // have recursive calls with the same parameters. We should build a |
| // constraint system for those, to find the types. |
| runTest(TEST_8, (inferrer) => [inferrer.dynamicType, inferrer.dynamicType]); |
| runTest(TEST_9, (inferrer) => [inferrer.dynamicType, inferrer.dynamicType]); |
| runTest(TEST_10, (inferrer) => [inferrer.dynamicType, inferrer.dynamicType]); |
| runTest(TEST_11, (inferrer) => [inferrer.dynamicType, inferrer.dynamicType]); |
| |
| runTest(TEST_12, (inferrer) => [inferrer.stringType, inferrer.intType]); |
| |
| runTest(TEST_13, (inferrer) => [inferrer.numType]); |
| |
| runTest(TEST_14, (inferrer) => [inferrer.intType, inferrer.stringType]); |
| |
| runTest(TEST_15, (inferrer) => [inferrer.stringType, inferrer.boolType]); |
| |
| runTest(TEST_16, (inferrer) => [inferrer.intType, |
| inferrer.intType, |
| inferrer.stringType]); |
| |
| runTest(TEST_17, (inferrer) => [inferrer.intType, |
| inferrer.boolType, |
| inferrer.doubleType]); |
| |
| runTest(TEST_18, (inferrer) => [inferrer.dynamicType, inferrer.dynamicType]); |
| } |
| |
| void main() { |
| test(); |
| } |