blob: b6200eb71691c4c8410770825b785922ff74bc68 [file] [log] [blame]
// Copyright (c) 2011, 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/elements/elements.dart';
import '../../../sdk/lib/_internal/compiler/implementation/tree/tree.dart';
import '../../../sdk/lib/_internal/compiler/implementation/util/util.dart';
import 'mock_compiler.dart';
import 'parser_helper.dart';
import '../../../sdk/lib/_internal/compiler/implementation/elements/modelx.dart'
show ElementX;
import '../../../sdk/lib/_internal/compiler/implementation/dart2jslib.dart'
hide SourceString;
import '../../../sdk/lib/_internal/compiler/implementation/dart_types.dart';
DartType voidType;
DartType intType;
DartType boolType;
DartType stringType;
DartType doubleType;
DartType objectType;
main() {
List tests = [testSimpleTypes,
testReturn,
testFor,
testWhile,
testOperators,
testConstructorInvocationArgumentCount,
testConstructorInvocationArgumentTypes,
testMethodInvocationArgumentCount,
testMethodInvocations,
testControlFlow,
// testNewExpression,
testConditionalExpression,
testIfStatement,
testThis];
for (Function test in tests) {
setup();
test();
}
}
testSimpleTypes() {
Expect.equals(intType, analyzeType("3"));
Expect.equals(boolType, analyzeType("false"));
Expect.equals(boolType, analyzeType("true"));
Expect.equals(stringType, analyzeType("'hestfisk'"));
}
testReturn() {
analyzeTopLevel("void foo() { return 3; }", MessageKind.RETURN_VALUE_IN_VOID);
analyzeTopLevel("int bar() { return 'hest'; }", MessageKind.NOT_ASSIGNABLE);
analyzeTopLevel("void baz() { var x; return x; }");
analyzeTopLevel(returnWithType("int", "'string'"),
MessageKind.NOT_ASSIGNABLE);
analyzeTopLevel(returnWithType("", "'string'"));
analyzeTopLevel(returnWithType("Object", "'string'"));
analyzeTopLevel(returnWithType("String", "'string'"));
analyzeTopLevel(returnWithType("String", null));
analyzeTopLevel(returnWithType("int", null));
analyzeTopLevel(returnWithType("void", ""));
analyzeTopLevel(returnWithType("void", 1), MessageKind.RETURN_VALUE_IN_VOID);
analyzeTopLevel(returnWithType("void", null));
analyzeTopLevel(returnWithType("String", ""), MessageKind.RETURN_NOTHING);
// analyzeTopLevel("String foo() {};"); // Should probably fail.
}
testFor() {
analyze("for (var x;true;x = x + 1) {}");
analyze("for (var x;null;x = x + 1) {}");
analyze("for (var x;0;x = x + 1) {}", MessageKind.NOT_ASSIGNABLE);
analyze("for (var x;'';x = x + 1) {}", MessageKind.NOT_ASSIGNABLE);
analyze("for (;true;) {}");
analyze("for (;null;) {}");
analyze("for (;0;) {}", MessageKind.NOT_ASSIGNABLE);
analyze("for (;'';) {}", MessageKind.NOT_ASSIGNABLE);
// Foreach tests
// TODO(karlklose): for each is not yet implemented.
// analyze("{ List<String> strings = ['1','2','3']; " +
// "for (String s in strings) {} }");
// analyze("{ List<int> ints = [1,2,3]; for (String s in ints) {} }",
// MessageKind.NOT_ASSIGNABLE);
// analyze("for (String s in true) {}", MessageKind.METHOD_NOT_FOUND);
}
testWhile() {
analyze("while (true) {}");
analyze("while (null) {}");
analyze("while (0) {}", MessageKind.NOT_ASSIGNABLE);
analyze("while ('') {}", MessageKind.NOT_ASSIGNABLE);
analyze("do {} while (true);");
analyze("do {} while (null);");
analyze("do {} while (0);", MessageKind.NOT_ASSIGNABLE);
analyze("do {} while ('');", MessageKind.NOT_ASSIGNABLE);
analyze("do { int i = 0.5; } while (true);", MessageKind.NOT_ASSIGNABLE);
analyze("do { int i = 0.5; } while (null);", MessageKind.NOT_ASSIGNABLE);
}
testOperators() {
// TODO(karlklose): add the DartC tests for operators when we can parse
// classes with operators.
for (final op in ['+', '-', '*', '/', '%', '~/', '|', '&']) {
analyze("{ var i = 1 ${op} 2; }");
analyze("{ var i = 1; i ${op}= 2; }");
analyze("{ int i; var j = (i = true) ${op} 2; }",
MessageKind.NOT_ASSIGNABLE);
analyze("{ int i; var j = 1 ${op} (i = true); }",
MessageKind.NOT_ASSIGNABLE);
}
for (final op in ['-', '~']) {
analyze("{ var i = ${op}1; }");
analyze("{ int i; var j = ${op}(i = true); }", MessageKind.NOT_ASSIGNABLE);
}
for (final op in ['++', '--']) {
analyze("{ int i = 1; int j = i${op}; }");
analyze("{ int i = 1; bool j = i${op}; }", MessageKind.NOT_ASSIGNABLE);
analyze("{ bool b = true; bool j = b${op}; }");
analyze("{ bool b = true; int j = ${op}b; }");
}
for (final op in ['||', '&&']) {
analyze("{ bool b = (true ${op} false); }");
analyze("{ int b = true ${op} false; }", MessageKind.NOT_ASSIGNABLE);
analyze("{ bool b = (1 ${op} false); }", MessageKind.NOT_ASSIGNABLE);
analyze("{ bool b = (true ${op} 2); }", MessageKind.NOT_ASSIGNABLE);
}
for (final op in ['>', '<', '<=', '>=', '==', '!=']) {
analyze("{ bool b = 1 ${op} 2; }");
analyze("{ int i = 1 ${op} 2; }", MessageKind.NOT_ASSIGNABLE);
analyze("{ int i; bool b = (i = true) ${op} 2; }",
MessageKind.NOT_ASSIGNABLE);
analyze("{ int i; bool b = 1 ${op} (i = true); }",
MessageKind.NOT_ASSIGNABLE);
}
}
void testConstructorInvocationArgumentCount() {
compiler.parseScript("""
class C1 { C1(x, y); }
class C2 { C2(int x, int y); }
""");
// calls to untyped constructor C1
analyze("new C1(1, 2);");
analyze("new C1();", MessageKind.MISSING_ARGUMENT);
analyze("new C1(1);", MessageKind.MISSING_ARGUMENT);
analyze("new C1(1, 2, 3);", MessageKind.ADDITIONAL_ARGUMENT);
// calls to typed constructor C2
analyze("new C2(1, 2);");
analyze("new C2();", MessageKind.MISSING_ARGUMENT);
analyze("new C2(1);", MessageKind.MISSING_ARGUMENT);
analyze("new C2(1, 2, 3);", MessageKind.ADDITIONAL_ARGUMENT);
}
void testConstructorInvocationArgumentTypes() {
compiler.parseScript("""
class C1 { C1(x); }
class C2 { C2(int x); }
""");
analyze("new C1(42);");
analyze("new C1('string');");
analyze("new C2(42);");
analyze("new C2('string');",
MessageKind.NOT_ASSIGNABLE);
}
void testMethodInvocationArgumentCount() {
compiler.parseScript(CLASS_WITH_METHODS);
final String header = "{ ClassWithMethods c; ";
analyze("${header}c.untypedNoArgumentMethod(1); }",
MessageKind.ADDITIONAL_ARGUMENT);
analyze("${header}c.untypedOneArgumentMethod(); }",
MessageKind.MISSING_ARGUMENT);
analyze("${header}c.untypedOneArgumentMethod(1, 1); }",
MessageKind.ADDITIONAL_ARGUMENT);
analyze("${header}c.untypedTwoArgumentMethod(); }",
MessageKind.MISSING_ARGUMENT);
analyze("${header}c.untypedTwoArgumentMethod(1, 2, 3); }",
MessageKind.ADDITIONAL_ARGUMENT);
analyze("${header}c.intNoArgumentMethod(1); }",
MessageKind.ADDITIONAL_ARGUMENT);
analyze("${header}c.intOneArgumentMethod(); }",
MessageKind.MISSING_ARGUMENT);
analyze("${header}c.intOneArgumentMethod(1, 1); }",
MessageKind.ADDITIONAL_ARGUMENT);
analyze("${header}c.intTwoArgumentMethod(); }",
MessageKind.MISSING_ARGUMENT);
analyze("${header}c.intTwoArgumentMethod(1, 2, 3); }",
MessageKind.ADDITIONAL_ARGUMENT);
// analyze("${header}c.untypedField(); }");
analyze("${header}c.intOneArgumentOneOptionalMethod(); }",
[MessageKind.MISSING_ARGUMENT]);
analyze("${header}c.intOneArgumentOneOptionalMethod(0); }");
analyze("${header}c.intOneArgumentOneOptionalMethod(0, 1); }");
analyze("${header}c.intOneArgumentOneOptionalMethod(0, 1, 2); }",
[MessageKind.ADDITIONAL_ARGUMENT]);
analyze("${header}c.intOneArgumentOneOptionalMethod(0, 1, c: 2); }",
[MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
analyze("${header}c.intOneArgumentOneOptionalMethod(0, b: 1); }",
[MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
analyze("${header}c.intOneArgumentOneOptionalMethod(a: 0, b: 1); }",
[MessageKind.NAMED_ARGUMENT_NOT_FOUND,
MessageKind.NAMED_ARGUMENT_NOT_FOUND,
MessageKind.MISSING_ARGUMENT]);
analyze("${header}c.intTwoOptionalMethod(); }");
analyze("${header}c.intTwoOptionalMethod(0); }");
analyze("${header}c.intTwoOptionalMethod(0, 1); }");
analyze("${header}c.intTwoOptionalMethod(0, 1, 2); }",
[MessageKind.ADDITIONAL_ARGUMENT]);
analyze("${header}c.intTwoOptionalMethod(a: 0); }",
[MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
analyze("${header}c.intTwoOptionalMethod(0, b: 1); }",
[MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
analyze("${header}c.intOneArgumentOneNamedMethod(); }",
[MessageKind.MISSING_ARGUMENT]);
analyze("${header}c.intOneArgumentOneNamedMethod(0); }");
analyze("${header}c.intOneArgumentOneNamedMethod(0, b: 1); }");
analyze("${header}c.intOneArgumentOneNamedMethod(b: 1); }",
[MessageKind.MISSING_ARGUMENT]);
analyze("${header}c.intOneArgumentOneNamedMethod(0, b: 1, c: 2); }",
[MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
analyze("${header}c.intOneArgumentOneNamedMethod(0, 1); }",
[MessageKind.ADDITIONAL_ARGUMENT]);
analyze("${header}c.intOneArgumentOneNamedMethod(0, 1, c: 2); }",
[MessageKind.ADDITIONAL_ARGUMENT,
MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
analyze("${header}c.intOneArgumentOneNamedMethod(a: 1, b: 1); }",
[MessageKind.NAMED_ARGUMENT_NOT_FOUND,
MessageKind.MISSING_ARGUMENT]);
analyze("${header}c.intTwoNamedMethod(); }");
analyze("${header}c.intTwoNamedMethod(a: 0); }");
analyze("${header}c.intTwoNamedMethod(b: 1); }");
analyze("${header}c.intTwoNamedMethod(a: 0, b: 1); }");
analyze("${header}c.intTwoNamedMethod(b: 1, a: 0); }");
analyze("${header}c.intTwoNamedMethod(0); }",
[MessageKind.ADDITIONAL_ARGUMENT]);
analyze("${header}c.intTwoNamedMethod(c: 2); }",
[MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
analyze("${header}c.intTwoNamedMethod(a: 0, c: 2); }",
[MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
analyze("${header}c.intTwoNamedMethod(a: 0, b: 1, c: 2); }",
[MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
analyze("${header}c.intTwoNamedMethod(c: 2, b: 1, a: 0); }",
[MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
analyze("${header}c.intTwoNamedMethod(0, b: 1); }",
[MessageKind.ADDITIONAL_ARGUMENT]);
analyze("${header}c.intTwoNamedMethod(0, 1); }",
[MessageKind.ADDITIONAL_ARGUMENT,
MessageKind.ADDITIONAL_ARGUMENT]);
analyze("${header}c.intTwoNamedMethod(0, c: 2); }",
[MessageKind.ADDITIONAL_ARGUMENT,
MessageKind.NAMED_ARGUMENT_NOT_FOUND]);
}
void testMethodInvocations() {
compiler.parseScript(CLASS_WITH_METHODS);
final String header = """{
ClassWithMethods c;
SubClass d;
var e;
int i;
int j;
int localMethod(String str) { return 0; }
""";
analyze("${header}int k = c.untypedNoArgumentMethod(); }");
analyze("${header}ClassWithMethods x = c.untypedNoArgumentMethod(); }");
analyze("${header}ClassWithMethods x = d.untypedNoArgumentMethod(); }");
analyze("${header}int k = d.intMethod(); }");
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 = d.untypedOneArgumentMethod(d); }");
analyze("${header}ClassWithMethods x = d.untypedOneArgumentMethod(1); }");
analyze("${header}int k = d.untypedOneArgumentMethod('string'); }");
analyze("${header}int k = d.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 = d.untypedTwoArgumentMethod(1, 'string'); }");
analyze("${header}int k = d.untypedTwoArgumentMethod(i, j); }");
analyze("${header}ClassWithMethods x = d.untypedTwoArgumentMethod(i, d); }");
analyze("${header}int k = c.intNoArgumentMethod(); }");
analyze("${header}ClassWithMethods x = c.intNoArgumentMethod(); }",
MessageKind.NOT_ASSIGNABLE);
analyze("${header}int k = c.intOneArgumentMethod(c); }",
MessageKind.NOT_ASSIGNABLE);
analyze("${header}ClassWithMethods x = c.intOneArgumentMethod(1); }",
MessageKind.NOT_ASSIGNABLE);
analyze("${header}int k = c.intOneArgumentMethod('string'); }",
MessageKind.NOT_ASSIGNABLE);
analyze("${header}int k = c.intOneArgumentMethod(i); }");
analyze("${header}int k = c.intTwoArgumentMethod(1, 'string'); }",
MessageKind.NOT_ASSIGNABLE);
analyze("${header}int k = c.intTwoArgumentMethod(i, j); }");
analyze("${header}ClassWithMethods x = c.intTwoArgumentMethod(i, j); }",
MessageKind.NOT_ASSIGNABLE);
analyze("${header}c.functionField(); }");
analyze("${header}d.functionField(); }");
analyze("${header}c.functionField(1); }");
analyze("${header}d.functionField('string'); }");
analyze("${header}c.intField(); }", MessageKind.NOT_CALLABLE);
analyze("${header}d.intField(); }", MessageKind.NOT_CALLABLE);
analyze("${header}c.untypedField(); }");
analyze("${header}d.untypedField(); }");
analyze("${header}c.untypedField(1); }");
analyze("${header}d.untypedField('string'); }");
// Invocation of dynamic variable.
analyze("${header}e(); }");
analyze("${header}e(1); }");
analyze("${header}e('string'); }");
// Invocation on local method.
analyze("${header}localMethod(); }", MessageKind.MISSING_ARGUMENT);
analyze("${header}localMethod(1); }", MessageKind.NOT_ASSIGNABLE);
analyze("${header}localMethod('string'); }");
analyze("${header}int k = localMethod('string'); }");
analyze("${header}String k = localMethod('string'); }",
MessageKind.NOT_ASSIGNABLE);
// Invocation on parenthesized expressions.
analyze("${header}(e)(); }");
analyze("${header}(e)(1); }");
analyze("${header}(e)('string'); }");
analyze("${header}(foo)(); }");
analyze("${header}(foo)(1); }");
analyze("${header}(foo)('string'); }");
// Invocations on function expressions.
analyze("${header}(foo){}(); }", MessageKind.MISSING_ARGUMENT);
analyze("${header}(foo){}(1); }");
analyze("${header}(foo){}('string'); }");
analyze("${header}(int foo){}('string'); }", MessageKind.NOT_ASSIGNABLE);
analyze("${header}(String foo){}('string'); }");
analyze("${header}int k = int bar(String foo){ return 0; }('string'); }");
analyze("${header}int k = String bar(String foo){ return foo; }('string'); }",
MessageKind.NOT_ASSIGNABLE);
// Static invocations.
analyze("${header}ClassWithMethods.staticMethod(); }",
MessageKind.MISSING_ARGUMENT);
analyze("${header}ClassWithMethods.staticMethod(1); }",
MessageKind.NOT_ASSIGNABLE);
analyze("${header}ClassWithMethods.staticMethod('string'); }");
analyze("${header}int k = ClassWithMethods.staticMethod('string'); }");
analyze("${header}String k = ClassWithMethods.staticMethod('string'); }",
MessageKind.NOT_ASSIGNABLE);
// Invocation on dynamic variable.
analyze("${header}e.foo(); }");
analyze("${header}e.foo(1); }");
analyze("${header}e.foo('string'); }");
// Invocation on unresolved variable.
analyze("${header}foo(); }");
analyze("${header}foo(1); }");
analyze("${header}foo('string'); }");
// TODO(johnniwinther): Add tests of invocations using implicit this.
}
/** Tests analysis of returns (not required by the specification). */
void testControlFlow() {
analyzeTopLevel("void foo() { if (true) { return; } }");
analyzeTopLevel("foo() { if (true) { return; } }");
analyzeTopLevel("int foo() { if (true) { return 1; } }",
MessageKind.MAYBE_MISSING_RETURN);
final bar =
"""void bar() {
if (true) {
if (true) { return; } else { return; }
} else { return; }
}""";
analyzeTopLevel(bar);
analyzeTopLevel("void baz() { return; int i = 1; }",
MessageKind.UNREACHABLE_CODE);
final qux =
"""void qux() {
if (true) {
return;
} else if (true) {
if (true) {
return;
}
throw 'hest';
}
throw 'fisk';
}""";
analyzeTopLevel(qux);
analyzeTopLevel("int hest() {}", MessageKind.MISSING_RETURN);
final fisk = """int fisk() {
if (true) {
if (true) { return 1; } else {}
} else { return 1; }
}""";
analyzeTopLevel(fisk, MessageKind.MAYBE_MISSING_RETURN);
analyzeTopLevel("int foo() { while(true) { return 1; } }");
analyzeTopLevel("int foo() { while(true) { return 1; } return 2; }",
MessageKind.UNREACHABLE_CODE);
}
testNewExpression() {
compiler.parseScript("class A {}");
analyze("A a = new A();");
analyze("int i = new A();", MessageKind.NOT_ASSIGNABLE);
// TODO(karlklose): constructors are not yet implemented.
// compiler.parseScript(
// "class Foo {\n" +
// " Foo(int x) {}\n" +
// " Foo.foo() {}\n" +
// " Foo.bar([int i = null]) {}\n" +
// "}\n" +
// "interface Bar<T> factory Baz {\n" +
// " Bar.make();\n" +
// "}\n" +
// "class Baz {\n" +
// " factory Bar<S>.make(S x) { return null; }\n" +
// "}");
//
// analyze("Foo x = new Foo(0);");
// analyze("Foo x = new Foo();", MessageKind.MISSING_ARGUMENT);
// analyze("Foo x = new Foo('');", MessageKind.NOT_ASSIGNABLE);
// analyze("Foo x = new Foo(0, null);", MessageKind.ADDITIONAL_ARGUMENT);
//
// analyze("Foo x = new Foo.foo();");
// analyze("Foo x = new Foo.foo(null);", MessageKind.ADDITIONAL_ARGUMENT);
//
// analyze("Foo x = new Foo.bar();");
// analyze("Foo x = new Foo.bar(0);");
// analyze("Foo x = new Foo.bar('');", MessageKind.NOT_ASSIGNABLE);
// analyze("Foo x = new Foo.bar(0, null);",
// MessageKind.ADDITIONAL_ARGUMENT);
//
// analyze("Bar<String> x = new Bar<String>.make('');");
}
testConditionalExpression() {
analyze("int i = true ? 2 : 1;");
analyze("int i = true ? 'hest' : 1;");
analyze("int i = true ? 'hest' : 'fisk';", MessageKind.NOT_ASSIGNABLE);
analyze("String s = true ? 'hest' : 'fisk';");
analyze("true ? 1 : 2;");
analyze("null ? 1 : 2;");
analyze("0 ? 1 : 2;", MessageKind.NOT_ASSIGNABLE);
analyze("'' ? 1 : 2;", MessageKind.NOT_ASSIGNABLE);
analyze("{ int i; true ? i = 2.7 : 2; }",
MessageKind.NOT_ASSIGNABLE);
analyze("{ int i; true ? 2 : i = 2.7; }",
MessageKind.NOT_ASSIGNABLE);
analyze("{ int i; i = true ? 2.7 : 2; }");
}
testIfStatement() {
analyze("if (true) {}");
analyze("if (null) {}");
analyze("if (0) {}",
MessageKind.NOT_ASSIGNABLE);
analyze("if ('') {}",
MessageKind.NOT_ASSIGNABLE);
analyze("{ int i = 27; if (true) { i = 2.7; } else {} }",
MessageKind.NOT_ASSIGNABLE);
analyze("{ int i = 27; if (true) {} else { i = 2.7; } }",
MessageKind.NOT_ASSIGNABLE);
}
testThis() {
String script = "class Foo {}";
LibraryElement library = mockLibrary(compiler, script);
compiler.parseScript(script, library);
ClassElement foo = library.find(const SourceString("Foo"));
analyzeIn(foo, "{ int i = this; }", MessageKind.NOT_ASSIGNABLE);
analyzeIn(foo, "{ Object o = this; }");
analyzeIn(foo, "{ Foo f = this; }");
}
const CLASS_WITH_METHODS = '''
class ClassWithMethods {
untypedNoArgumentMethod() {}
untypedOneArgumentMethod(argument) {}
untypedTwoArgumentMethod(argument1, argument2) {}
int intNoArgumentMethod() {}
int intOneArgumentMethod(int argument) {}
int intTwoArgumentMethod(int argument1, int argument2) {}
void intOneArgumentOneOptionalMethod(int a, [int b]) {}
void intTwoOptionalMethod([int a, int b]) {}
void intOneArgumentOneNamedMethod(int a, {int b}) {}
void intTwoNamedMethod({int a, int b}) {}
Function functionField;
var untypedField;
int intField;
static int staticMethod(String str) {}
}
interface I {
int intMethod();
}
class SubClass extends ClassWithMethods implements I {}''';
Types types;
MockCompiler compiler;
String returnWithType(String type, expression) {
return "$type foo() { return $expression; }";
}
Node parseExpression(String text) =>
parseBodyCode(text, (parser, token) => parser.parseExpression(token));
void setup() {
compiler = new MockCompiler();
types = compiler.types;
voidType = compiler.types.voidType;
intType = compiler.intClass.computeType(compiler);
doubleType = compiler.doubleClass.computeType(compiler);
boolType = compiler.boolClass.computeType(compiler);
stringType = compiler.stringClass.computeType(compiler);
objectType = compiler.objectClass.computeType(compiler);
}
DartType analyzeType(String text) {
var node = parseExpression(text);
TypeCheckerVisitor visitor =
new TypeCheckerVisitor(compiler, new TreeElementMapping(null), types);
return visitor.analyze(node);
}
analyzeTopLevel(String text, [expectedWarnings]) {
if (expectedWarnings == null) expectedWarnings = [];
if (expectedWarnings is !List) expectedWarnings = [expectedWarnings];
LibraryElement library = mockLibrary(compiler, text);
Link<Element> topLevelElements = parseUnit(text, compiler, library);
for (Link<Element> elements = topLevelElements;
!elements.isEmpty;
elements = elements.tail) {
Node node = elements.head.parseNode(compiler);
TreeElements mapping = compiler.resolver.resolve(elements.head);
TypeCheckerVisitor checker =
new TypeCheckerVisitor(compiler, mapping, types);
compiler.clearWarnings();
checker.analyze(node);
compareWarningKinds(text, expectedWarnings, compiler.warnings);
}
}
analyze(String text, [expectedWarnings]) {
if (expectedWarnings == null) expectedWarnings = [];
if (expectedWarnings is !List) expectedWarnings = [expectedWarnings];
Token tokens = scan(text);
NodeListener listener = new NodeListener(compiler, null);
Parser parser = new Parser(listener);
parser.parseStatement(tokens);
Node node = listener.popNode();
Element function = new ElementX(
buildSourceString(''), ElementKind.FUNCTION, compiler.mainApp);
TreeElements elements = compiler.resolveNodeStatement(node, function);
TypeCheckerVisitor checker = new TypeCheckerVisitor(compiler, elements,
types);
compiler.clearWarnings();
checker.analyze(node);
compareWarningKinds(text, expectedWarnings, compiler.warnings);
}
analyzeIn(ClassElement classElement, String text, [expectedWarnings]) {
if (expectedWarnings == null) expectedWarnings = [];
if (expectedWarnings is !List) expectedWarnings = [expectedWarnings];
Token tokens = scan(text);
NodeListener listener = new NodeListener(compiler, null);
Parser parser = new Parser(listener);
parser.parseStatement(tokens);
Node node = listener.popNode();
classElement.ensureResolved(compiler);
TreeElements elements = compiler.resolveNodeStatement(node, classElement);
TypeCheckerVisitor checker = new TypeCheckerVisitor(compiler, elements,
types);
compiler.clearWarnings();
checker.currentClass = classElement;
checker.analyze(node);
compareWarningKinds(text, expectedWarnings, compiler.warnings);
}