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

Unified Diff: compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerTest.java

Issue 8513011: Sorted some files before refactoring (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 9 years, 1 month 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 side-by-side diff with in-line comments
Download patch
Index: compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerTest.java
diff --git a/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerTest.java b/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerTest.java
index 6805a1754acf6b7f5b62bce8fca81659a270bf6d..47cf5bf0d3abfbf4b24fa75923f1ab1260cbca73 100644
--- a/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerTest.java
+++ b/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerTest.java
@@ -20,64 +20,52 @@ import java.util.Map;
public class TypeAnalyzerTest extends TypeAnalyzerTestCase {
- public void testLabels() {
- // Labels should be inside a function or method to be used
-
- // break
- analyze("foo() { L: for (;true;) { break L; } }");
- analyze("foo() { int x; List<int> c; L: for (x in c) { break L; } }");
- analyze("foo() { List<int> c; L: for (var x in c) { break L; } }");
- analyze("foo() { L: while (true) { break L; } }");
- analyze("foo() { L: do { break L; } while (true); }");
-
- analyze("foo() { L: for (;true;) { for (;true;) { break L; } } }");
- analyze("foo() { int x; List<int> c; L: for (x in c) { for (;true;) { break L; } } }");
- analyze("foo() { List<int> c; L: for (var x in c) { for (;true;) { break L; } } }");
- analyze("foo() { L: while (true) { for (;true;) { break L; } } }");
- analyze("foo() { L: do { for (;true;) { break L; } } while (true); }");
-
- // continue
- analyze("foo() { L: for (;true;) { continue L; } }");
- analyze("foo() { int x; List<int> c; L: for (x in c) { continue L; } }");
- analyze("foo() { List<int> c; L: for (var x in c) { continue L; } }");
- analyze("foo() { L: do { continue L; } while (true); }");
-
- analyze("foo() { L: for (;true;) { for (;true;) { continue L; } } }");
- analyze(
- "foo() { int x; List<int> c; L: for (x in c) { for (;true;) { continue L; } } }");
- analyze("foo() { List<int> c; L: for (var x in c) { for (;true;) { continue L; } } }");
- analyze("foo() { L: while (true) { for (;true;) { continue L; } } }");
- analyze("foo() { L: do { for (;true;) { continue L; } } while (true); }");
-
- // corner cases
- analyze("foo() { L: break L; }");
-
- // TODO(zundel): Not type errors, but warnings.
- analyze("foo() { L: for (;true;) { } }");
- analyze("foo() { while (true) { L: var a; } }");
- }
-
- public void testLiterals() {
- checkSimpleType(intElement.getType(), "1");
- checkSimpleType(doubleElement.getType(), ".0");
- checkSimpleType(doubleElement.getType(), "1.0");
- checkSimpleType(bool.getType(), "true");
- checkSimpleType(bool.getType(), "false");
- checkSimpleType(string.getType(), "'fisk'");
- checkSimpleType(string.getType(), "'f${null}sk'");
+ /**
+ * There was problem that cyclic class declaration caused infinite loop.
+ * <p>
+ * http://code.google.com/p/dart/issues/detail?id=348
+ */
+ public void test_cyclicDeclaration() {
+ Map<String, ClassElement> source = loadSource(
+ "class Foo extends Bar {",
+ "}",
+ "class Bar extends Foo {",
+ "}");
+ analyzeClasses(source);
+ // Foo and Bar have cyclic declaration
+ ClassElement classFoo = source.get("Foo");
+ ClassElement classBar = source.get("Bar");
+ assertEquals(classFoo, classBar.getSupertype().getElement());
+ assertEquals(classBar, classFoo.getSupertype().getElement());
}
- public void testUnresolvedIdentifier() {
- setExpectedTypeErrorCount(3);
- checkType(typeProvider.getDynamicType(), "y");
- checkExpectedTypeErrorCount();
+ public void testArrayLiteral() {
+ analyze("['x'];");
+ analyze("<String>['x'];");
+ analyzeFail("<int>['x'];", TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyzeFail("<String>['x', 1];", TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyze("List<String> strings = ['x'];");
+ analyze("List<String> strings = <String>['x'];");
+ analyze("List array = ['x'];");
+ analyze("List array = <String>['x'];");
+ analyze("List<int> ints = ['x'];");
+ analyzeFail("List<int> ints = <String>['x'];",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
}
- public void testInitializers() {
- analyze("int i = 1;");
- analyze("double d1 = .0;");
- analyze("double d2 = 1.0;");
- analyze("int x = null;");
+ public void testAssert() {
+ analyze("assert(true);");
+ analyze("assert(false);");
+ analyzeFail("assert('message');",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyze("assert(null);");
+ analyzeFail("assert(1);",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyze("assert(foo() {});");
+ analyze("assert(bool foo() {});");
+ analyze("assert(Object foo() {});");
+ analyzeFail("assert(String foo() {});",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
}
public void testBadInitializers() {
@@ -85,420 +73,742 @@ public class TypeAnalyzerTest extends TypeAnalyzerTestCase {
analyzeFail("int j = 1.0;", TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
}
- public void testFunctionTypes() {
- checkFunctionStatement("String foo() {};", "() -> String");
- checkFunctionStatement("Object foo() {};", "() -> Object");
- checkFunctionStatement("String foo(int i, bool b) {};", "(int, bool) -> String");
- }
-
- public void testIdentifiers() {
- analyze("{ int i; i = 2; }");
- analyze("{ int j, k; j = 1; k = 3; }");
- analyzeFail("{ int i; i = 'string'; }", TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyzeFail("{ int j, k; k = 'string'; }",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyzeFail("{ int j, k; j = 'string'; }",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- }
+ public void testBinaryOperators() {
+ ClassElement cls = loadClass("class_with_operators.dart", "ClassWithOperators");
+ analyzeIn(cls, "i = o[0]", 0);
+ analyzeIn(cls, "s = o[0]", 1);
+ analyzeIn(cls, "o['fisk']", 1);
+ analyzeIn(cls, "i && o", 2);
+ analyzeIn(cls, "b && o", 1);
+ analyzeIn(cls, "i && b", 1);
+ analyzeIn(cls, "b && b", 0);
+ analyzeIn(cls, "i || o", 2);
+ analyzeIn(cls, "b || o", 1);
+ analyzeIn(cls, "i || b", 1);
+ analyzeIn(cls, "b || b", 0);
- public void testRawTypes() {
- loadFile("interfaces.dart");
+ EnumSet<Token> userOperators = EnumSet.of(Token.SHR,
+ Token.ADD,
+ Token.SUB,
+ Token.MUL,
+ Token.DIV,
+ Token.TRUNC,
+ Token.MOD,
+ Token.LT,
+ Token.GT,
+ Token.LTE,
+ Token.GTE);
+ for (Token op : userOperators) {
+ String expression;
+ expression = String.format("untyped %s untyped", op.getSyntax());
+ analyzeIn(cls, expression, 0);
+ expression = String.format("o = untyped %s untyped", op.getSyntax());
+ analyzeIn(cls, expression, 0);
+ expression = String.format("s = untyped %s untyped", op.getSyntax());
+ analyzeIn(cls, expression, 0);
+ expression = String.format("o %s untyped", op.getSyntax());
+ analyzeIn(cls, expression, 0);
+ expression = String.format("o = o %s untyped", op.getSyntax());
+ analyzeIn(cls, expression, 0);
+ expression = String.format("s = o %s untyped", op.getSyntax());
+ analyzeIn(cls, expression, 1);
+ expression = String.format("o %s null", op.getSyntax());
+ analyzeIn(cls, expression, 0);
+ expression = String.format("o = o %s null", op.getSyntax());
+ analyzeIn(cls, expression, 0);
+ expression = String.format("s = o %s null", op.getSyntax());
+ analyzeIn(cls, expression, 1);
+ expression = String.format("o %s o", op.getSyntax());
+ analyzeIn(cls, expression, 0);
+ expression = String.format("o = o %s o", op.getSyntax());
+ analyzeIn(cls, expression, 0);
+ expression = String.format("s = o %s o", op.getSyntax());
+ analyzeIn(cls, expression, 1);
+ expression = String.format("o %s s", op.getSyntax());
+ analyzeIn(cls, expression, 1);
+ expression = String.format("o %s i", op.getSyntax());
+ analyzeIn(cls, expression, 1);
+ }
- analyze("{ Sub s; }");
- analyze("{ var s = new Sub(); }");
- analyze("{ Sub s = new Sub(); }");
- analyze("{ Sub<String> s = new Sub(); }");
- analyze("{ Sub<String> s; }");
- analyze("{ var s = new Sub<String>(); }");
- analyze("{ Sub s = new Sub<String>(); }");
- analyze("{ Sub<String> s = new Sub<String>(); }");
- }
+ EnumSet<Token> equalityOperators = EnumSet.of(Token.EQ,
+ Token.NE,
+ Token.EQ_STRICT,
+ Token.NE_STRICT);
+ for (Token op : equalityOperators) {
+ String expression;
+ expression = String.format("untyped %s untyped", op.getSyntax());
+ analyzeIn(cls, expression, 0);
+ expression = String.format("b = untyped %s untyped", op.getSyntax());
+ analyzeIn(cls, expression, 0);
+ expression = String.format("s = untyped %s untyped", op.getSyntax());
+ analyzeIn(cls, expression, 1);
+ expression = String.format("i = untyped %s untyped", op.getSyntax());
+ analyzeIn(cls, expression, 1);
- public void testMethodInvocations() {
- loadFile("class_with_methods.dart");
- final String header = "{ ClassWithMethods c; int i, j; ";
+ expression = String.format("o %s o", op.getSyntax());
+ analyzeIn(cls, expression, 0);
+ expression = String.format("b = o %s o", op.getSyntax());
+ analyzeIn(cls, expression, 0);
+ expression = String.format("s = o %s o", op.getSyntax());
+ analyzeIn(cls, expression, 1);
+ expression = String.format("i = o %s o", op.getSyntax());
+ analyzeIn(cls, expression, 1);
- analyze(header + "int k = c.untypedNoArgumentMethod(); }");
- analyze(header + "ClassWithMethods x = c.untypedNoArgumentMethod(); }");
+ expression = String.format("o %s s", op.getSyntax());
+ analyzeIn(cls, expression, 0);
+ expression = String.format("b = o %s s", op.getSyntax());
+ analyzeIn(cls, expression, 0);
+ expression = String.format("s = o %s s", op.getSyntax());
+ analyzeIn(cls, expression, 1);
+ expression = String.format("i = o %s s", op.getSyntax());
+ analyzeIn(cls, expression, 1);
+ }
- analyze(header + "int k = c.untypedOneArgumentMethod(c); }");
- analyze(header + "ClassWithMethods x = c.untypedOneArgumentMethod(1); }");
- analyze(header + "int k = c.untypedOneArgumentMethod('string'); }");
- analyze(header + "int k = c.untypedOneArgumentMethod(i); }");
+ EnumSet<Token> compoundAssignmentOperators =
+ EnumSet.of(Token.ASSIGN_ADD,
+ Token.ASSIGN_SUB,
+ Token.ASSIGN_MUL,
+ Token.ASSIGN_DIV,
+ Token.ASSIGN_MOD,
+ Token.ASSIGN_TRUNC,
+ Token.ASSIGN_SHR);
- analyze(header + "int k = c.untypedTwoArgumentMethod(1, 'string'); }");
- analyze(header + "int k = c.untypedTwoArgumentMethod(i, j); }");
- analyze(header + "ClassWithMethods x = c.untypedTwoArgumentMethod(i, c); }");
+ for (Token op : compoundAssignmentOperators) {
+ String expression;
+ expression = String.format("o %s untyped", op.getSyntax());
+ analyzeIn(cls, expression, 0);
+ expression = String.format("s %s untyped", op.getSyntax());
+ analyzeIn(cls, expression, 1);
+ expression = String.format("o %s null", op.getSyntax());
+ analyzeIn(cls, expression, 0);
+ expression = String.format("s %s null", op.getSyntax());
+ analyzeIn(cls, expression, 1);
+ expression = String.format("o %s o", op.getSyntax());
+ analyzeIn(cls, expression, 0);
+ expression = String.format("s %s o", op.getSyntax());
+ analyzeIn(cls, expression, 1);
+ expression = String.format("o %s i", op.getSyntax());
+ analyzeIn(cls, expression, 1);
+ }
- analyze(header + "int k = c.intNoArgumentMethod(); }");
- analyzeFail(header + "ClassWithMethods x = c.intNoArgumentMethod(); }",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyzeIn(cls, "untyped is String", 0);
+ analyzeIn(cls, "b = untyped is String", 0);
+ analyzeIn(cls, "s = untyped is String", 1);
+ analyzeIn(cls, "s is String", 0);
+ analyzeIn(cls, "b = s is String", 0);
+ analyzeIn(cls, "s = s is String", 1);
- analyzeFail(header + "int k = c.intOneArgumentMethod(c); }",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyzeFail(header + "ClassWithMethods x = c.intOneArgumentMethod(1); }",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyzeFail(header + "int k = c.intOneArgumentMethod('string'); }",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyze(header + "int k = c.intOneArgumentMethod(i); }");
+ analyzeIn(cls, "untyped is !String", 0);
+ analyzeIn(cls, "b = untyped is !String", 0);
+ analyzeIn(cls, "s = untyped is !String", 1);
+ analyzeIn(cls, "s is !String", 0);
+ analyzeIn(cls, "b = s is !String", 0);
+ analyzeIn(cls, "s = s is !String", 1);
- analyzeFail(header + "int k = c.intTwoArgumentMethod(1, 'string'); }",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyze(header + "int k = c.intTwoArgumentMethod(i, j); }");
- analyzeFail(header + "ClassWithMethods x = c.intTwoArgumentMethod(i, j); }",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyzeFail("1 == !'s';", TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
}
- public void testMethodInvocationArgumentCount() {
- loadFile("class_with_methods.dart");
- final String header = "{ ClassWithMethods c; ";
+ public void testBitOperators() {
+ Map<String, ClassElement> source = loadSource(
+ "class ClassWithBitops {",
+ " num n;",
+ " int i;",
+ " double d;",
+ " ClassWithBitops o;",
+ " num foo() { return 42; }",
+ " int operator |(int arg) { return arg; }",
+ " int operator &(int arg) { return arg; }",
+ " int operator ^(int arg) { return arg; }",
+ " int operator >>(int arg) { return arg; }",
+ " int operator >>>(int arg) { return arg; }",
+ " int operator <<(int arg) { return arg; }",
+ " int operator ~() { return 1; }",
+ "}");
+ ClassElement cls = source.get("ClassWithBitops");
+ analyzeClasses(source);
- analyzeFail(header + "c.untypedNoArgumentMethod(1); }",
- TypeErrorCode.EXTRA_ARGUMENT);
- analyzeFail(header + "c.untypedOneArgumentMethod(); }",
- TypeErrorCode.MISSING_ARGUMENT);
- analyzeFail(header + "c.untypedOneArgumentMethod(1, 1); }",
- TypeErrorCode.EXTRA_ARGUMENT);
- analyzeFail(header + "c.untypedTwoArgumentMethod(); }",
- TypeErrorCode.MISSING_ARGUMENT);
- analyzeFail(header + "c.untypedTwoArgumentMethod(1, 2, 3); }",
- TypeErrorCode.EXTRA_ARGUMENT);
- analyzeFail(header + "c.intNoArgumentMethod(1); }",
- TypeErrorCode.EXTRA_ARGUMENT);
- analyzeFail(header + "c.intOneArgumentMethod(); }",
- TypeErrorCode.MISSING_ARGUMENT);
- analyzeFail(header + "c.intOneArgumentMethod(1, 1); }",
- TypeErrorCode.EXTRA_ARGUMENT);
- analyzeFail(header + "c.intTwoArgumentMethod(); }",
- TypeErrorCode.MISSING_ARGUMENT);
- analyzeFail(header + "c.intTwoArgumentMethod(1, 2, 3); }",
- TypeErrorCode.EXTRA_ARGUMENT);
- analyze(header + "c.untypedField(); }");
- }
+ EnumSet<Token> operators = EnumSet.of(Token.BIT_AND,
+ Token.BIT_OR,
+ Token.BIT_XOR,
+ Token.SHL,
+ Token.SAR);
+ for (Token operator : operators) {
+ analyzeIn(cls, String.format("n %s n" , operator), 0);
+ analyzeIn(cls, String.format("foo() %s i" , operator), 0);
+ analyzeIn(cls, String.format("o %s i" , operator), 0);
+ analyzeIn(cls, String.format("n = d %s i", operator), 1);
+ analyzeIn(cls, String.format("d = o %s i", operator), 1);
+ analyzeIn(cls, String.format("d = n %s i", operator), 1);
+ analyzeIn(cls, String.format("n %s o" , operator), 1);
+ }
- public void testLoadInterfaces() {
- loadFile("interfaces.dart");
- ClassElement superElement = coreElements.get("Super");
- assertNotNull("no element for Super", superElement);
- assertEquals(object.getType(), superElement.getSupertype());
- assertEquals(0, superElement.getInterfaces().size());
- ClassElement sub = coreElements.get("Sub");
- assertNotNull("no element for Sub", sub);
- assertEquals(object.getType(), sub.getSupertype());
- assertEquals(1, sub.getInterfaces().size());
- assertEquals(superElement, sub.getInterfaces().get(0).getElement());
- InterfaceType superString = itype(superElement, itype(string));
- InterfaceType subString = itype(sub, itype(string));
- Types types = getTypes();
- assertEquals("Super<String>", String.valueOf(types.asInstanceOf(superString, superElement)));
- assertEquals("Super<String>", String.valueOf(types.asInstanceOf(subString, superElement)));
- assertEquals("Sub<String>", String.valueOf(types.asInstanceOf(subString, sub)));
- assertNull(types.asInstanceOf(superString, sub));
+ EnumSet<Token> assignOperators = EnumSet.of(Token.ASSIGN_BIT_AND,
+ Token.ASSIGN_BIT_OR,
+ Token.ASSIGN_BIT_XOR,
+ Token.ASSIGN_SHL,
+ Token.ASSIGN_SAR);
+ for (Token operator : assignOperators) {
+ analyzeIn(cls, String.format("n %s n" , operator), 0);
+ analyzeIn(cls, String.format("n %s i" , operator), 0);
+ analyzeIn(cls, String.format("d %s i", operator), 1);
+ analyzeIn(cls, String.format("o %s i", operator), 1);
+ analyzeIn(cls, String.format("n %s o" , operator), 1);
+ }
+
+ analyzeIn(cls, "i = ~o", 0);
+ analyzeIn(cls, "i = ~n", 0);
+ analyzeIn(cls, "d = ~n", 1);
}
- public void testSuperInterfaces() {
- // If this test is failing, first debug any failures in testLoadInterfaces.
- loadFile("interfaces.dart");
- analyze("Super<String> s = new Sub<String>();");
- analyze("Super<Object> o = new Sub<String>();");
- analyzeFail("Super<String> f1 = new Sub<int>();",
+ public void testConditionalExpression() {
+ analyze("true ? 1 : 2;");
+ analyze("null ? 1 : 2;");
+ analyzeFail("0 ? 1 : 2;",
TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyzeFail("Sub<String> f2 = new Sub<int>();",
+ analyzeFail("'' ? 1 : 2;",
TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyzeFail("{ int i; true ? i = 2.7 : 2; }",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyzeFail("{ int i; true ? 2 : i = 2.7; }",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyze("{ int i; i = true ? 2.7 : 2; }");
}
- public void testUnaryOperators() {
- Map<String, ClassElement> source = loadSource(
- "class Foo {",
- " Foo foo;",
- " bool b;",
- " int i;",
- " Foo operator negate() { return this; }",
- " Foo operator +(int operand) { return this; }",
- " Foo operator -(int operand) { return this; }",
+ public void testConstructorForwarding() {
+ Map<String, ClassElement> classes = loadSource(
+ "class MissingArgument {",
+ " MissingArgument() : this.bar() {}",
+ " MissingArgument.bar(int i) {}",
"}",
- "class Bar {",
- " Bar bar;",
- " Bar operator +(Bar operand) { return this; }",
- " Bar operator -(Bar operand) { return this; }",
+ "class IntArgument {",
+ " IntArgument() : this.bar(1) {}",
+ " IntArgument.bar(int i) {}",
"}",
- "class Baz<T extends Foo> {",
- " T baz;",
+ "class ExtraIntArgument {",
+ " ExtraIntArgument() : this.bar(1, 1) {}",
+ " ExtraIntArgument.bar(int i) {}",
"}",
- "class Qux<T> { ",
- " T qux; ",
- " void x() { }",
- " y() { }",
+ "class StringArgument {",
+ " StringArgument() : this.bar('') {}",
+ " StringArgument.bar(int i) {}",
"}",
- "class X {",
- " X x;",
- " Z operator negate() { return null; }",
- " Z operator +(int operand) { return null; }",
- " Z operator -(int operand) { return null; }",
+ "class NullArgument {",
+ " NullArgument() : this.bar(null) {}",
+ " NullArgument.bar(int i) {}",
"}",
- "class Y extends X { Y y; }",
- "class Z extends X { Z z; }"
- );
- analyzeClasses(source);
- ClassElement foo = source.get("Foo");
- ClassElement bar = source.get("Bar");
- ClassElement baz = source.get("Baz");
- ClassElement qux = source.get("Qux");
- ClassElement y = source.get("Y");
- ClassElement z = source.get("Z");
- for (Token op : EnumSet.of(Token.DEC, Token.INC, Token.SUB)) {
- analyzeIn(foo, String.format("%sfoo", op), 0);
- analyzeIn(foo, String.format("i = %sfoo", op), 1);
- analyzeIn(bar, String.format("%sbar", op), 1);
- analyzeIn(baz, String.format("%sbaz", op), 0);
- analyzeIn(qux, String.format("%squx", op), 1);
- }
- analyzeIn(z, "z = x++", 0);
- analyzeIn(z, "z = ++x", 0);
- analyzeIn(z, "z = x--", 0);
- analyzeIn(z, "z = --x", 0);
- analyzeIn(y, "y = x++", 0);
- analyzeIn(y, "y = ++x", 1);
- analyzeIn(y, "y = x--", 0);
- analyzeIn(y, "y = --x", 1);
+ "class OptionalParameter {",
+ " OptionalParameter() : this.bar() {}",
+ " OptionalParameter.bar([int i = null]) {}",
+ " OptionalParameter.foo() : this.bar('') {}",
+ "}");
+ analyzeClass(classes.get("MissingArgument"), 1);
+ analyzeClass(classes.get("IntArgument"), 0);
+ analyzeClass(classes.get("ExtraIntArgument"), 1);
+ analyzeClass(classes.get("StringArgument"), 1);
+ analyzeClass(classes.get("NullArgument"), 0);
+ analyzeClass(classes.get("OptionalParameter"), 1);
+ }
- analyzeIn(foo, "b = !b", 0);
- analyzeIn(foo, "foo = !foo", 2);
- analyzeIn(foo, "b = !i", 1);
- analyzeIn(foo, "foo = !b", 1);
- analyzeIn(qux, "-x()", 1);
- analyzeIn(qux, "-y()", 0);
+ public void testDoWhileStatement() {
+ analyze("do {} while (true);");
+ analyze("do {} while (null);");
+ analyzeFail("do {} while (0);",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyzeFail("do {} while ('');",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyzeFail("do { int i = 0.5; } while (true);",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyzeFail("do { int i = 0.5; } while (null);",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
}
- public void testBinaryOperators() {
- ClassElement cls = loadClass("class_with_operators.dart", "ClassWithOperators");
- analyzeIn(cls, "i = o[0]", 0);
- analyzeIn(cls, "s = o[0]", 1);
- analyzeIn(cls, "o['fisk']", 1);
- analyzeIn(cls, "i && o", 2);
- analyzeIn(cls, "b && o", 1);
- analyzeIn(cls, "i && b", 1);
- analyzeIn(cls, "b && b", 0);
- analyzeIn(cls, "i || o", 2);
- analyzeIn(cls, "b || o", 1);
- analyzeIn(cls, "i || b", 1);
- analyzeIn(cls, "b || b", 0);
+ public void testFactory() {
+ analyzeClasses(loadSource(
+ "interface Foo factory Bar {",
+ " Foo(argument);",
+ "}",
+ "interface Baz {}",
+ "class Bar implements Foo, Baz {",
+ " Bar(String argument) {}",
+ "}"));
- EnumSet<Token> userOperators = EnumSet.of(Token.SHR,
- Token.ADD,
- Token.SUB,
- Token.MUL,
- Token.DIV,
- Token.TRUNC,
- Token.MOD,
- Token.LT,
- Token.GT,
- Token.LTE,
- Token.GTE);
- for (Token op : userOperators) {
- String expression;
- expression = String.format("untyped %s untyped", op.getSyntax());
- analyzeIn(cls, expression, 0);
- expression = String.format("o = untyped %s untyped", op.getSyntax());
- analyzeIn(cls, expression, 0);
- expression = String.format("s = untyped %s untyped", op.getSyntax());
- analyzeIn(cls, expression, 0);
- expression = String.format("o %s untyped", op.getSyntax());
- analyzeIn(cls, expression, 0);
- expression = String.format("o = o %s untyped", op.getSyntax());
- analyzeIn(cls, expression, 0);
- expression = String.format("s = o %s untyped", op.getSyntax());
- analyzeIn(cls, expression, 1);
- expression = String.format("o %s null", op.getSyntax());
- analyzeIn(cls, expression, 0);
- expression = String.format("o = o %s null", op.getSyntax());
- analyzeIn(cls, expression, 0);
- expression = String.format("s = o %s null", op.getSyntax());
- analyzeIn(cls, expression, 1);
- expression = String.format("o %s o", op.getSyntax());
- analyzeIn(cls, expression, 0);
- expression = String.format("o = o %s o", op.getSyntax());
- analyzeIn(cls, expression, 0);
- expression = String.format("s = o %s o", op.getSyntax());
- analyzeIn(cls, expression, 1);
- expression = String.format("o %s s", op.getSyntax());
- analyzeIn(cls, expression, 1);
- expression = String.format("o %s i", op.getSyntax());
- analyzeIn(cls, expression, 1);
- }
-
- EnumSet<Token> equalityOperators = EnumSet.of(Token.EQ,
- Token.NE,
- Token.EQ_STRICT,
- Token.NE_STRICT);
- for (Token op : equalityOperators) {
- String expression;
- expression = String.format("untyped %s untyped", op.getSyntax());
- analyzeIn(cls, expression, 0);
- expression = String.format("b = untyped %s untyped", op.getSyntax());
- analyzeIn(cls, expression, 0);
- expression = String.format("s = untyped %s untyped", op.getSyntax());
- analyzeIn(cls, expression, 1);
- expression = String.format("i = untyped %s untyped", op.getSyntax());
- analyzeIn(cls, expression, 1);
+ analyzeFail("Baz x = new Foo('');", TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ }
- expression = String.format("o %s o", op.getSyntax());
- analyzeIn(cls, expression, 0);
- expression = String.format("b = o %s o", op.getSyntax());
- analyzeIn(cls, expression, 0);
- expression = String.format("s = o %s o", op.getSyntax());
- analyzeIn(cls, expression, 1);
- expression = String.format("i = o %s o", op.getSyntax());
- analyzeIn(cls, expression, 1);
+ public void testFieldAccess() {
+ ClassElement element = loadFile("class_with_supertypes.dart").get("ClassWithSupertypes");
+ assertNotNull("unable to locate ClassWithSupertypes", element);
+ analyzeIn(element, "field = 1", 0);
+ analyzeIn(element, "staticField = 1", 0);
+ analyzeIn(element, "fieldInSuperclass = 1", 0);
+ analyzeIn(element, "staticFieldInSuperclass = 1", 0);
- expression = String.format("o %s s", op.getSyntax());
- analyzeIn(cls, expression, 0);
- expression = String.format("b = o %s s", op.getSyntax());
- analyzeIn(cls, expression, 0);
- expression = String.format("s = o %s s", op.getSyntax());
- analyzeIn(cls, expression, 1);
- expression = String.format("i = o %s s", op.getSyntax());
- analyzeIn(cls, expression, 1);
- }
+ analyzeIn(element, "field = field", 0);
+ analyzeIn(element, "field = staticField", 0);
+ analyzeIn(element, "field = fieldInSuperclass", 0);
+ analyzeIn(element, "field = staticFieldInSuperclass", 0);
+ analyzeIn(element, "field = fieldInInterface", 0);
+ analyzeIn(element, "field = staticFieldInInterface", 0);
- EnumSet<Token> compoundAssignmentOperators =
- EnumSet.of(Token.ASSIGN_ADD,
- Token.ASSIGN_SUB,
- Token.ASSIGN_MUL,
- Token.ASSIGN_DIV,
- Token.ASSIGN_MOD,
- Token.ASSIGN_TRUNC,
- Token.ASSIGN_SHR);
+ analyzeIn(element, "field = 1", 0);
+ analyzeIn(element, "staticField = 1", 0);
+ analyzeIn(element, "fieldInSuperclass = 1", 0);
+ analyzeIn(element, "staticFieldInSuperclass = 1", 0);
- for (Token op : compoundAssignmentOperators) {
- String expression;
- expression = String.format("o %s untyped", op.getSyntax());
- analyzeIn(cls, expression, 0);
- expression = String.format("s %s untyped", op.getSyntax());
- analyzeIn(cls, expression, 1);
- expression = String.format("o %s null", op.getSyntax());
- analyzeIn(cls, expression, 0);
- expression = String.format("s %s null", op.getSyntax());
- analyzeIn(cls, expression, 1);
- expression = String.format("o %s o", op.getSyntax());
- analyzeIn(cls, expression, 0);
- expression = String.format("s %s o", op.getSyntax());
- analyzeIn(cls, expression, 1);
- expression = String.format("o %s i", op.getSyntax());
- analyzeIn(cls, expression, 1);
- }
+ analyzeIn(element, "field = ''", 1);
+ analyzeIn(element, "staticField = ''", 1);
+ analyzeIn(element, "fieldInSuperclass = ''", 1);
+ analyzeIn(element, "staticFieldInSuperclass = ''", 1);
- analyzeIn(cls, "untyped is String", 0);
- analyzeIn(cls, "b = untyped is String", 0);
- analyzeIn(cls, "s = untyped is String", 1);
- analyzeIn(cls, "s is String", 0);
- analyzeIn(cls, "b = s is String", 0);
- analyzeIn(cls, "s = s is String", 1);
+ analyzeIn(element, "field.noSuchField", 1);
+ analyzeIn(element, "staticField.noSuchField", 1);
+ analyzeIn(element, "fieldInSuperclass.noSuchField", 1);
+ analyzeIn(element, "staticFieldInSuperclass.noSuchField", 1);
+ analyzeIn(element, "fieldInInterface.noSuchField", 1);
+ analyzeIn(element, "staticFieldInInterface.noSuchField", 1);
- analyzeIn(cls, "untyped is !String", 0);
- analyzeIn(cls, "b = untyped is !String", 0);
- analyzeIn(cls, "s = untyped is !String", 1);
- analyzeIn(cls, "s is !String", 0);
- analyzeIn(cls, "b = s is !String", 0);
- analyzeIn(cls, "s = s is !String", 1);
+ analyzeIn(element, "new ClassWithSupertypes()", 2); // Abstract class.
+ analyzeIn(element, "field = new ClassWithSupertypes().field", 1);
+ analyzeIn(element, "field = new ClassWithSupertypes().staticField", 2);
+ analyzeIn(element, "field = new ClassWithSupertypes().fieldInSuperclass", 1);
+ analyzeIn(element, "field = new ClassWithSupertypes().staticFieldInSuperclass", 2);
+ analyzeIn(element, "field = new ClassWithSupertypes().fieldInInterface", 1);
+ analyzeIn(element, "field = new ClassWithSupertypes().staticFieldInInterface", 2);
- analyzeFail("1 == !'s';", TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyzeIn(element, "new ClassWithSupertypes().field = 1", 1);
+ analyzeIn(element, "new ClassWithSupertypes().staticField = 1", 2);
+ analyzeIn(element, "new ClassWithSupertypes().fieldInSuperclass = 1", 1);
+ analyzeIn(element, "new ClassWithSupertypes().staticFieldInSuperclass = 1", 2);
+ // Enable this test when constness is propagated:
+ // analyzeIn(element, "new ClassWithSupertypes().fieldInInterface = 1", 1);
+ analyzeIn(element, "new ClassWithSupertypes().staticFieldInInterface = 1", 2);
}
- public void testBitOperators() {
- Map<String, ClassElement> source = loadSource(
- "class ClassWithBitops {",
- " num n;",
+ public void testFieldInitializers() {
+ Map<String, ClassElement> classes = loadSource(
+ "class Good {",
+ " String string;",
" int i;",
- " double d;",
- " ClassWithBitops o;",
- " num foo() { return 42; }",
- " int operator |(int arg) { return arg; }",
- " int operator &(int arg) { return arg; }",
- " int operator ^(int arg) { return arg; }",
- " int operator >>(int arg) { return arg; }",
- " int operator >>>(int arg) { return arg; }",
- " int operator <<(int arg) { return arg; }",
- " int operator ~() { return 1; }",
+ " Good() : string = '', i = 1;",
+ " Good.name() : string = null, i = null;",
+ " Good.untyped(x) : string = x, i = x;",
+ " Good.string(String s) : string = s, i = 0;",
+ "}",
+ "class Bad {",
+ " String string;",
+ " int i;",
+ " Bad() : string = 1, i = '';",
+ " Bad.string(String s) : string = s, i = s;",
"}");
- ClassElement cls = source.get("ClassWithBitops");
- analyzeClasses(source);
+ analyzeClass(classes.get("Good"), 0);
+ analyzeClass(classes.get("Bad"), 3);
+ }
- EnumSet<Token> operators = EnumSet.of(Token.BIT_AND,
- Token.BIT_OR,
- Token.BIT_XOR,
- Token.SHL,
- Token.SAR);
- for (Token operator : operators) {
- analyzeIn(cls, String.format("n %s n" , operator), 0);
- analyzeIn(cls, String.format("foo() %s i" , operator), 0);
- analyzeIn(cls, String.format("o %s i" , operator), 0);
- analyzeIn(cls, String.format("n = d %s i", operator), 1);
- analyzeIn(cls, String.format("d = o %s i", operator), 1);
- analyzeIn(cls, String.format("d = n %s i", operator), 1);
- analyzeIn(cls, String.format("n %s o" , operator), 1);
- }
+ public void testForEachStatement() {
+ Map<String, ClassElement> invalidReturnType = loadSource(
+ "class A {",
+ " Iterator<int> iterator() {}",
+ "}",
+ "class B {",
+ " main() { for (int i in new A()) {}}",
+ "}");
+ analyzeClasses(invalidReturnType);
+ }
- EnumSet<Token> assignOperators = EnumSet.of(Token.ASSIGN_BIT_AND,
- Token.ASSIGN_BIT_OR,
- Token.ASSIGN_BIT_XOR,
- Token.ASSIGN_SHL,
- Token.ASSIGN_SAR);
- for (Token operator : assignOperators) {
- analyzeIn(cls, String.format("n %s n" , operator), 0);
- analyzeIn(cls, String.format("n %s i" , operator), 0);
- analyzeIn(cls, String.format("d %s i", operator), 1);
- analyzeIn(cls, String.format("o %s i", operator), 1);
- analyzeIn(cls, String.format("n %s o" , operator), 1);
- }
+ public void testForEachStatement_Negative1() {
+ Map<String, ClassElement> fieldNotMethod = loadSource(
+ "class A {",
+ " int iterator;",
+ "}",
+ "class B {",
+ " main() { for (int i in new A()) {}}",
+ "}");
+ analyzeClasses(fieldNotMethod, TypeErrorCode.FOR_IN_WITH_ITERATOR_FIELD);
+ }
- analyzeIn(cls, "i = ~o", 0);
- analyzeIn(cls, "i = ~n", 0);
- analyzeIn(cls, "d = ~n", 1);
+ public void testForEachStatement_Negative2() {
+ Map<String, ClassElement> invalidReturnType = loadSource(
+ "class A {",
+ " int iterator() {}",
+ "}",
+ "class B {",
+ " main() { for (int i in new A()) {}}",
+ "}");
+ analyzeClasses(invalidReturnType, TypeErrorCode.FOR_IN_WITH_INVALID_ITERATOR_RETURN_TYPE);
+ }
+
+
+ public void testForStatement() {
+ analyze("for (;true;) {}");
+ analyze("for (;null;) {}");
+ analyzeFail("for (;0;) {}",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyzeFail("for (;'';) {}",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+
+ // Foreach tests
+ analyze("{ List<String> strings = ['1','2','3']; for (String s in strings) {} }");
+ analyzeFail("{ List<int> ints = [1,2,3]; for (String s in ints) {} }",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyzeFail("for (String s in true) {}", TypeErrorCode.INTERFACE_HAS_NO_METHOD_NAMED);
+ }
+
+ public void testFunctionObjectLiterals() {
+ analyze("{ bool b = foo() {}(); }");
+ analyze("{ int i = foo() {}(); }");
+ analyze("{ bool b = bool foo() { return null; }(); }");
+ analyze("{ int i = int foo() { return null; }(); }");
+ analyzeFail("{ int i = bool foo() { return null; }(); }",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyze("{ int i = Object _(Object x) { return x; }('fisk'); }");
+ analyzeFail("{ int i = String _(Object x) { return x; }(1); }",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyze("Function f = foo() {};");
+ }
+
+ public void testFunctionTypeAlias() {
+ Map<String, ClassElement> classes = loadSource(
+ "typedef void VoidFunction();",
+ "typedef String StringFunction();",
+ "typedef String IntToStringFunction(int i);",
+ "class Foo {",
+ " VoidFunction voidFunction;",
+ " StringFunction stringFunction;",
+ " IntToStringFunction intToStringFunction;",
+ " Foo foo;",
+ " String string;",
+ " int i;",
+ "}");
+ analyzeClasses(classes);
+ ClassElement foo = classes.get("Foo");
+ analyzeIn(foo, "voidFunction()", 0);
+ analyzeIn(foo, "voidFunction(1)", 1);
+ analyzeIn(foo, "this.voidFunction()", 0);
+ analyzeIn(foo, "this.voidFunction(1)", 1);
+ analyzeIn(foo, "foo.voidFunction()", 0);
+ analyzeIn(foo, "foo.voidFunction(1)", 1);
+ analyzeIn(foo, "(voidFunction)()", 0);
+ analyzeIn(foo, "(voidFunction)(1)", 1);
+ analyzeIn(foo, "(this.voidFunction)()", 0);
+ analyzeIn(foo, "(this.voidFunction)(1)", 1);
+ analyzeIn(foo, "(foo.voidFunction)()", 0);
+ analyzeIn(foo, "(foo.voidFunction)(1)", 1);
+
+ analyzeIn(foo, "string = stringFunction()", 0);
+ analyzeIn(foo, "i = stringFunction()", 1);
+ analyzeIn(foo, "string = this.stringFunction()", 0);
+ analyzeIn(foo, "i = this.stringFunction()", 1);
+ analyzeIn(foo, "string = foo.stringFunction()", 0);
+ analyzeIn(foo, "i = foo.stringFunction()", 1);
+ analyzeIn(foo, "string = (stringFunction)()", 0);
+ analyzeIn(foo, "i = (stringFunction)()", 1);
+ analyzeIn(foo, "string = (this.stringFunction)()", 0);
+ analyzeIn(foo, "i = (this.stringFunction)()", 1);
+ analyzeIn(foo, "string = (foo.stringFunction)()", 0);
+ analyzeIn(foo, "i = (foo.stringFunction)()", 1);
+
+ analyzeIn(foo, "voidFunction = stringFunction", 0);
+ analyzeIn(foo, "stringFunction = intToStringFunction", 1);
+ analyzeIn(foo, "stringFunction = String foo() { return ''; }", 0);
+ analyzeIn(foo, "intToStringFunction = String foo() { return ''; }", 1);
+ }
+
+ public void testFunctionTypes() {
+ checkFunctionStatement("String foo() {};", "() -> String");
+ checkFunctionStatement("Object foo() {};", "() -> Object");
+ checkFunctionStatement("String foo(int i, bool b) {};", "(int, bool) -> String");
+ }
+
+ public void testGetAllSupertypes()
+ throws CyclicDeclarationException, DuplicatedInterfaceException {
+ Map<String, ClassElement> classes = loadSource(
+ "class A extends B<String> {",
+ "}",
+ "class B<T> extends C<G<T>> implements I<int>, I1<T> {",
+ "}",
+ "class C<U> {",
+ "}",
+ "interface I<S> extends I2<bool> {",
+ "}",
+ "class G<V> {",
+ "}",
+ "interface I1<W> {",
+ "}",
+ "interface I2<X> {",
+ "}",
+ "class D implements I2<int> {",
+ "}",
+ "class E extends D implements I2<int> {",
+ "}");
+ analyzeClasses(classes);
+ assertEquals("[]", object.getAllSupertypes().toString());
+ assertEquals("[I<int>, I1<String>, I2<bool>, B<String>, C<G<String>>, Object]",
+ classes.get("A").getAllSupertypes().toString());
+ assertEquals("[I<int>, I1<B.T>, I2<bool>, C<G<B.T>>, Object]",
+ classes.get("B").getAllSupertypes().toString());
+ assertEquals("[Object]", classes.get("C").getAllSupertypes().toString());
+ assertEquals("[I2<bool>, Object]", classes.get("I").getAllSupertypes().toString());
+ assertEquals("[Object]", classes.get("G").getAllSupertypes().toString());
+ assertEquals("[Object]", classes.get("I1").getAllSupertypes().toString());
+ assertEquals("[Object]", classes.get("I2").getAllSupertypes().toString());
+ assertEquals("[I2<int>, Object]", classes.get("D").getAllSupertypes().toString());
+ assertEquals("[I2<int>, D, Object]", classes.get("E").getAllSupertypes().toString());
+ }
+
+ public void testIdentifiers() {
+ analyze("{ int i; i = 2; }");
+ analyze("{ int j, k; j = 1; k = 3; }");
+ analyzeFail("{ int i; i = 'string'; }", TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyzeFail("{ int j, k; k = 'string'; }",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyzeFail("{ int j, k; j = 'string'; }",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ }
+
+ public void testIfStatement() {
+ analyze("if (true) {}");
+ analyze("if (null) {}");
+ analyzeFail("if (0) {}",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyzeFail("if ('') {}",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyzeFail("{ int i = 27; if (true) { i = 2.7; } else {} }",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyzeFail("{ int i = 27; if (true) {} else { i = 2.7; } }",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ }
+
+ public void testImplementsAndOverrides() {
+ analyzeClasses(loadSource(
+ "interface Interface {",
+ " void foo(x);",
+ " void bar();",
+ "}",
+ // Abstract class not reported until first instantiation.
+ "class Class implements Interface {",
+ " Class() {}",
+ " String bar() { return null; }",
+ "}",
+ // Abstract class not reported until first instantiation.
+ "class SubClass extends Class {",
+ " SubClass() : super() {}",
+ " Object bar() { return null; }",
+ "}",
+ "class SubSubClass extends Class {",
+ " num bar() { return null; }", // CANNOT_OVERRIDE_METHOD_NOT_SUBTYPE
+ " void foo() {}", // CANNOT_OVERRIDE_METHOD_NOT_SUBTYPE
+ "}",
+ "class Usage {",
+ " m() {",
+ " new Class();", // CANNOT_INSTATIATE_ABSTRACT_CLASS
+ // ABSTRACT_CLASS.
+ " new Class();", // CANNOT_INSTATIATE_ABSTRACT_CLASS.
+ " new SubClass();", // CANNOT_INSTATIATE_ABSTRACT_CLASS
+ //ABSTRACT_CLASS.
+ " }",
+ "}"),
+ TypeErrorCode.CANNOT_OVERRIDE_METHOD_NOT_SUBTYPE,
+ TypeErrorCode.CANNOT_OVERRIDE_METHOD_NOT_SUBTYPE,
+ TypeErrorCode.CANNOT_INSTATIATE_ABSTRACT_CLASS,
+ TypeErrorCode.ABSTRACT_CLASS,
+ TypeErrorCode.CANNOT_INSTATIATE_ABSTRACT_CLASS,
+ TypeErrorCode.CANNOT_INSTATIATE_ABSTRACT_CLASS,
+ TypeErrorCode.ABSTRACT_CLASS);
+ }
+
+ public void testImplementsAndOverrides2() {
+ analyzeClasses(loadSource(
+ "interface Interface {",
+ " void foo(x);",
+ "}",
+ // Abstract class not reported until first instantiation.
+ "class Class implements Interface {",
+ " Class() {}",
+ " void foo() {}", // CANNOT_OVERRIDE_METHOD_NOT_SUBTYPE
+ "}"),
+ TypeErrorCode.CANNOT_OVERRIDE_METHOD_NOT_SUBTYPE);
+ }
+
+ public void testInitializedFields() {
+ Map<String, ClassElement> classes = loadSource(
+ "class GoodField {",
+ " static final int i = 1;",
+ "}");
+ analyzeClass(classes.get("GoodField"), 0);
+
+ // Note, the TypeAnalyzer doesn't get a chance
+ // to get its hands on bad initializers anymore
+ // due to type checking in CompileTimeConstVisitor.
+ }
+
+ public void testInitializedLocals() {
+ analyze("void f([int x = 1]) {}");
+ analyzeFail("void f([int x = '']) {}", TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+
+ analyze("{ int x = 1; }");
+ analyzeFail("{ int x = ''; }", TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ }
+
+ public void testInitializers() {
+ analyze("int i = 1;");
+ analyze("double d1 = .0;");
+ analyze("double d2 = 1.0;");
+ analyze("int x = null;");
+ }
+
+ public void testLabels() {
+ // Labels should be inside a function or method to be used
+
+ // break
+ analyze("foo() { L: for (;true;) { break L; } }");
+ analyze("foo() { int x; List<int> c; L: for (x in c) { break L; } }");
+ analyze("foo() { List<int> c; L: for (var x in c) { break L; } }");
+ analyze("foo() { L: while (true) { break L; } }");
+ analyze("foo() { L: do { break L; } while (true); }");
+
+ analyze("foo() { L: for (;true;) { for (;true;) { break L; } } }");
+ analyze("foo() { int x; List<int> c; L: for (x in c) { for (;true;) { break L; } } }");
+ analyze("foo() { List<int> c; L: for (var x in c) { for (;true;) { break L; } } }");
+ analyze("foo() { L: while (true) { for (;true;) { break L; } } }");
+ analyze("foo() { L: do { for (;true;) { break L; } } while (true); }");
+
+ // continue
+ analyze("foo() { L: for (;true;) { continue L; } }");
+ analyze("foo() { int x; List<int> c; L: for (x in c) { continue L; } }");
+ analyze("foo() { List<int> c; L: for (var x in c) { continue L; } }");
+ analyze("foo() { L: do { continue L; } while (true); }");
+
+ analyze("foo() { L: for (;true;) { for (;true;) { continue L; } } }");
+ analyze(
+ "foo() { int x; List<int> c; L: for (x in c) { for (;true;) { continue L; } } }");
+ analyze("foo() { List<int> c; L: for (var x in c) { for (;true;) { continue L; } } }");
+ analyze("foo() { L: while (true) { for (;true;) { continue L; } } }");
+ analyze("foo() { L: do { for (;true;) { continue L; } } while (true); }");
+
+ // corner cases
+ analyze("foo() { L: break L; }");
+
+ // TODO(zundel): Not type errors, but warnings.
+ analyze("foo() { L: for (;true;) { } }");
+ analyze("foo() { while (true) { L: var a; } }");
+ }
+
+ public void testLiterals() {
+ checkSimpleType(intElement.getType(), "1");
+ checkSimpleType(doubleElement.getType(), ".0");
+ checkSimpleType(doubleElement.getType(), "1.0");
+ checkSimpleType(bool.getType(), "true");
+ checkSimpleType(bool.getType(), "false");
+ checkSimpleType(string.getType(), "'fisk'");
+ checkSimpleType(string.getType(), "'f${null}sk'");
+ }
+
+ public void testLoadInterfaces() {
+ loadFile("interfaces.dart");
+ ClassElement superElement = coreElements.get("Super");
+ assertNotNull("no element for Super", superElement);
+ assertEquals(object.getType(), superElement.getSupertype());
+ assertEquals(0, superElement.getInterfaces().size());
+ ClassElement sub = coreElements.get("Sub");
+ assertNotNull("no element for Sub", sub);
+ assertEquals(object.getType(), sub.getSupertype());
+ assertEquals(1, sub.getInterfaces().size());
+ assertEquals(superElement, sub.getInterfaces().get(0).getElement());
+ InterfaceType superString = itype(superElement, itype(string));
+ InterfaceType subString = itype(sub, itype(string));
+ Types types = getTypes();
+ assertEquals("Super<String>", String.valueOf(types.asInstanceOf(superString, superElement)));
+ assertEquals("Super<String>", String.valueOf(types.asInstanceOf(subString, superElement)));
+ assertEquals("Sub<String>", String.valueOf(types.asInstanceOf(subString, sub)));
+ assertNull(types.asInstanceOf(superString, sub));
+ }
+
+
+ public void testMapLiteral() {
+ analyze("{ var x = {\"key\": 42}; }");
+ analyze("{ var x = {'key': 42}; }");
+ analyze("{ var x = <String, num>{'key': 42}; }");
+ analyze("{ var x = <String, int>{'key': 42}; }");
+ analyze("{ var x = <String, num>{'key': 0.42}; }");
+ analyze("{ var x = <Object, num>{'key': 42}; }");
+ analyzeFail("{ var x = <String, int>{'key': 0.42}; }",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyzeFail("{ int i; var x = {'key': i = 0.42}; }",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyze("{ var x = const {\"key\": 42}; }");
+ analyze("{ var x = const {'key': 42}; }");
+ analyze("{ var x = const <String, num>{'key': 42}; }");
+ analyze("{ var x = const <String, int>{'key': 42}; }");
+ analyze("{ var x = const <String, num>{'key': 0.42}; }");
+ analyze("{ var x = const <Object, num>{'key': 42}; }");
+ analyzeFail("{ var x = const <String, int>{'key': 0.42}; }",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyzeFail("{ int i; var x = const {'key': i = 0.42}; }",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyzeFail("{var x = const <num, num>{}; }",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ }
+
+ public void testMethodInvocationArgumentCount() {
+ loadFile("class_with_methods.dart");
+ final String header = "{ ClassWithMethods c; ";
+
+ analyzeFail(header + "c.untypedNoArgumentMethod(1); }",
+ TypeErrorCode.EXTRA_ARGUMENT);
+ analyzeFail(header + "c.untypedOneArgumentMethod(); }",
+ TypeErrorCode.MISSING_ARGUMENT);
+ analyzeFail(header + "c.untypedOneArgumentMethod(1, 1); }",
+ TypeErrorCode.EXTRA_ARGUMENT);
+ analyzeFail(header + "c.untypedTwoArgumentMethod(); }",
+ TypeErrorCode.MISSING_ARGUMENT);
+ analyzeFail(header + "c.untypedTwoArgumentMethod(1, 2, 3); }",
+ TypeErrorCode.EXTRA_ARGUMENT);
+ analyzeFail(header + "c.intNoArgumentMethod(1); }",
+ TypeErrorCode.EXTRA_ARGUMENT);
+ analyzeFail(header + "c.intOneArgumentMethod(); }",
+ TypeErrorCode.MISSING_ARGUMENT);
+ analyzeFail(header + "c.intOneArgumentMethod(1, 1); }",
+ TypeErrorCode.EXTRA_ARGUMENT);
+ analyzeFail(header + "c.intTwoArgumentMethod(); }",
+ TypeErrorCode.MISSING_ARGUMENT);
+ analyzeFail(header + "c.intTwoArgumentMethod(1, 2, 3); }",
+ TypeErrorCode.EXTRA_ARGUMENT);
+ analyze(header + "c.untypedField(); }");
}
+ public void testMethodInvocations() {
+ loadFile("class_with_methods.dart");
+ final String header = "{ ClassWithMethods c; int i, j; ";
- public void testFunctionObjectLiterals() {
- analyze("{ bool b = foo() {}(); }");
- analyze("{ int i = foo() {}(); }");
- analyze("{ bool b = bool foo() { return null; }(); }");
- analyze("{ int i = int foo() { return null; }(); }");
- analyzeFail("{ int i = bool foo() { return null; }(); }",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyze("{ int i = Object _(Object x) { return x; }('fisk'); }");
- analyzeFail("{ int i = String _(Object x) { return x; }(1); }",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyze("Function f = foo() {};");
- }
+ analyze(header + "int k = c.untypedNoArgumentMethod(); }");
+ analyze(header + "ClassWithMethods x = c.untypedNoArgumentMethod(); }");
- public void testAssert() {
- analyze("assert(true);");
- analyze("assert(false);");
- analyzeFail("assert('message');",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyze("assert(null);");
- analyzeFail("assert(1);",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyze("assert(foo() {});");
- analyze("assert(bool foo() {});");
- analyze("assert(Object foo() {});");
- analyzeFail("assert(String foo() {});",
+ analyze(header + "int k = c.untypedOneArgumentMethod(c); }");
+ analyze(header + "ClassWithMethods x = c.untypedOneArgumentMethod(1); }");
+ analyze(header + "int k = c.untypedOneArgumentMethod('string'); }");
+ analyze(header + "int k = c.untypedOneArgumentMethod(i); }");
+
+ analyze(header + "int k = c.untypedTwoArgumentMethod(1, 'string'); }");
+ analyze(header + "int k = c.untypedTwoArgumentMethod(i, j); }");
+ analyze(header + "ClassWithMethods x = c.untypedTwoArgumentMethod(i, c); }");
+
+ analyze(header + "int k = c.intNoArgumentMethod(); }");
+ analyzeFail(header + "ClassWithMethods x = c.intNoArgumentMethod(); }",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+
+ analyzeFail(header + "int k = c.intOneArgumentMethod(c); }",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyzeFail(header + "ClassWithMethods x = c.intOneArgumentMethod(1); }",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyzeFail(header + "int k = c.intOneArgumentMethod('string'); }",
TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- }
+ analyze(header + "int k = c.intOneArgumentMethod(i); }");
- public void testReturn() {
- analyzeFail(returnWithType("int", "'string'"),
+ analyzeFail(header + "int k = c.intTwoArgumentMethod(1, 'string'); }",
TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyze(returnWithType("", "'string'"));
- analyze(returnWithType("Object", "'string'"));
- analyze(returnWithType("String", "'string'"));
- analyze(returnWithType("String", null));
- analyze(returnWithType("int", null));
- analyze(returnWithType("void", ""));
- analyzeFail(returnWithType("void", 1), TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyze(returnWithType("void", null));
- analyzeFail(returnWithType("String", ""), TypeErrorCode.MISSING_RETURN_VALUE);
- analyze("String foo() {};"); // Should probably fail, http://b/4484060.
+ analyze(header + "int k = c.intTwoArgumentMethod(i, j); }");
+ analyzeFail(header + "ClassWithMethods x = c.intTwoArgumentMethod(i, j); }",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
}
public void testNamedFunctionTypeAlias() {
@@ -506,110 +816,89 @@ public class TypeAnalyzerTest extends TypeAnalyzerTestCase {
analyze("VoidFunction f = foo() {};");
}
- public void testUnresolved() {
- ClassElement element = loadClass("class_with_supertypes.dart", "ClassWithSupertypes");
- analyzeIn(element, "null", 0);
- analyzeIn(element, "noSuchField", 1);
- analyzeIn(element, "noSuchMethod()", 1);
- analyzeIn(element, "method()", 0);
- analyzeIn(element, "field", 0);
- analyzeIn(element, "this.noSuchField", 1);
- analyzeIn(element, "this.noSuchMethod()", 1);
- analyzeIn(element, "this.method()", 0);
- analyzeIn(element, "this.field", 0);
- analyzeIn(element, "staticMethod()", 0);
- analyzeIn(element, "staticField", 0);
- analyzeIn(element, "this.staticMethod()", 1);
- analyzeIn(element, "this.staticField", 1);
- analyzeIn(element, "ClassWithSupertypes.staticMethod()", 0);
- analyzeIn(element, "ClassWithSupertypes.staticField", 0);
- analyzeIn(element, "methodInSuperclass()", 0);
- analyzeIn(element, "fieldInSuperclass", 0);
- analyzeIn(element, "staticMethodInSuperclass()", 0);
- analyzeIn(element, "staticFieldInSuperclass", 0);
- analyzeIn(element, "this.methodInSuperclass()", 0);
- analyzeIn(element, "this.fieldInSuperclass", 0);
- analyzeIn(element, "this.staticMethodInSuperclass()", 1);
- analyzeIn(element, "this.staticFieldInSuperclass", 1);
- analyzeIn(element, "Superclass.staticMethodInSuperclass()", 0);
- analyzeIn(element, "Superclass.staticFieldInSuperclass", 0);
- analyzeIn(element, "methodInInterface()", 0);
- analyzeIn(element, "fieldInInterface", 0);
- analyzeIn(element, "this.methodInInterface()", 0);
- analyzeIn(element, "this.fieldInInterface", 0);
- analyzeIn(element, "staticFieldInInterface", 0);
- analyzeIn(element, "Interface.staticFieldInInterface", 0);
- analyzeIn(element, "this.staticFieldInInterface", 1);
- }
-
- public void testTypeVariables() {
- ClassElement cls = loadFile("class_with_type_parameter.dart").get("ClassWithTypeParameter");
- assertNotNull("unable to locate ClassWithTypeParameter", cls);
- analyzeIn(cls, "aField = tField", 0);
- analyzeIn(cls, "bField = tField", 0);
- analyzeIn(cls, "tField = aField", 0);
- analyzeIn(cls, "tField = bField", 0);
- analyzeIn(cls, "tField = null", 0);
- analyzeIn(cls, "tField = 1", 1);
- analyzeIn(cls, "tField = ''", 1);
- analyzeIn(cls, "tField = true", 1);
-
- analyzeIn(cls, "foo() { A a = null; T t = a; }()", 0);
- analyzeIn(cls, "foo() { B b = null; T t = b; }()", 0);
- analyzeIn(cls, "foo() { T t = null; A a = t; }()", 0);
- analyzeIn(cls, "foo() { T t = null; B b = t; }()", 0);
- analyzeIn(cls, "foo() { T t = 1; }()", 1);
- analyzeIn(cls, "foo() { T t = ''; }()", 1);
- analyzeIn(cls, "foo() { T t = true; }()", 1);
- }
+ public void testNewExpression() {
+ analyzeClasses(loadSource(
+ "class Foo {",
+ " Foo(int x) {}",
+ " Foo.foo() {}",
+ " Foo.bar([int i = null]) {}",
+ "}",
+ "interface Bar<T> factory Baz {",
+ " Bar.make();",
+ "}",
+ "class Baz {",
+ " factory Bar<S>.make(S x) { return null; }",
+ "}"));
- public void testFieldAccess() {
- ClassElement element = loadFile("class_with_supertypes.dart").get("ClassWithSupertypes");
- assertNotNull("unable to locate ClassWithSupertypes", element);
- analyzeIn(element, "field = 1", 0);
- analyzeIn(element, "staticField = 1", 0);
- analyzeIn(element, "fieldInSuperclass = 1", 0);
- analyzeIn(element, "staticFieldInSuperclass = 1", 0);
+ analyze("Foo x = new Foo(0);");
+ analyzeFail("Foo x = new Foo();", TypeErrorCode.MISSING_ARGUMENT);
+ analyzeFail("Foo x = new Foo('');", TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyzeFail("Foo x = new Foo(0, null);", TypeErrorCode.EXTRA_ARGUMENT);
- analyzeIn(element, "field = field", 0);
- analyzeIn(element, "field = staticField", 0);
- analyzeIn(element, "field = fieldInSuperclass", 0);
- analyzeIn(element, "field = staticFieldInSuperclass", 0);
- analyzeIn(element, "field = fieldInInterface", 0);
- analyzeIn(element, "field = staticFieldInInterface", 0);
+ analyze("Foo x = new Foo.foo();");
+ analyzeFail("Foo x = new Foo.foo(null);", TypeErrorCode.EXTRA_ARGUMENT);
- analyzeIn(element, "field = 1", 0);
- analyzeIn(element, "staticField = 1", 0);
- analyzeIn(element, "fieldInSuperclass = 1", 0);
- analyzeIn(element, "staticFieldInSuperclass = 1", 0);
+ analyze("Foo x = new Foo.bar();");
+ analyze("Foo x = new Foo.bar(0);");
+ analyzeFail("Foo x = new Foo.bar('');", TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyzeFail("Foo x = new Foo.bar(0, null);", TypeErrorCode.EXTRA_ARGUMENT);
- analyzeIn(element, "field = ''", 1);
- analyzeIn(element, "staticField = ''", 1);
- analyzeIn(element, "fieldInSuperclass = ''", 1);
- analyzeIn(element, "staticFieldInSuperclass = ''", 1);
+ analyze("Bar<String> x = new Bar<String>.make('');");
+ }
- analyzeIn(element, "field.noSuchField", 1);
- analyzeIn(element, "staticField.noSuchField", 1);
- analyzeIn(element, "fieldInSuperclass.noSuchField", 1);
- analyzeIn(element, "staticFieldInSuperclass.noSuchField", 1);
- analyzeIn(element, "fieldInInterface.noSuchField", 1);
- analyzeIn(element, "staticFieldInInterface.noSuchField", 1);
+ public void testOddStuff() {
+ Map<String, ClassElement> classes = analyzeClasses(loadSource(
+ "class Class {",
+ " Class() {}",
+ " var field;",
+ " void m() {}",
+ " static void f() {}",
+ " static g(int i) {}",
+ "}"));
+ ClassElement cls = classes.get("Class");
+ analyzeIn(cls, "m().foo()", 1);
+ analyzeIn(cls, "m().x", 1);
+ analyzeIn(cls, "m()", 0);
+ analyzeIn(cls, "(m)().foo()", 1);
+ analyzeIn(cls, "(m)().x", 1);
+ analyzeIn(cls, "(m)()", 0);
+ analyzeIn(cls, "field = m()", 1);
+ analyzeIn(cls, "field = Class.f()", 1);
+ analyzeIn(cls, "field = (Class.f)()", 1);
+ analyzeIn(cls, "Class.f()", 0);
+ analyzeIn(cls, "(Class.f)()", 0);
+ analyzeIn(cls, "field = Class.g('x')", 1);
+ analyzeIn(cls, "field = (Class.g)('x')", 1);
+ analyzeIn(cls, "field = Class.g(0)", 0);
+ analyzeIn(cls, "field = (Class.g)(0)", 0);
+ analyzeFail("fisk: while (true) fisk++;", TypeErrorCode.CANNOT_BE_RESOLVED);
+ analyzeFail("new Class().m().x;", TypeErrorCode.VOID);
+ analyzeFail("(new Class().m)().x;", TypeErrorCode.VOID);
+ }
- analyzeIn(element, "new ClassWithSupertypes()", 2); // Abstract class.
- analyzeIn(element, "field = new ClassWithSupertypes().field", 1);
- analyzeIn(element, "field = new ClassWithSupertypes().staticField", 2);
- analyzeIn(element, "field = new ClassWithSupertypes().fieldInSuperclass", 1);
- analyzeIn(element, "field = new ClassWithSupertypes().staticFieldInSuperclass", 2);
- analyzeIn(element, "field = new ClassWithSupertypes().fieldInInterface", 1);
- analyzeIn(element, "field = new ClassWithSupertypes().staticFieldInInterface", 2);
+ public void testParameterAccess() {
+ analyze("{ f(int x) { x = 1; } }");
+ analyzeFail("{ f(String x) { x = 1; } }",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyze("{ f(int x, int y) { x = y; } }");
+ analyzeFail("{ f(String x, int y) { x = y; } }",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyze("{ f(x, int y) { x = y; } }");
+ analyze("{ f(x, int y) { x = y; } }");
+ analyzeFail("{ f(String x) { x = 1;} }",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ }
- analyzeIn(element, "new ClassWithSupertypes().field = 1", 1);
- analyzeIn(element, "new ClassWithSupertypes().staticField = 1", 2);
- analyzeIn(element, "new ClassWithSupertypes().fieldInSuperclass = 1", 1);
- analyzeIn(element, "new ClassWithSupertypes().staticFieldInSuperclass = 1", 2);
- // Enable this test when constness is propagated:
- // analyzeIn(element, "new ClassWithSupertypes().fieldInInterface = 1", 1);
- analyzeIn(element, "new ClassWithSupertypes().staticFieldInInterface = 1", 2);
+ public void testParameterInitializers() {
+ Map<String, ClassElement> classes = loadSource(
+ "class C1 { int i; C1(this.i) {} }",
+ "class C2 { String s; C2(int this.s) {} }",
+ "class C3 { int i; C3(double this.i) {} }",
+ "class C4 { int i; C4(num this.i) {} }");
+ analyzeClass(classes.get("C1"), 0);
+ analyzeClass(classes.get("C2"), 1);
+ analyzeClass(classes.get("C3"), 1);
+ analyzeClass(classes.get("C4"), 0);
}
public void testPropertyAccess() {
@@ -632,114 +921,141 @@ public class TypeAnalyzerTest extends TypeAnalyzerTestCase {
}
}
- public void testParameterAccess() {
- analyze("{ f(int x) { x = 1; } }");
- analyzeFail("{ f(String x) { x = 1; } }",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyze("{ f(int x, int y) { x = y; } }");
- analyzeFail("{ f(String x, int y) { x = y; } }",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyze("{ f(x, int y) { x = y; } }");
- analyze("{ f(x, int y) { x = y; } }");
- analyzeFail("{ f(String x) { x = 1;} }",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ public void testRawTypes() {
+ loadFile("interfaces.dart");
+
+ analyze("{ Sub s; }");
+ analyze("{ var s = new Sub(); }");
+ analyze("{ Sub s = new Sub(); }");
+ analyze("{ Sub<String> s = new Sub(); }");
+ analyze("{ Sub<String> s; }");
+ analyze("{ var s = new Sub<String>(); }");
+ analyze("{ Sub s = new Sub<String>(); }");
+ analyze("{ Sub<String> s = new Sub<String>(); }");
}
- public void testConditionalExpression() {
- analyze("true ? 1 : 2;");
- analyze("null ? 1 : 2;");
- analyzeFail("0 ? 1 : 2;",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyzeFail("'' ? 1 : 2;",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyzeFail("{ int i; true ? i = 2.7 : 2; }",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyzeFail("{ int i; true ? 2 : i = 2.7; }",
+ public void testReturn() {
+ analyzeFail(returnWithType("int", "'string'"),
TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyze("{ int i; i = true ? 2.7 : 2; }");
+ analyze(returnWithType("", "'string'"));
+ analyze(returnWithType("Object", "'string'"));
+ analyze(returnWithType("String", "'string'"));
+ analyze(returnWithType("String", null));
+ analyze(returnWithType("int", null));
+ analyze(returnWithType("void", ""));
+ analyzeFail(returnWithType("void", 1), TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyze(returnWithType("void", null));
+ analyzeFail(returnWithType("String", ""), TypeErrorCode.MISSING_RETURN_VALUE);
+ analyze("String foo() {};"); // Should probably fail, http://b/4484060.
}
- public void testDoWhileStatement() {
- analyze("do {} while (true);");
- analyze("do {} while (null);");
- analyzeFail("do {} while (0);",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyzeFail("do {} while ('');",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyzeFail("do { int i = 0.5; } while (true);",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyzeFail("do { int i = 0.5; } while (null);",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- }
+ public void testSuper() {
+ ClassElement sub = loadClass("covariant_class.dart", "Sub");
+ checkAssignIn(sub, "B", "field", 0);
+ checkAssignIn(sub, "C", "field", 1);
+ checkAssignIn(sub, "D", "field", 1);
- public void testForStatement() {
- analyze("for (;true;) {}");
- analyze("for (;null;) {}");
- analyzeFail("for (;0;) {}",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyzeFail("for (;'';) {}",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ checkAssignIn(sub, "B", "super.field", 0);
+ checkAssignIn(sub, "C", "super.field", 0);
+ checkAssignIn(sub, "D", "super.field", 1);
- // Foreach tests
- analyze("{ List<String> strings = ['1','2','3']; for (String s in strings) {} }");
- analyzeFail("{ List<int> ints = [1,2,3]; for (String s in ints) {} }",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyzeFail("for (String s in true) {}", TypeErrorCode.INTERFACE_HAS_NO_METHOD_NAMED);
- }
+ checkAssignIn(sub, "B", "accessor", 0);
+ checkAssignIn(sub, "C", "accessor", 1);
+ checkAssignIn(sub, "D", "accessor", 1);
- public void testForEachStatement() {
- Map<String, ClassElement> invalidReturnType = loadSource(
- "class A {",
- " Iterator<int> iterator() {}",
- "}",
- "class B {",
- " main() { for (int i in new A()) {}}",
- "}");
- analyzeClasses(invalidReturnType);
- }
+ checkAssignIn(sub, "B", "super.accessor", 0);
+ checkAssignIn(sub, "C", "super.accessor", 0);
+ checkAssignIn(sub, "D", "super.accessor", 1);
- public void testForEachStatement_Negative1() {
- Map<String, ClassElement> fieldNotMethod = loadSource(
- "class A {",
- " int iterator;",
- "}",
- "class B {",
- " main() { for (int i in new A()) {}}",
- "}");
- analyzeClasses(fieldNotMethod, TypeErrorCode.FOR_IN_WITH_ITERATOR_FIELD);
+ analyzeIn(sub, "accessor = b", 0);
+ analyzeIn(sub, "accessor = c", 1);
+ analyzeIn(sub, "accessor = d", 1);
+
+ analyzeIn(sub, "super.accessor = b", 0);
+ analyzeIn(sub, "super.accessor = c", 0);
+ analyzeIn(sub, "super.accessor = d", 1);
+
+ checkAssignIn(sub, "B", "method()", 0);
+ checkAssignIn(sub, "C", "method()", 1);
+ checkAssignIn(sub, "D", "method()", 1);
+
+ checkAssignIn(sub, "B", "super.untypedMethod()", 0);
+ checkAssignIn(sub, "C", "super.untypedMethod()", 0);
+ checkAssignIn(sub, "D", "super.untypedMethod()", 0);
+
+ checkAssignIn(sub, "B", "super.untypedField", 0);
+ checkAssignIn(sub, "C", "super.untypedField", 0);
+ checkAssignIn(sub, "D", "super.untypedField", 0);
+
+ checkAssignIn(sub, "B", "super.untypedAccessor", 0);
+ checkAssignIn(sub, "C", "super.untypedAccessor", 0);
+ checkAssignIn(sub, "D", "super.untypedAccessor", 0);
+
+ analyzeIn(sub, "super.untypedAccessor = b", 0);
+ analyzeIn(sub, "super.untypedAccessor = c", 0);
+ analyzeIn(sub, "super.untypedAccessor = d", 0);
+
+ checkAssignIn(sub, "B", "super.untypedMethod()", 0);
+ checkAssignIn(sub, "C", "super.untypedMethod()", 0);
+ checkAssignIn(sub, "D", "super.untypedMethod()", 0);
}
- public void testForEachStatement_Negative2() {
- Map<String, ClassElement> invalidReturnType = loadSource(
+ public void testSuperConstructorInvocation() {
+ Map<String, ClassElement> classes = loadSource(
+ "class Super {",
+ " Super(int x) {}",
+ " Super.foo() {}",
+ " Super.bar([int i = null]) {}",
+ "}",
+ "class BadSub extends Super {",
+ " BadSub() : super('x') {}",
+ " BadSub.foo() : super.foo('x') {}",
+ " BadSub.bar() : super() {}",
+ " BadSub.baz() : super.foo(null) {}",
+ " BadSub.fisk() : super.bar('') {}",
+ " BadSub.hest() : super.bar(1, 2) {}",
+ "}",
+ "class NullSub extends Super {",
+ " NullSub() : super(null) {}",
+ " NullSub.foo() : super.bar(null) {}",
+ " NullSub.bar() : super.bar() {}",
+ "}",
+ "class IntSub extends Super {",
+ " IntSub() : super(1) {}",
+ " IntSub.foo() : super.bar(1) {}",
+ "}",
+ // The following works fine, but was claimed to be a bug:
"class A {",
- " int iterator() {}",
+ " int value;",
+ " A([this.value = 3]) {}",
"}",
- "class B {",
- " main() { for (int i in new A()) {}}",
+ "class B extends A {",
+ " B() : super() {}",
"}");
- analyzeClasses(invalidReturnType, TypeErrorCode.FOR_IN_WITH_INVALID_ITERATOR_RETURN_TYPE);
+ analyzeClass(classes.get("Super"), 0);
+ analyzeClass(classes.get("BadSub"), 6);
+ analyzeClass(classes.get("NullSub"), 0);
+ analyzeClass(classes.get("IntSub"), 0);
+ analyzeClass(classes.get("A"), 0);
+ analyzeClass(classes.get("B"), 0);
}
-
- public void testIfStatement() {
- analyze("if (true) {}");
- analyze("if (null) {}");
- analyzeFail("if (0) {}",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyzeFail("if ('') {}",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyzeFail("{ int i = 27; if (true) { i = 2.7; } else {} }",
+ public void testSuperInterfaces() {
+ // If this test is failing, first debug any failures in testLoadInterfaces.
+ loadFile("interfaces.dart");
+ analyze("Super<String> s = new Sub<String>();");
+ analyze("Super<Object> o = new Sub<String>();");
+ analyzeFail("Super<String> f1 = new Sub<int>();",
TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyzeFail("{ int i = 27; if (true) {} else { i = 2.7; } }",
+ analyzeFail("Sub<String> f2 = new Sub<int>();",
TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
}
- public void testWhileStatement() {
- analyze("while (true) {}");
- analyze("while (null) {}");
- analyzeFail("while (0) {}",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyzeFail("while ('') {}",
+ public void testSwitch() {
+ analyze("{ int i = 27; switch(i) { case i: break; } }");
+ analyze("{ num i = 27; switch(i) { case i: break; } }");
+ analyze("{ switch(true) { case 1: break; case 'foo': break; }}");
+ analyzeFail("{ int i = 27; switch(true) { case false: i = 2.7; }}",
TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
}
@@ -757,39 +1073,98 @@ public class TypeAnalyzerTest extends TypeAnalyzerTestCase {
analyzeIn(subclass, "() { Interface x = this; }", 0);
}
- public void testMapLiteral() {
- analyze("{ var x = {\"key\": 42}; }");
- analyze("{ var x = {'key': 42}; }");
- analyze("{ var x = <String, num>{'key': 42}; }");
- analyze("{ var x = <String, int>{'key': 42}; }");
- analyze("{ var x = <String, num>{'key': 0.42}; }");
- analyze("{ var x = <Object, num>{'key': 42}; }");
- analyzeFail("{ var x = <String, int>{'key': 0.42}; }",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyzeFail("{ int i; var x = {'key': i = 0.42}; }",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyze("{ var x = const {\"key\": 42}; }");
- analyze("{ var x = const {'key': 42}; }");
- analyze("{ var x = const <String, num>{'key': 42}; }");
- analyze("{ var x = const <String, int>{'key': 42}; }");
- analyze("{ var x = const <String, num>{'key': 0.42}; }");
- analyze("{ var x = const <Object, num>{'key': 42}; }");
- analyzeFail("{ var x = const <String, int>{'key': 0.42}; }",
+ public void testTryCatchFinally() {
+ analyze("try { } catch (var _) { } finally { }");
+ analyzeFail("try { int i = 4.2; } catch (var _) { } finally { }",
TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyzeFail("{ int i; var x = const {'key': i = 0.42}; }",
+ analyzeFail("try { } catch (var _) { int i = 4.2; } finally { }",
TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyzeFail("{var x = const <num, num>{}; }",
+ analyzeFail("try { } catch (var _) { } finally { int i = 4.2; }",
TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
}
- public void testTryCatchFinally() {
- analyze("try { } catch (var _) { } finally { }");
- analyzeFail("try { int i = 4.2; } catch (var _) { } finally { }",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyzeFail("try { } catch (var _) { int i = 4.2; } finally { }",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyzeFail("try { } catch (var _) { } finally { int i = 4.2; }",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ public void testTypeVariables() {
+ ClassElement cls = loadFile("class_with_type_parameter.dart").get("ClassWithTypeParameter");
+ assertNotNull("unable to locate ClassWithTypeParameter", cls);
+ analyzeIn(cls, "aField = tField", 0);
+ analyzeIn(cls, "bField = tField", 0);
+ analyzeIn(cls, "tField = aField", 0);
+ analyzeIn(cls, "tField = bField", 0);
+ analyzeIn(cls, "tField = null", 0);
+ analyzeIn(cls, "tField = 1", 1);
+ analyzeIn(cls, "tField = ''", 1);
+ analyzeIn(cls, "tField = true", 1);
+
+ analyzeIn(cls, "foo() { A a = null; T t = a; }()", 0);
+ analyzeIn(cls, "foo() { B b = null; T t = b; }()", 0);
+ analyzeIn(cls, "foo() { T t = null; A a = t; }()", 0);
+ analyzeIn(cls, "foo() { T t = null; B b = t; }()", 0);
+ analyzeIn(cls, "foo() { T t = 1; }()", 1);
+ analyzeIn(cls, "foo() { T t = ''; }()", 1);
+ analyzeIn(cls, "foo() { T t = true; }()", 1);
+ }
+
+ public void testUnaryOperators() {
+ Map<String, ClassElement> source = loadSource(
+ "class Foo {",
+ " Foo foo;",
+ " bool b;",
+ " int i;",
+ " Foo operator negate() { return this; }",
+ " Foo operator +(int operand) { return this; }",
+ " Foo operator -(int operand) { return this; }",
+ "}",
+ "class Bar {",
+ " Bar bar;",
+ " Bar operator +(Bar operand) { return this; }",
+ " Bar operator -(Bar operand) { return this; }",
+ "}",
+ "class Baz<T extends Foo> {",
+ " T baz;",
+ "}",
+ "class Qux<T> { ",
+ " T qux; ",
+ " void x() { }",
+ " y() { }",
+ "}",
+ "class X {",
+ " X x;",
+ " Z operator negate() { return null; }",
+ " Z operator +(int operand) { return null; }",
+ " Z operator -(int operand) { return null; }",
+ "}",
+ "class Y extends X { Y y; }",
+ "class Z extends X { Z z; }"
+ );
+ analyzeClasses(source);
+ ClassElement foo = source.get("Foo");
+ ClassElement bar = source.get("Bar");
+ ClassElement baz = source.get("Baz");
+ ClassElement qux = source.get("Qux");
+ ClassElement y = source.get("Y");
+ ClassElement z = source.get("Z");
+ for (Token op : EnumSet.of(Token.DEC, Token.INC, Token.SUB)) {
+ analyzeIn(foo, String.format("%sfoo", op), 0);
+ analyzeIn(foo, String.format("i = %sfoo", op), 1);
+ analyzeIn(bar, String.format("%sbar", op), 1);
+ analyzeIn(baz, String.format("%sbaz", op), 0);
+ analyzeIn(qux, String.format("%squx", op), 1);
+ }
+ analyzeIn(z, "z = x++", 0);
+ analyzeIn(z, "z = ++x", 0);
+ analyzeIn(z, "z = x--", 0);
+ analyzeIn(z, "z = --x", 0);
+ analyzeIn(y, "y = x++", 0);
+ analyzeIn(y, "y = ++x", 1);
+ analyzeIn(y, "y = x--", 0);
+ analyzeIn(y, "y = --x", 1);
+
+ analyzeIn(foo, "b = !b", 0);
+ analyzeIn(foo, "foo = !foo", 2);
+ analyzeIn(foo, "b = !i", 1);
+ analyzeIn(foo, "foo = !b", 1);
+ analyzeIn(qux, "-x()", 1);
+ analyzeIn(qux, "-y()", 0);
}
public void testUnqualified() {
@@ -865,228 +1240,46 @@ public class TypeAnalyzerTest extends TypeAnalyzerTestCase {
checkAssignIn(element, "T2", "interfaceMethod(t1)", 1);
}
- public void testSuper() {
- ClassElement sub = loadClass("covariant_class.dart", "Sub");
- checkAssignIn(sub, "B", "field", 0);
- checkAssignIn(sub, "C", "field", 1);
- checkAssignIn(sub, "D", "field", 1);
-
- checkAssignIn(sub, "B", "super.field", 0);
- checkAssignIn(sub, "C", "super.field", 0);
- checkAssignIn(sub, "D", "super.field", 1);
-
- checkAssignIn(sub, "B", "accessor", 0);
- checkAssignIn(sub, "C", "accessor", 1);
- checkAssignIn(sub, "D", "accessor", 1);
-
- checkAssignIn(sub, "B", "super.accessor", 0);
- checkAssignIn(sub, "C", "super.accessor", 0);
- checkAssignIn(sub, "D", "super.accessor", 1);
-
- analyzeIn(sub, "accessor = b", 0);
- analyzeIn(sub, "accessor = c", 1);
- analyzeIn(sub, "accessor = d", 1);
-
- analyzeIn(sub, "super.accessor = b", 0);
- analyzeIn(sub, "super.accessor = c", 0);
- analyzeIn(sub, "super.accessor = d", 1);
-
- checkAssignIn(sub, "B", "method()", 0);
- checkAssignIn(sub, "C", "method()", 1);
- checkAssignIn(sub, "D", "method()", 1);
-
- checkAssignIn(sub, "B", "super.untypedMethod()", 0);
- checkAssignIn(sub, "C", "super.untypedMethod()", 0);
- checkAssignIn(sub, "D", "super.untypedMethod()", 0);
-
- checkAssignIn(sub, "B", "super.untypedField", 0);
- checkAssignIn(sub, "C", "super.untypedField", 0);
- checkAssignIn(sub, "D", "super.untypedField", 0);
-
- checkAssignIn(sub, "B", "super.untypedAccessor", 0);
- checkAssignIn(sub, "C", "super.untypedAccessor", 0);
- checkAssignIn(sub, "D", "super.untypedAccessor", 0);
-
- analyzeIn(sub, "super.untypedAccessor = b", 0);
- analyzeIn(sub, "super.untypedAccessor = c", 0);
- analyzeIn(sub, "super.untypedAccessor = d", 0);
-
- checkAssignIn(sub, "B", "super.untypedMethod()", 0);
- checkAssignIn(sub, "C", "super.untypedMethod()", 0);
- checkAssignIn(sub, "D", "super.untypedMethod()", 0);
- }
-
- public void testSwitch() {
- analyze("{ int i = 27; switch(i) { case i: break; } }");
- analyze("{ num i = 27; switch(i) { case i: break; } }");
- analyze("{ switch(true) { case 1: break; case 'foo': break; }}");
- analyzeFail("{ int i = 27; switch(true) { case false: i = 2.7; }}",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- }
-
- public void testConstructorForwarding() {
- Map<String, ClassElement> classes = loadSource(
- "class MissingArgument {",
- " MissingArgument() : this.bar() {}",
- " MissingArgument.bar(int i) {}",
- "}",
- "class IntArgument {",
- " IntArgument() : this.bar(1) {}",
- " IntArgument.bar(int i) {}",
- "}",
- "class ExtraIntArgument {",
- " ExtraIntArgument() : this.bar(1, 1) {}",
- " ExtraIntArgument.bar(int i) {}",
- "}",
- "class StringArgument {",
- " StringArgument() : this.bar('') {}",
- " StringArgument.bar(int i) {}",
- "}",
- "class NullArgument {",
- " NullArgument() : this.bar(null) {}",
- " NullArgument.bar(int i) {}",
- "}",
- "class OptionalParameter {",
- " OptionalParameter() : this.bar() {}",
- " OptionalParameter.bar([int i = null]) {}",
- " OptionalParameter.foo() : this.bar('') {}",
- "}");
- analyzeClass(classes.get("MissingArgument"), 1);
- analyzeClass(classes.get("IntArgument"), 0);
- analyzeClass(classes.get("ExtraIntArgument"), 1);
- analyzeClass(classes.get("StringArgument"), 1);
- analyzeClass(classes.get("NullArgument"), 0);
- analyzeClass(classes.get("OptionalParameter"), 1);
- }
-
- public void testSuperConstructorInvocation() {
- Map<String, ClassElement> classes = loadSource(
- "class Super {",
- " Super(int x) {}",
- " Super.foo() {}",
- " Super.bar([int i = null]) {}",
- "}",
- "class BadSub extends Super {",
- " BadSub() : super('x') {}",
- " BadSub.foo() : super.foo('x') {}",
- " BadSub.bar() : super() {}",
- " BadSub.baz() : super.foo(null) {}",
- " BadSub.fisk() : super.bar('') {}",
- " BadSub.hest() : super.bar(1, 2) {}",
- "}",
- "class NullSub extends Super {",
- " NullSub() : super(null) {}",
- " NullSub.foo() : super.bar(null) {}",
- " NullSub.bar() : super.bar() {}",
- "}",
- "class IntSub extends Super {",
- " IntSub() : super(1) {}",
- " IntSub.foo() : super.bar(1) {}",
- "}",
- // The following works fine, but was claimed to be a bug:
- "class A {",
- " int value;",
- " A([this.value = 3]) {}",
- "}",
- "class B extends A {",
- " B() : super() {}",
- "}");
- analyzeClass(classes.get("Super"), 0);
- analyzeClass(classes.get("BadSub"), 6);
- analyzeClass(classes.get("NullSub"), 0);
- analyzeClass(classes.get("IntSub"), 0);
- analyzeClass(classes.get("A"), 0);
- analyzeClass(classes.get("B"), 0);
- }
-
- public void testNewExpression() {
- analyzeClasses(loadSource(
- "class Foo {",
- " Foo(int x) {}",
- " Foo.foo() {}",
- " Foo.bar([int i = null]) {}",
- "}",
- "interface Bar<T> factory Baz {",
- " Bar.make();",
- "}",
- "class Baz {",
- " factory Bar<S>.make(S x) { return null; }",
- "}"));
-
- analyze("Foo x = new Foo(0);");
- analyzeFail("Foo x = new Foo();", TypeErrorCode.MISSING_ARGUMENT);
- analyzeFail("Foo x = new Foo('');", TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyzeFail("Foo x = new Foo(0, null);", TypeErrorCode.EXTRA_ARGUMENT);
-
- analyze("Foo x = new Foo.foo();");
- analyzeFail("Foo x = new Foo.foo(null);", TypeErrorCode.EXTRA_ARGUMENT);
-
- analyze("Foo x = new Foo.bar();");
- analyze("Foo x = new Foo.bar(0);");
- analyzeFail("Foo x = new Foo.bar('');", TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyzeFail("Foo x = new Foo.bar(0, null);", TypeErrorCode.EXTRA_ARGUMENT);
-
- analyze("Bar<String> x = new Bar<String>.make('');");
- }
-
- public void testFactory() {
- analyzeClasses(loadSource(
- "interface Foo factory Bar {",
- " Foo(argument);",
- "}",
- "interface Baz {}",
- "class Bar implements Foo, Baz {",
- " Bar(String argument) {}",
- "}"));
-
- analyzeFail("Baz x = new Foo('');", TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ public void testUnresolved() {
+ ClassElement element = loadClass("class_with_supertypes.dart", "ClassWithSupertypes");
+ analyzeIn(element, "null", 0);
+ analyzeIn(element, "noSuchField", 1);
+ analyzeIn(element, "noSuchMethod()", 1);
+ analyzeIn(element, "method()", 0);
+ analyzeIn(element, "field", 0);
+ analyzeIn(element, "this.noSuchField", 1);
+ analyzeIn(element, "this.noSuchMethod()", 1);
+ analyzeIn(element, "this.method()", 0);
+ analyzeIn(element, "this.field", 0);
+ analyzeIn(element, "staticMethod()", 0);
+ analyzeIn(element, "staticField", 0);
+ analyzeIn(element, "this.staticMethod()", 1);
+ analyzeIn(element, "this.staticField", 1);
+ analyzeIn(element, "ClassWithSupertypes.staticMethod()", 0);
+ analyzeIn(element, "ClassWithSupertypes.staticField", 0);
+ analyzeIn(element, "methodInSuperclass()", 0);
+ analyzeIn(element, "fieldInSuperclass", 0);
+ analyzeIn(element, "staticMethodInSuperclass()", 0);
+ analyzeIn(element, "staticFieldInSuperclass", 0);
+ analyzeIn(element, "this.methodInSuperclass()", 0);
+ analyzeIn(element, "this.fieldInSuperclass", 0);
+ analyzeIn(element, "this.staticMethodInSuperclass()", 1);
+ analyzeIn(element, "this.staticFieldInSuperclass", 1);
+ analyzeIn(element, "Superclass.staticMethodInSuperclass()", 0);
+ analyzeIn(element, "Superclass.staticFieldInSuperclass", 0);
+ analyzeIn(element, "methodInInterface()", 0);
+ analyzeIn(element, "fieldInInterface", 0);
+ analyzeIn(element, "this.methodInInterface()", 0);
+ analyzeIn(element, "this.fieldInInterface", 0);
+ analyzeIn(element, "staticFieldInInterface", 0);
+ analyzeIn(element, "Interface.staticFieldInInterface", 0);
+ analyzeIn(element, "this.staticFieldInInterface", 1);
}
- public void testFunctionTypeAlias() {
- Map<String, ClassElement> classes = loadSource(
- "typedef void VoidFunction();",
- "typedef String StringFunction();",
- "typedef String IntToStringFunction(int i);",
- "class Foo {",
- " VoidFunction voidFunction;",
- " StringFunction stringFunction;",
- " IntToStringFunction intToStringFunction;",
- " Foo foo;",
- " String string;",
- " int i;",
- "}");
- analyzeClasses(classes);
- ClassElement foo = classes.get("Foo");
- analyzeIn(foo, "voidFunction()", 0);
- analyzeIn(foo, "voidFunction(1)", 1);
- analyzeIn(foo, "this.voidFunction()", 0);
- analyzeIn(foo, "this.voidFunction(1)", 1);
- analyzeIn(foo, "foo.voidFunction()", 0);
- analyzeIn(foo, "foo.voidFunction(1)", 1);
- analyzeIn(foo, "(voidFunction)()", 0);
- analyzeIn(foo, "(voidFunction)(1)", 1);
- analyzeIn(foo, "(this.voidFunction)()", 0);
- analyzeIn(foo, "(this.voidFunction)(1)", 1);
- analyzeIn(foo, "(foo.voidFunction)()", 0);
- analyzeIn(foo, "(foo.voidFunction)(1)", 1);
-
- analyzeIn(foo, "string = stringFunction()", 0);
- analyzeIn(foo, "i = stringFunction()", 1);
- analyzeIn(foo, "string = this.stringFunction()", 0);
- analyzeIn(foo, "i = this.stringFunction()", 1);
- analyzeIn(foo, "string = foo.stringFunction()", 0);
- analyzeIn(foo, "i = foo.stringFunction()", 1);
- analyzeIn(foo, "string = (stringFunction)()", 0);
- analyzeIn(foo, "i = (stringFunction)()", 1);
- analyzeIn(foo, "string = (this.stringFunction)()", 0);
- analyzeIn(foo, "i = (this.stringFunction)()", 1);
- analyzeIn(foo, "string = (foo.stringFunction)()", 0);
- analyzeIn(foo, "i = (foo.stringFunction)()", 1);
-
- analyzeIn(foo, "voidFunction = stringFunction", 0);
- analyzeIn(foo, "stringFunction = intToStringFunction", 1);
- analyzeIn(foo, "stringFunction = String foo() { return ''; }", 0);
- analyzeIn(foo, "intToStringFunction = String foo() { return ''; }", 1);
+ public void testUnresolvedIdentifier() {
+ setExpectedTypeErrorCount(3);
+ checkType(typeProvider.getDynamicType(), "y");
+ checkExpectedTypeErrorCount();
}
public void testVoid() {
@@ -1128,205 +1321,12 @@ public class TypeAnalyzerTest extends TypeAnalyzerTestCase {
analyzeFail("{ void f() {} ({ 'x': f() }); }", TypeErrorCode.VOID);
}
- public void testFieldInitializers() {
- Map<String, ClassElement> classes = loadSource(
- "class Good {",
- " String string;",
- " int i;",
- " Good() : string = '', i = 1;",
- " Good.name() : string = null, i = null;",
- " Good.untyped(x) : string = x, i = x;",
- " Good.string(String s) : string = s, i = 0;",
- "}",
- "class Bad {",
- " String string;",
- " int i;",
- " Bad() : string = 1, i = '';",
- " Bad.string(String s) : string = s, i = s;",
- "}");
- analyzeClass(classes.get("Good"), 0);
- analyzeClass(classes.get("Bad"), 3);
- }
-
- public void testArrayLiteral() {
- analyze("['x'];");
- analyze("<String>['x'];");
- analyzeFail("<int>['x'];", TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyzeFail("<String>['x', 1];", TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- analyze("List<String> strings = ['x'];");
- analyze("List<String> strings = <String>['x'];");
- analyze("List array = ['x'];");
- analyze("List array = <String>['x'];");
- analyze("List<int> ints = ['x'];");
- analyzeFail("List<int> ints = <String>['x'];",
- TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- }
-
- public void testInitializedLocals() {
- analyze("void f([int x = 1]) {}");
- analyzeFail("void f([int x = '']) {}", TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
-
- analyze("{ int x = 1; }");
- analyzeFail("{ int x = ''; }", TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
- }
-
- public void testInitializedFields() {
- Map<String, ClassElement> classes = loadSource(
- "class GoodField {",
- " static final int i = 1;",
- "}");
- analyzeClass(classes.get("GoodField"), 0);
-
- // Note, the TypeAnalyzer doesn't get a chance
- // to get its hands on bad initializers anymore
- // due to type checking in CompileTimeConstVisitor.
- }
-
- public void testGetAllSupertypes()
- throws CyclicDeclarationException, DuplicatedInterfaceException {
- Map<String, ClassElement> classes = loadSource(
- "class A extends B<String> {",
- "}",
- "class B<T> extends C<G<T>> implements I<int>, I1<T> {",
- "}",
- "class C<U> {",
- "}",
- "interface I<S> extends I2<bool> {",
- "}",
- "class G<V> {",
- "}",
- "interface I1<W> {",
- "}",
- "interface I2<X> {",
- "}",
- "class D implements I2<int> {",
- "}",
- "class E extends D implements I2<int> {",
- "}");
- analyzeClasses(classes);
- assertEquals("[]", object.getAllSupertypes().toString());
- assertEquals("[I<int>, I1<String>, I2<bool>, B<String>, C<G<String>>, Object]",
- classes.get("A").getAllSupertypes().toString());
- assertEquals("[I<int>, I1<B.T>, I2<bool>, C<G<B.T>>, Object]",
- classes.get("B").getAllSupertypes().toString());
- assertEquals("[Object]", classes.get("C").getAllSupertypes().toString());
- assertEquals("[I2<bool>, Object]", classes.get("I").getAllSupertypes().toString());
- assertEquals("[Object]", classes.get("G").getAllSupertypes().toString());
- assertEquals("[Object]", classes.get("I1").getAllSupertypes().toString());
- assertEquals("[Object]", classes.get("I2").getAllSupertypes().toString());
- assertEquals("[I2<int>, Object]", classes.get("D").getAllSupertypes().toString());
- assertEquals("[I2<int>, D, Object]", classes.get("E").getAllSupertypes().toString());
- }
-
- public void testParameterInitializers() {
- Map<String, ClassElement> classes = loadSource(
- "class C1 { int i; C1(this.i) {} }",
- "class C2 { String s; C2(int this.s) {} }",
- "class C3 { int i; C3(double this.i) {} }",
- "class C4 { int i; C4(num this.i) {} }");
- analyzeClass(classes.get("C1"), 0);
- analyzeClass(classes.get("C2"), 1);
- analyzeClass(classes.get("C3"), 1);
- analyzeClass(classes.get("C4"), 0);
- }
-
- public void testImplementsAndOverrides() {
- analyzeClasses(loadSource(
- "interface Interface {",
- " void foo(x);",
- " void bar();",
- "}",
- // Abstract class not reported until first instantiation.
- "class Class implements Interface {",
- " Class() {}",
- " String bar() { return null; }",
- "}",
- // Abstract class not reported until first instantiation.
- "class SubClass extends Class {",
- " SubClass() : super() {}",
- " Object bar() { return null; }",
- "}",
- "class SubSubClass extends Class {",
- " num bar() { return null; }", // CANNOT_OVERRIDE_METHOD_NOT_SUBTYPE
- " void foo() {}", // CANNOT_OVERRIDE_METHOD_NOT_SUBTYPE
- "}",
- "class Usage {",
- " m() {",
- " new Class();", // CANNOT_INSTATIATE_ABSTRACT_CLASS
- // ABSTRACT_CLASS.
- " new Class();", // CANNOT_INSTATIATE_ABSTRACT_CLASS.
- " new SubClass();", // CANNOT_INSTATIATE_ABSTRACT_CLASS
- //ABSTRACT_CLASS.
- " }",
- "}"),
- TypeErrorCode.CANNOT_OVERRIDE_METHOD_NOT_SUBTYPE,
- TypeErrorCode.CANNOT_OVERRIDE_METHOD_NOT_SUBTYPE,
- TypeErrorCode.CANNOT_INSTATIATE_ABSTRACT_CLASS,
- TypeErrorCode.ABSTRACT_CLASS,
- TypeErrorCode.CANNOT_INSTATIATE_ABSTRACT_CLASS,
- TypeErrorCode.CANNOT_INSTATIATE_ABSTRACT_CLASS,
- TypeErrorCode.ABSTRACT_CLASS);
- }
-
- public void testImplementsAndOverrides2() {
- analyzeClasses(loadSource(
- "interface Interface {",
- " void foo(x);",
- "}",
- // Abstract class not reported until first instantiation.
- "class Class implements Interface {",
- " Class() {}",
- " void foo() {}", // CANNOT_OVERRIDE_METHOD_NOT_SUBTYPE
- "}"),
- TypeErrorCode.CANNOT_OVERRIDE_METHOD_NOT_SUBTYPE);
- }
-
- public void testOddStuff() {
- Map<String, ClassElement> classes = analyzeClasses(loadSource(
- "class Class {",
- " Class() {}",
- " var field;",
- " void m() {}",
- " static void f() {}",
- " static g(int i) {}",
- "}"));
- ClassElement cls = classes.get("Class");
- analyzeIn(cls, "m().foo()", 1);
- analyzeIn(cls, "m().x", 1);
- analyzeIn(cls, "m()", 0);
- analyzeIn(cls, "(m)().foo()", 1);
- analyzeIn(cls, "(m)().x", 1);
- analyzeIn(cls, "(m)()", 0);
- analyzeIn(cls, "field = m()", 1);
- analyzeIn(cls, "field = Class.f()", 1);
- analyzeIn(cls, "field = (Class.f)()", 1);
- analyzeIn(cls, "Class.f()", 0);
- analyzeIn(cls, "(Class.f)()", 0);
- analyzeIn(cls, "field = Class.g('x')", 1);
- analyzeIn(cls, "field = (Class.g)('x')", 1);
- analyzeIn(cls, "field = Class.g(0)", 0);
- analyzeIn(cls, "field = (Class.g)(0)", 0);
- analyzeFail("fisk: while (true) fisk++;", TypeErrorCode.CANNOT_BE_RESOLVED);
- analyzeFail("new Class().m().x;", TypeErrorCode.VOID);
- analyzeFail("(new Class().m)().x;", TypeErrorCode.VOID);
- }
-
- /**
- * There was problem that cyclic class declaration caused infinite loop.
- * <p>
- * http://code.google.com/p/dart/issues/detail?id=348
- */
- public void test_cyclicDeclaration() {
- Map<String, ClassElement> source = loadSource(
- "class Foo extends Bar {",
- "}",
- "class Bar extends Foo {",
- "}");
- analyzeClasses(source);
- // Foo and Bar have cyclic declaration
- ClassElement classFoo = source.get("Foo");
- ClassElement classBar = source.get("Bar");
- assertEquals(classFoo, classBar.getSupertype().getElement());
- assertEquals(classBar, classFoo.getSupertype().getElement());
+ public void testWhileStatement() {
+ analyze("while (true) {}");
+ analyze("while (null) {}");
+ analyzeFail("while (0) {}",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
+ analyzeFail("while ('') {}",
+ TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE);
}
}

Powered by Google App Engine
This is Rietveld 408576698