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

Side by Side Diff: frog/tests/leg/src/TypeCheckerTest.dart

Issue 10250002: test rename overhaul: step 5 - frog and leg tests (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 #import("../../../../lib/compiler/implementation/leg.dart");
6 #import("../../../../lib/compiler/implementation/elements/elements.dart");
7 #import("../../../../lib/compiler/implementation/tree/tree.dart");
8 #import('../../../../lib/compiler/implementation/scanner/scannerlib.dart');
9 #import("../../../../lib/compiler/implementation/util/util.dart");
10 #import("mock_compiler.dart");
11 #import("parser_helper.dart");
12
13 Type intType;
14 Type boolType;
15 Type stringType;
16 Type doubleType;
17 Type objectType;
18
19 main() {
20 List tests = [testSimpleTypes,
21 testReturn,
22 testFor,
23 testWhile,
24 testOperators,
25 testConstructorInvocationArgumentCount,
26 testConstructorInvocationArgumentTypes,
27 testMethodInvocationArgumentCount,
28 testMethodInvocations,
29 testControlFlow,
30 // testNewExpression,
31 testConditionalExpression,
32 testIfStatement,
33 testThis,
34 testFunctionSubtyping];
35 for (Function test in tests) {
36 setup();
37 test();
38 }
39 }
40
41 testSimpleTypes() {
42 Expect.equals(intType, analyzeType("3"));
43 Expect.equals(boolType, analyzeType("false"));
44 Expect.equals(boolType, analyzeType("true"));
45 Expect.equals(stringType, analyzeType("'hestfisk'"));
46 }
47
48 testReturn() {
49 analyzeTopLevel("void foo() { return 3; }", MessageKind.RETURN_VALUE_IN_VOID);
50 analyzeTopLevel("int bar() { return 'hest'; }", MessageKind.NOT_ASSIGNABLE);
51 analyzeTopLevel("void baz() { var x; return x; }");
52 analyzeTopLevel(returnWithType("int", "'string'"),
53 MessageKind.NOT_ASSIGNABLE);
54 analyzeTopLevel(returnWithType("", "'string'"));
55 analyzeTopLevel(returnWithType("Object", "'string'"));
56 analyzeTopLevel(returnWithType("String", "'string'"));
57 analyzeTopLevel(returnWithType("String", null));
58 analyzeTopLevel(returnWithType("int", null));
59 analyzeTopLevel(returnWithType("void", ""));
60 analyzeTopLevel(returnWithType("void", 1), MessageKind.RETURN_VALUE_IN_VOID);
61 analyzeTopLevel(returnWithType("void", null));
62 analyzeTopLevel(returnWithType("String", ""), MessageKind.RETURN_NOTHING);
63 // analyzeTopLevel("String foo() {};"); // Should probably fail.
64 }
65
66 testFor() {
67 analyze("for (var x;true;x = x + 1) {}");
68 analyze("for (var x;null;x = x + 1) {}");
69 analyze("for (var x;0;x = x + 1) {}", MessageKind.NOT_ASSIGNABLE);
70 analyze("for (var x;'';x = x + 1) {}", MessageKind.NOT_ASSIGNABLE);
71
72 analyze("for (;true;) {}");
73 analyze("for (;null;) {}");
74 analyze("for (;0;) {}", MessageKind.NOT_ASSIGNABLE);
75 analyze("for (;'';) {}", MessageKind.NOT_ASSIGNABLE);
76
77 // Foreach tests
78 // TODO(karlklose): for each is not yet implemented.
79 // analyze("{ List<String> strings = ['1','2','3']; " +
80 // "for (String s in strings) {} }");
81 // analyze("{ List<int> ints = [1,2,3]; for (String s in ints) {} }",
82 // MessageKind.NOT_ASSIGNABLE);
83 // analyze("for (String s in true) {}", MessageKind.METHOD_NOT_FOUND);
84 }
85
86 testWhile() {
87 analyze("while (true) {}");
88 analyze("while (null) {}");
89 analyze("while (0) {}", MessageKind.NOT_ASSIGNABLE);
90 analyze("while ('') {}", MessageKind.NOT_ASSIGNABLE);
91
92 analyze("do {} while (true);");
93 analyze("do {} while (null);");
94 analyze("do {} while (0);", MessageKind.NOT_ASSIGNABLE);
95 analyze("do {} while ('');", MessageKind.NOT_ASSIGNABLE);
96 analyze("do { int i = 0.5; } while (true);", MessageKind.NOT_ASSIGNABLE);
97 analyze("do { int i = 0.5; } while (null);", MessageKind.NOT_ASSIGNABLE);
98 }
99
100 testOperators() {
101 // TODO(karlklose): add the DartC tests for operators when we can parse
102 // classes with operators.
103 for (final op in ['+', '-', '*', '/', '%', '~/', '|', '&']) {
104 analyze("{ var i = 1 ${op} 2; }");
105 analyze("{ var i = 1; i ${op}= 2; }");
106 analyze("{ int i; var j = (i = true) ${op} 2; }",
107 MessageKind.NOT_ASSIGNABLE);
108 analyze("{ int i; var j = 1 ${op} (i = true); }",
109 MessageKind.NOT_ASSIGNABLE);
110 }
111 for (final op in ['-', '~']) {
112 analyze("{ var i = ${op}1; }");
113 analyze("{ int i; var j = ${op}(i = true); }", MessageKind.NOT_ASSIGNABLE);
114 }
115 for (final op in ['++', '--']) {
116 analyze("{ int i = 1; int j = i${op}; }");
117 analyze("{ int i = 1; bool j = i${op}; }", MessageKind.NOT_ASSIGNABLE);
118 analyze("{ bool b = true; bool j = b${op}; }");
119 analyze("{ bool b = true; int j = ${op}b; }");
120 }
121 for (final op in ['||', '&&']) {
122 analyze("{ bool b = (true ${op} false); }");
123 analyze("{ int b = true ${op} false; }", MessageKind.NOT_ASSIGNABLE);
124 analyze("{ bool b = (1 ${op} false); }", MessageKind.NOT_ASSIGNABLE);
125 analyze("{ bool b = (true ${op} 2); }", MessageKind.NOT_ASSIGNABLE);
126 }
127 for (final op in ['>', '<', '<=', '>=', '==', '!=', '===', '!==']) {
128 analyze("{ bool b = 1 ${op} 2; }");
129 analyze("{ int i = 1 ${op} 2; }", MessageKind.NOT_ASSIGNABLE);
130 analyze("{ int i; bool b = (i = true) ${op} 2; }",
131 MessageKind.NOT_ASSIGNABLE);
132 analyze("{ int i; bool b = 1 ${op} (i = true); }",
133 MessageKind.NOT_ASSIGNABLE);
134 }
135 }
136
137 void testConstructorInvocationArgumentCount() {
138 compiler.parseScript("""
139 class C1 { C1(x, y); }
140 class C2 { C2(int x, int y); }
141 """);
142 // calls to untyped constructor C1
143 analyze("new C1(1, 2);");
144 analyze("new C1();", MessageKind.MISSING_ARGUMENT);
145 analyze("new C1(1);", MessageKind.MISSING_ARGUMENT);
146 analyze("new C1(1, 2, 3);", MessageKind.ADDITIONAL_ARGUMENT);
147 // calls to typed constructor C2
148 analyze("new C2(1, 2);");
149 analyze("new C2();", MessageKind.MISSING_ARGUMENT);
150 analyze("new C2(1);", MessageKind.MISSING_ARGUMENT);
151 analyze("new C2(1, 2, 3);", MessageKind.ADDITIONAL_ARGUMENT);
152 }
153
154 void testConstructorInvocationArgumentTypes() {
155 compiler.parseScript("""
156 class C1 { C1(x); }
157 class C2 { C2(int x); }
158 """);
159 analyze("new C1(42);");
160 analyze("new C1('string');");
161 analyze("new C2(42);");
162 analyze("new C2('string');",
163 MessageKind.NOT_ASSIGNABLE);
164 }
165
166 void testMethodInvocationArgumentCount() {
167 compiler.parseScript(CLASS_WITH_METHODS);
168 final String header = "{ ClassWithMethods c; ";
169 analyze("${header}c.untypedNoArgumentMethod(1); }",
170 MessageKind.ADDITIONAL_ARGUMENT);
171 analyze("${header}c.untypedOneArgumentMethod(); }",
172 MessageKind.MISSING_ARGUMENT);
173 analyze("${header}c.untypedOneArgumentMethod(1, 1); }",
174 MessageKind.ADDITIONAL_ARGUMENT);
175 analyze("${header}c.untypedTwoArgumentMethod(); }",
176 MessageKind.MISSING_ARGUMENT);
177 analyze("${header}c.untypedTwoArgumentMethod(1, 2, 3); }",
178 MessageKind.ADDITIONAL_ARGUMENT);
179 analyze("${header}c.intNoArgumentMethod(1); }",
180 MessageKind.ADDITIONAL_ARGUMENT);
181 analyze("${header}c.intOneArgumentMethod(); }",
182 MessageKind.MISSING_ARGUMENT);
183 analyze("${header}c.intOneArgumentMethod(1, 1); }",
184 MessageKind.ADDITIONAL_ARGUMENT);
185 analyze("${header}c.intTwoArgumentMethod(); }",
186 MessageKind.MISSING_ARGUMENT);
187 analyze("${header}c.intTwoArgumentMethod(1, 2, 3); }",
188 MessageKind.ADDITIONAL_ARGUMENT);
189 // analyze("${header}c.untypedField(); }");
190 }
191
192 void testMethodInvocations() {
193 compiler.parseScript(CLASS_WITH_METHODS);
194 final String header = "{ ClassWithMethods c; SubClass d; int i; int j; ";
195
196 analyze("${header}int k = c.untypedNoArgumentMethod(); }");
197 analyze("${header}ClassWithMethods x = c.untypedNoArgumentMethod(); }");
198 analyze("${header}ClassWithMethods x = d.untypedNoArgumentMethod(); }");
199 analyze("${header}int k = d.intMethod(); }");
200 analyze("${header}int k = c.untypedOneArgumentMethod(c); }");
201 analyze("${header}ClassWithMethods x = c.untypedOneArgumentMethod(1); }");
202 analyze("${header}int k = c.untypedOneArgumentMethod('string'); }");
203 analyze("${header}int k = c.untypedOneArgumentMethod(i); }");
204 analyze("${header}int k = d.untypedOneArgumentMethod(d); }");
205 analyze("${header}ClassWithMethods x = d.untypedOneArgumentMethod(1); }");
206 analyze("${header}int k = d.untypedOneArgumentMethod('string'); }");
207 analyze("${header}int k = d.untypedOneArgumentMethod(i); }");
208
209 analyze("${header}int k = c.untypedTwoArgumentMethod(1, 'string'); }");
210 analyze("${header}int k = c.untypedTwoArgumentMethod(i, j); }");
211 analyze("${header}ClassWithMethods x = c.untypedTwoArgumentMethod(i, c); }");
212 analyze("${header}int k = d.untypedTwoArgumentMethod(1, 'string'); }");
213 analyze("${header}int k = d.untypedTwoArgumentMethod(i, j); }");
214 analyze("${header}ClassWithMethods x = d.untypedTwoArgumentMethod(i, d); }");
215
216 analyze("${header}int k = c.intNoArgumentMethod(); }");
217 analyze("${header}ClassWithMethods x = c.intNoArgumentMethod(); }",
218 MessageKind.NOT_ASSIGNABLE);
219
220 analyze("${header}int k = c.intOneArgumentMethod(c); }",
221 MessageKind.NOT_ASSIGNABLE);
222 analyze("${header}ClassWithMethods x = c.intOneArgumentMethod(1); }",
223 MessageKind.NOT_ASSIGNABLE);
224 analyze("${header}int k = c.intOneArgumentMethod('string'); }",
225 MessageKind.NOT_ASSIGNABLE);
226 analyze("${header}int k = c.intOneArgumentMethod(i); }");
227
228 analyze("${header}int k = c.intTwoArgumentMethod(1, 'string'); }",
229 MessageKind.NOT_ASSIGNABLE);
230 analyze("${header}int k = c.intTwoArgumentMethod(i, j); }");
231 analyze("${header}ClassWithMethods x = c.intTwoArgumentMethod(i, j); }",
232 MessageKind.NOT_ASSIGNABLE);
233
234 analyze("${header}c.intField(); }", MessageKind.METHOD_NOT_FOUND);
235 analyze("${header}d.intField(); }", MessageKind.METHOD_NOT_FOUND);
236 }
237
238 /** Tests analysis of returns (not required by the specification). */
239 void testControlFlow() {
240 analyzeTopLevel("int foo() { if (true) { return 1; } }",
241 MessageKind.MAYBE_MISSING_RETURN);
242 final bar =
243 """void bar() {
244 if (true) {
245 if (true) { return; } else { return; }
246 } else { return; }
247 }""";
248 analyzeTopLevel(bar);
249 analyzeTopLevel("void baz() { return; int i = 1; }",
250 MessageKind.UNREACHABLE_CODE);
251 final qux =
252 """void qux() {
253 if (true) {
254 return;
255 } else if (true) {
256 if (true) {
257 return;
258 }
259 throw 'hest';
260 }
261 throw 'fisk';
262 }""";
263 analyzeTopLevel(qux);
264 analyzeTopLevel("int hest() {}", MessageKind.MISSING_RETURN);
265 final fisk = """int fisk() {
266 if (true) {
267 if (true) { return 1; } else {}
268 } else { return 1; }
269 }""";
270 analyzeTopLevel(fisk, MessageKind.MAYBE_MISSING_RETURN);
271 }
272
273 testNewExpression() {
274 compiler.parseScript("class A {}");
275 analyze("A a = new A();");
276 analyze("int i = new A();", MessageKind.NOT_ASSIGNABLE);
277
278 // TODO(karlklose): constructors are not yet implemented.
279 // compiler.parseScript(
280 // "class Foo {\n" +
281 // " Foo(int x) {}\n" +
282 // " Foo.foo() {}\n" +
283 // " Foo.bar([int i = null]) {}\n" +
284 // "}\n" +
285 // "interface Bar<T> factory Baz {\n" +
286 // " Bar.make();\n" +
287 // "}\n" +
288 // "class Baz {\n" +
289 // " factory Bar<S>.make(S x) { return null; }\n" +
290 // "}");
291 //
292 // analyze("Foo x = new Foo(0);");
293 // analyze("Foo x = new Foo();", MessageKind.MISSING_ARGUMENT);
294 // analyze("Foo x = new Foo('');", MessageKind.NOT_ASSIGNABLE);
295 // analyze("Foo x = new Foo(0, null);", MessageKind.ADDITIONAL_ARGUMENT);
296 //
297 // analyze("Foo x = new Foo.foo();");
298 // analyze("Foo x = new Foo.foo(null);", MessageKind.ADDITIONAL_ARGUMENT);
299 //
300 // analyze("Foo x = new Foo.bar();");
301 // analyze("Foo x = new Foo.bar(0);");
302 // analyze("Foo x = new Foo.bar('');", MessageKind.NOT_ASSIGNABLE);
303 // analyze("Foo x = new Foo.bar(0, null);",
304 // MessageKind.ADDITIONAL_ARGUMENT);
305 //
306 // analyze("Bar<String> x = new Bar<String>.make('');");
307 }
308
309 testConditionalExpression() {
310 analyze("int i = true ? 2 : 1;");
311 analyze("int i = true ? 'hest' : 1;");
312 analyze("int i = true ? 'hest' : 'fisk';", MessageKind.NOT_ASSIGNABLE);
313 analyze("String s = true ? 'hest' : 'fisk';");
314
315 analyze("true ? 1 : 2;");
316 analyze("null ? 1 : 2;");
317 analyze("0 ? 1 : 2;", MessageKind.NOT_ASSIGNABLE);
318 analyze("'' ? 1 : 2;", MessageKind.NOT_ASSIGNABLE);
319 analyze("{ int i; true ? i = 2.7 : 2; }",
320 MessageKind.NOT_ASSIGNABLE);
321 analyze("{ int i; true ? 2 : i = 2.7; }",
322 MessageKind.NOT_ASSIGNABLE);
323 analyze("{ int i; i = true ? 2.7 : 2; }");
324 }
325
326 testIfStatement() {
327 analyze("if (true) {}");
328 analyze("if (null) {}");
329 analyze("if (0) {}",
330 MessageKind.NOT_ASSIGNABLE);
331 analyze("if ('') {}",
332 MessageKind.NOT_ASSIGNABLE);
333 analyze("{ int i = 27; if (true) { i = 2.7; } else {} }",
334 MessageKind.NOT_ASSIGNABLE);
335 analyze("{ int i = 27; if (true) {} else { i = 2.7; } }",
336 MessageKind.NOT_ASSIGNABLE);
337 }
338
339 testThis() {
340 String script = "class Foo {}";
341 LibraryElement library = mockLibrary(compiler, script);
342 compiler.parseScript(script, library);
343 ClassElement foo = library.find(const SourceString("Foo"));
344 analyzeIn(foo, "{ int i = this; }", MessageKind.NOT_ASSIGNABLE);
345 analyzeIn(foo, "{ Object o = this; }");
346 analyzeIn(foo, "{ Foo f = this; }");
347 }
348
349 testFunctionSubtyping() {
350 // Checks that the type (in1 -> out1) is a subtype of (in2 -> out2).
351 bool isSubtype(List<Type> in1, Type out1, List<Type> in2, Type out2) {
352 return compiler.types.isSubtype(
353 new FunctionType(out1, new Link<Type>.fromList(in1), null),
354 new FunctionType(out2, new Link<Type>.fromList(in2), null));
355 }
356 Expect.isTrue(isSubtype([], intType, [], intType));
357 Expect.isTrue(isSubtype([], intType, [], objectType));
358 Expect.isFalse(isSubtype([], intType, [], doubleType));
359 Expect.isTrue(isSubtype([intType], intType, [intType], intType));
360 Expect.isTrue(isSubtype([objectType], intType, [intType], objectType));
361 Expect.isFalse(isSubtype([intType], intType, [doubleType], intType));
362 Expect.isFalse(isSubtype([intType], intType, [intType, intType], intType));
363 Expect.isFalse(isSubtype([intType, intType], intType, [intType], intType));
364 }
365
366 final CLASS_WITH_METHODS = '''
367 class ClassWithMethods {
368 untypedNoArgumentMethod() {}
369 untypedOneArgumentMethod(argument) {}
370 untypedTwoArgumentMethod(argument1, argument2) {}
371
372 int intNoArgumentMethod() {}
373 int intOneArgumentMethod(int argument) {}
374 int intTwoArgumentMethod(int argument1, int argument2) {}
375
376 Function functionField;
377 var untypedField;
378 int intField;
379 }
380 interface I {
381 int intMethod();
382 }
383 class SubClass extends ClassWithMethods implements I {}''';
384
385 Types types;
386 MockCompiler compiler;
387
388 String returnWithType(String type, expression) {
389 return "$type foo() { return $expression; }";
390 }
391
392 Node parseExpression(String text) =>
393 parseBodyCode(text, (parser, token) => parser.parseExpression(token));
394
395 void setup() {
396 compiler = new MockCompiler();
397 types = compiler.types;
398 intType = compiler.intClass.computeType(compiler);
399 doubleType = compiler.doubleClass.computeType(compiler);
400 boolType = compiler.boolClass.computeType(compiler);
401 stringType = compiler.stringClass.computeType(compiler);
402 objectType = compiler.objectClass.computeType(compiler);
403 }
404
405 Type analyzeType(String text) {
406 var node = parseExpression(text);
407 TypeCheckerVisitor visitor =
408 new TypeCheckerVisitor(compiler, new TreeElementMapping(), types);
409 return visitor.analyze(node);
410 }
411
412 analyzeTopLevel(String text, [expectedWarnings]) {
413 if (expectedWarnings === null) expectedWarnings = [];
414 if (expectedWarnings is !List) expectedWarnings = [expectedWarnings];
415
416 LibraryElement library = mockLibrary(compiler, text);
417
418 Link<Element> topLevelElements = parseUnit(text, compiler, library);
419
420 for (Link<Element> elements = topLevelElements;
421 !elements.isEmpty();
422 elements = elements.tail) {
423 Node node = elements.head.parseNode(compiler);
424 TreeElements mapping = compiler.resolver.resolve(elements.head);
425 TypeCheckerVisitor checker =
426 new TypeCheckerVisitor(compiler, mapping, types);
427 compiler.clearWarnings();
428 checker.analyze(node);
429 compareWarningKinds(text, expectedWarnings, compiler.warnings);
430 }
431 }
432
433 analyze(String text, [expectedWarnings]) {
434 if (expectedWarnings === null) expectedWarnings = [];
435 if (expectedWarnings is !List) expectedWarnings = [expectedWarnings];
436
437 Token tokens = scan(text);
438 NodeListener listener = new NodeListener(compiler, null);
439 Parser parser = new Parser(listener);
440 parser.parseStatement(tokens);
441 Node node = listener.popNode();
442 TreeElements elements = compiler.resolveNodeStatement(node, compiler.mainApp);
443 TypeCheckerVisitor checker = new TypeCheckerVisitor(compiler, elements,
444 types);
445 compiler.clearWarnings();
446 checker.analyze(node);
447 compareWarningKinds(text, expectedWarnings, compiler.warnings);
448 }
449
450 analyzeIn(ClassElement classElement, String text, [expectedWarnings]) {
451 if (expectedWarnings === null) expectedWarnings = [];
452 if (expectedWarnings is !List) expectedWarnings = [expectedWarnings];
453
454 Token tokens = scan(text);
455 NodeListener listener = new NodeListener(compiler, null);
456 Parser parser = new Parser(listener);
457 parser.parseStatement(tokens);
458 Node node = listener.popNode();
459 TreeElements elements = compiler.resolveNodeStatement(node, classElement);
460 TypeCheckerVisitor checker = new TypeCheckerVisitor(compiler, elements,
461 types);
462 compiler.clearWarnings();
463 checker.currentClass = classElement;
464 checker.analyze(node);
465 compareWarningKinds(text, expectedWarnings, compiler.warnings);
466 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698