OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
| 5 import 'dart:async'; |
5 import "package:expect/expect.dart"; | 6 import "package:expect/expect.dart"; |
| 7 import "package:async_helper/async_helper.dart"; |
6 import '../../../sdk/lib/_internal/compiler/implementation/source_file.dart'; | 8 import '../../../sdk/lib/_internal/compiler/implementation/source_file.dart'; |
7 import '../../../sdk/lib/_internal/compiler/implementation/types/types.dart'; | 9 import '../../../sdk/lib/_internal/compiler/implementation/types/types.dart'; |
8 import '../../../sdk/lib/_internal/compiler/implementation/types/concrete_types_
inferrer.dart'; | 10 import '../../../sdk/lib/_internal/compiler/implementation/types/concrete_types_
inferrer.dart'; |
9 | 11 |
10 import "parser_helper.dart"; | 12 import "parser_helper.dart"; |
11 import "compiler_helper.dart"; | 13 import "compiler_helper.dart"; |
12 | 14 |
13 /** | 15 /** |
14 * Finds the node corresponding to the last occurence of the substring | 16 * Finds the node corresponding to the last occurence of the substring |
15 * [: identifier; :] in the program represented by the visited AST. | 17 * [: identifier; :] in the program represented by the visited AST. |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 */ | 140 */ |
139 void checkFieldHasUknownType(String className, String fieldName) { | 141 void checkFieldHasUknownType(String className, String fieldName) { |
140 return Expect.isTrue( | 142 return Expect.isTrue( |
141 inferrer.inferredFieldTypes[findField(className, fieldName)] | 143 inferrer.inferredFieldTypes[findField(className, fieldName)] |
142 .isUnknown()); | 144 .isUnknown()); |
143 } | 145 } |
144 } | 146 } |
145 | 147 |
146 const String CORELIB = r''' | 148 const String CORELIB = r''' |
147 print(var obj) {} | 149 print(var obj) {} |
148 abstract class num { | 150 abstract class num { |
149 num operator +(num x); | 151 num operator +(num x); |
150 num operator *(num x); | 152 num operator *(num x); |
151 num operator -(num x); | 153 num operator -(num x); |
152 operator ==(x); | 154 operator ==(x); |
153 num floor(); | 155 num floor(); |
154 } | 156 } |
155 abstract class int extends num { | 157 abstract class int extends num { |
156 bool get isEven; | 158 bool get isEven; |
157 } | 159 } |
158 abstract class double extends num { | 160 abstract class double extends num { |
159 bool get isNaN; | 161 bool get isNaN; |
160 } | 162 } |
161 class bool {} | 163 class bool {} |
162 class String {} | 164 class String {} |
163 class Object { | 165 class Object { |
164 Object(); | 166 Object(); |
165 } | 167 } |
166 class Function {} | 168 class Function {} |
167 abstract class List<E> { | 169 abstract class List<E> { |
168 factory List([int length]) {} | 170 factory List([int length]) {} |
169 } | 171 } |
170 abstract class Map<K, V> {} | 172 abstract class Map<K, V> {} |
171 class Closure {} | 173 class Closure {} |
172 class Type {} | 174 class Type {} |
173 class StackTrace {} | 175 class StackTrace {} |
174 class Dynamic_ {} | 176 class Dynamic_ {} |
175 bool identical(Object a, Object b) {}'''; | 177 bool identical(Object a, Object b) {}'''; |
176 | 178 |
177 AnalysisResult analyze(String code, {int maxConcreteTypeSize: 1000}) { | 179 Future<AnalysisResult> analyze(String code, {int maxConcreteTypeSize: 1000}) { |
178 Uri uri = new Uri(scheme: 'source'); | 180 Uri uri = new Uri(scheme: 'source'); |
179 MockCompiler compiler = new MockCompiler( | 181 MockCompiler compiler = new MockCompiler( |
180 coreSource: CORELIB, | 182 coreSource: CORELIB, |
181 enableConcreteTypeInference: true, | 183 enableConcreteTypeInference: true, |
182 maxConcreteTypeSize: maxConcreteTypeSize); | 184 maxConcreteTypeSize: maxConcreteTypeSize); |
183 compiler.sourceFiles[uri.toString()] = new SourceFile(uri.toString(), code); | 185 compiler.sourceFiles[uri.toString()] = new SourceFile(uri.toString(), code); |
184 compiler.typesTask.concreteTypesInferrer.testMode = true; | 186 compiler.typesTask.concreteTypesInferrer.testMode = true; |
185 compiler.runCompiler(uri); | 187 return compiler.runCompiler(uri).then((_) { |
186 return new AnalysisResult(compiler); | 188 return new AnalysisResult(compiler); |
| 189 }); |
187 } | 190 } |
188 | 191 |
189 testDynamicBackDoor() { | 192 testDynamicBackDoor() { |
190 final String source = r""" | 193 final String source = r""" |
191 main () { | 194 main () { |
192 var x = "__dynamic_for_test"; | 195 var x = "__dynamic_for_test"; |
193 x; | 196 x; |
194 } | 197 } |
195 """; | 198 """; |
196 AnalysisResult result = analyze(source); | 199 return analyze(source).then((result) { |
197 result.checkNodeHasUnknownType('x'); | 200 result.checkNodeHasUnknownType('x'); |
| 201 }); |
198 } | 202 } |
199 | 203 |
200 testVariableDeclaration() { | 204 testVariableDeclaration() { |
201 final String source = r""" | 205 final String source = r""" |
202 main() { | 206 main() { |
203 var v1; | 207 var v1; |
204 var v2; | 208 var v2; |
205 v2 = 1; | 209 v2 = 1; |
206 v1; v2; | 210 v1; v2; |
207 } | 211 } |
208 """; | 212 """; |
209 AnalysisResult result = analyze(source); | 213 return analyze(source).then((result) { |
210 result.checkNodeHasType('v1', [result.nullType]); | 214 result.checkNodeHasType('v1', [result.nullType]); |
211 result.checkNodeHasType('v2', [result.int]); | 215 result.checkNodeHasType('v2', [result.int]); |
| 216 }); |
212 } | 217 } |
213 | 218 |
214 testLiterals() { | 219 testLiterals() { |
215 final String source = r""" | 220 final String source = r""" |
216 main() { | 221 main() { |
217 var v1 = 42; | 222 var v1 = 42; |
218 var v2 = 42.0; | 223 var v2 = 42.0; |
219 var v3 = 'abc'; | 224 var v3 = 'abc'; |
220 var v4 = true; | 225 var v4 = true; |
221 var v5 = null; | 226 var v5 = null; |
222 v1; v2; v3; v4; v5; | 227 v1; v2; v3; v4; v5; |
223 } | 228 } |
224 """; | 229 """; |
225 AnalysisResult result = analyze(source); | 230 return analyze(source).then((result) { |
226 result.checkNodeHasType('v1', [result.int]); | 231 result.checkNodeHasType('v1', [result.int]); |
227 result.checkNodeHasType('v2', [result.double]); | 232 result.checkNodeHasType('v2', [result.double]); |
228 result.checkNodeHasType('v3', [result.string]); | 233 result.checkNodeHasType('v3', [result.string]); |
229 result.checkNodeHasType('v4', [result.bool]); | 234 result.checkNodeHasType('v4', [result.bool]); |
230 result.checkNodeHasType('v5', [result.nullType]); | 235 result.checkNodeHasType('v5', [result.nullType]); |
| 236 }); |
231 } | 237 } |
232 | 238 |
233 testRedefinition() { | 239 testRedefinition() { |
234 final String source = r""" | 240 final String source = r""" |
235 main() { | 241 main() { |
236 var foo = 42; | 242 var foo = 42; |
237 foo = 'abc'; | 243 foo = 'abc'; |
238 foo; | 244 foo; |
239 } | 245 } |
240 """; | 246 """; |
241 AnalysisResult result = analyze(source); | 247 return analyze(source).then((result) { |
242 result.checkNodeHasType('foo', [result.string]); | 248 result.checkNodeHasType('foo', [result.string]); |
| 249 }); |
243 } | 250 } |
244 | 251 |
245 testIfThenElse() { | 252 testIfThenElse() { |
246 final String source = r""" | 253 final String source = r""" |
247 main() { | 254 main() { |
248 var foo = 42; | 255 var foo = 42; |
249 if (true) { | 256 if (true) { |
250 foo = 'abc'; | 257 foo = 'abc'; |
251 } else { | 258 } else { |
252 foo = false; | 259 foo = false; |
253 } | 260 } |
254 foo; | 261 foo; |
255 } | 262 } |
256 """; | 263 """; |
257 AnalysisResult result = analyze(source); | 264 return analyze(source).then((result) { |
258 result.checkNodeHasType('foo', [result.string, result.bool]); | 265 result.checkNodeHasType('foo', [result.string, result.bool]); |
| 266 }); |
259 } | 267 } |
260 | 268 |
261 testTernaryIf() { | 269 testTernaryIf() { |
262 final String source = r""" | 270 final String source = r""" |
263 main() { | 271 main() { |
264 var foo = 42; | 272 var foo = 42; |
265 foo = true ? 'abc' : false; | 273 foo = true ? 'abc' : false; |
266 foo; | 274 foo; |
267 } | 275 } |
268 """; | 276 """; |
269 AnalysisResult result = analyze(source); | 277 return analyze(source).then((result) { |
270 result.checkNodeHasType('foo', [result.string, result.bool]); | 278 result.checkNodeHasType('foo', [result.string, result.bool]); |
| 279 }); |
271 } | 280 } |
272 | 281 |
273 testWhile() { | 282 testWhile() { |
274 final String source = r""" | 283 final String source = r""" |
275 class A { f() => new B(); } | 284 class A { f() => new B(); } |
276 class B { f() => new C(); } | 285 class B { f() => new C(); } |
277 class C { f() => new A(); } | 286 class C { f() => new A(); } |
278 main() { | 287 main() { |
279 var bar = null; | 288 var bar = null; |
280 var foo = new A(); | 289 var foo = new A(); |
281 while(bar = 42) { | 290 while(bar = 42) { |
282 foo = foo.f(); | 291 foo = foo.f(); |
283 } | 292 } |
284 foo; bar; | 293 foo; bar; |
285 } | 294 } |
286 """; | 295 """; |
287 AnalysisResult result = analyze(source); | 296 return analyze(source).then((result) { |
288 result.checkNodeHasType( | 297 result.checkNodeHasType( |
289 'foo', | 298 'foo', |
290 [result.base('A'), result.base('B'), result.base('C')]); | 299 [result.base('A'), result.base('B'), result.base('C')]); |
291 // Check that the condition is evaluated. | 300 // Check that the condition is evaluated. |
292 result.checkNodeHasType('bar', [result.int]); | 301 result.checkNodeHasType('bar', [result.int]); |
| 302 }); |
293 } | 303 } |
294 | 304 |
295 testDoWhile() { | 305 testDoWhile() { |
296 final String source = r""" | 306 final String source = r""" |
297 class A { f() => new B(); } | 307 class A { f() => new B(); } |
298 class B { f() => new C(); } | 308 class B { f() => new C(); } |
299 class C { f() => new A(); } | 309 class C { f() => new A(); } |
300 main() { | 310 main() { |
301 var bar = null; | 311 var bar = null; |
302 var foo = new A(); | 312 var foo = new A(); |
303 do { | 313 do { |
304 foo = foo.f(); | 314 foo = foo.f(); |
305 } while (bar = 42); | 315 } while (bar = 42); |
306 foo; bar; | 316 foo; bar; |
307 } | 317 } |
308 """; | 318 """; |
309 AnalysisResult result = analyze(source); | 319 return analyze(source).then((AnalysisResult result) { |
310 result.checkNodeHasType( | 320 result.checkNodeHasType( |
311 'foo', | 321 'foo', |
312 [result.base('A'), result.base('B'), result.base('C')]); | 322 [result.base('A'), result.base('B'), result.base('C')]); |
313 // Check that the condition is evaluated. | 323 // Check that the condition is evaluated. |
314 result.checkNodeHasType('bar', [result.int]); | 324 result.checkNodeHasType('bar', [result.int]); |
| 325 }); |
315 } | 326 } |
316 | 327 |
317 testFor1() { | 328 testFor1() { |
318 final String source = r""" | 329 final String source = r""" |
319 class A { f() => new B(); } | 330 class A { f() => new B(); } |
320 class B { f() => new C(); } | 331 class B { f() => new C(); } |
321 class C { f() => new A(); } | 332 class C { f() => new A(); } |
322 main() { | 333 main() { |
323 var foo = new A(); | 334 var foo = new A(); |
324 for(;;) { | 335 for(;;) { |
325 foo = foo.f(); | 336 foo = foo.f(); |
326 } | 337 } |
327 foo; | 338 foo; |
328 } | 339 } |
329 """; | 340 """; |
330 AnalysisResult result = analyze(source); | 341 return analyze(source).then((result) { |
331 result.checkNodeHasType( | 342 result.checkNodeHasType( |
332 'foo', | 343 'foo', |
333 [result.base('A'), result.base('B'), result.base('C')]); | 344 [result.base('A'), result.base('B'), result.base('C')]); |
| 345 }); |
334 } | 346 } |
335 | 347 |
336 testFor2() { | 348 testFor2() { |
337 final String source = r""" | 349 final String source = r""" |
338 class A { f() => new B(); test() => true; } | 350 class A { f() => new B(); test() => true; } |
339 class B { f() => new A(); test() => true; } | 351 class B { f() => new A(); test() => true; } |
340 main() { | 352 main() { |
341 var bar = null; | 353 var bar = null; |
342 var foo = new A(); | 354 var foo = new A(); |
343 for(var i = new A(); bar = 42; i = i.f()) { | 355 for(var i = new A(); bar = 42; i = i.f()) { |
344 foo = i; | 356 foo = i; |
345 } | 357 } |
346 foo; bar; | 358 foo; bar; |
347 } | 359 } |
348 """; | 360 """; |
349 AnalysisResult result = analyze(source); | 361 return analyze(source).then((result) { |
350 result.checkNodeHasType('foo', [result.base('A'), result.base('B')]); | 362 result.checkNodeHasType('foo', [result.base('A'), result.base('B')]); |
351 // Check that the condition is evaluated. | 363 // Check that the condition is evaluated. |
352 result.checkNodeHasType('bar', [result.int]); | 364 result.checkNodeHasType('bar', [result.int]); |
| 365 }); |
353 } | 366 } |
354 | 367 |
355 testFor3() { | 368 testFor3() { |
356 final String source = r""" | 369 final String source = r""" |
357 main() { | 370 main() { |
358 var i = 1; | 371 var i = 1; |
359 for(;;) { | 372 for(;;) { |
360 var x = 2; | 373 var x = 2; |
361 i = x; | 374 i = x; |
362 } | 375 } |
363 i; | 376 i; |
364 } | 377 } |
365 """; | 378 """; |
366 AnalysisResult result = analyze(source); | 379 return analyze(source).then((result) { |
367 result.checkNodeHasType('i', [result.int]); | 380 result.checkNodeHasType('i', [result.int]); |
| 381 }); |
368 } | 382 } |
369 | 383 |
370 testForIn() { | 384 testForIn() { |
371 final String source = r""" | 385 final String source = r""" |
372 class MyIterator { | 386 class MyIterator { |
373 var counter = 0; | 387 var counter = 0; |
374 | 388 |
375 moveNext() { | 389 moveNext() { |
376 if (counter == 0) { | 390 if (counter == 0) { |
377 counter = 1; | 391 counter = 1; |
(...skipping 14 matching lines...) Expand all Loading... |
392 } | 406 } |
393 | 407 |
394 main() { | 408 main() { |
395 var res; | 409 var res; |
396 for (var i in new MyIterable()) { | 410 for (var i in new MyIterable()) { |
397 res = i; | 411 res = i; |
398 } | 412 } |
399 res; | 413 res; |
400 } | 414 } |
401 """; | 415 """; |
402 AnalysisResult result = analyze(source); | 416 return analyze(source).then((AnalysisResult result) { |
403 result.checkNodeHasType('res', [result.int, result.string, result.nullType]); | 417 result.checkNodeHasType('res', |
| 418 [result.int, result.string, result.nullType]); |
| 419 }); |
404 } | 420 } |
405 | 421 |
406 testToplevelVariable() { | 422 testToplevelVariable() { |
407 final String source = r""" | 423 final String source = r""" |
408 final top = 'abc'; | 424 final top = 'abc'; |
409 class A { | 425 class A { |
410 f() => top; | 426 f() => top; |
411 } | 427 } |
412 main() { | 428 main() { |
413 var foo = top; | 429 var foo = top; |
414 var bar = new A().f(); | 430 var bar = new A().f(); |
415 foo; bar; | 431 foo; bar; |
416 } | 432 } |
417 """; | 433 """; |
418 AnalysisResult result = analyze(source); | 434 return analyze(source).then((result) { |
419 result.checkNodeHasType('foo', [result.string]); | 435 result.checkNodeHasType('foo', [result.string]); |
420 result.checkNodeHasType('bar', [result.string]); | 436 result.checkNodeHasType('bar', [result.string]); |
| 437 }); |
421 } | 438 } |
422 | 439 |
423 testNonRecusiveFunction() { | 440 testNonRecusiveFunction() { |
424 final String source = r""" | 441 final String source = r""" |
425 f(x, y) => true ? x : y; | 442 f(x, y) => true ? x : y; |
426 main() { var foo = f(42, "abc"); foo; } | 443 main() { var foo = f(42, "abc"); foo; } |
427 """; | 444 """; |
428 AnalysisResult result = analyze(source); | 445 return analyze(source).then((result) { |
429 result.checkNodeHasType('foo', [result.int, result.string]); | 446 result.checkNodeHasType('foo', [result.int, result.string]); |
| 447 }); |
430 } | 448 } |
431 | 449 |
432 testRecusiveFunction() { | 450 testRecusiveFunction() { |
433 final String source = r""" | 451 final String source = r""" |
434 f(x) { | 452 f(x) { |
435 if (true) return x; | 453 if (true) return x; |
436 else return f(true ? x : "abc"); | 454 else return f(true ? x : "abc"); |
437 } | 455 } |
438 main() { var foo = f(42); foo; } | 456 main() { var foo = f(42); foo; } |
439 """; | 457 """; |
440 AnalysisResult result = analyze(source); | 458 return analyze(source).then((result) { |
441 result.checkNodeHasType('foo', [result.int, result.string]); | 459 result.checkNodeHasType('foo', [result.int, result.string]); |
| 460 }); |
442 } | 461 } |
443 | 462 |
444 testMutuallyRecusiveFunction() { | 463 testMutuallyRecusiveFunction() { |
445 final String source = r""" | 464 final String source = r""" |
446 f() => true ? 42 : g(); | 465 f() => true ? 42 : g(); |
447 g() => true ? "abc" : f(); | 466 g() => true ? "abc" : f(); |
448 main() { var foo = f(); foo; } | 467 main() { var foo = f(); foo; } |
449 """; | 468 """; |
450 AnalysisResult result = analyze(source); | 469 return analyze(source).then((result) { |
451 result.checkNodeHasType('foo', [result.int, result.string]); | 470 result.checkNodeHasType('foo', [result.int, result.string]); |
| 471 }); |
452 } | 472 } |
453 | 473 |
454 testSimpleSend() { | 474 testSimpleSend() { |
455 final String source = r""" | 475 final String source = r""" |
456 class A { | 476 class A { |
457 f(x) => x; | 477 f(x) => x; |
458 } | 478 } |
459 class B { | 479 class B { |
460 f(x) => 'abc'; | 480 f(x) => 'abc'; |
461 } | 481 } |
462 class C { | 482 class C { |
463 f(x) => 3.14; | 483 f(x) => 3.14; |
464 } | 484 } |
465 class D { | 485 class D { |
466 var f; // we check that this field is ignored in calls to dynamic.f() | 486 var f; // we check that this field is ignored in calls to dynamic.f() |
467 D(this.f); | 487 D(this.f); |
468 } | 488 } |
469 main() { | 489 main() { |
470 new B(); new D(42); // we instantiate B and D but not C | 490 new B(); new D(42); // we instantiate B and D but not C |
471 var foo = new A().f(42); | 491 var foo = new A().f(42); |
472 var bar = "__dynamic_for_test".f(42); | 492 var bar = "__dynamic_for_test".f(42); |
473 foo; bar; | 493 foo; bar; |
474 } | 494 } |
475 """; | 495 """; |
476 AnalysisResult result = analyze(source); | 496 return analyze(source).then((result) { |
477 result.checkNodeHasType('foo', [result.int]); | 497 result.checkNodeHasType('foo', [result.int]); |
478 result.checkNodeHasType('bar', [result.int, result.string]); | 498 result.checkNodeHasType('bar', [result.int, result.string]); |
| 499 }); |
479 } | 500 } |
480 | 501 |
481 testSendToClosureField() { | 502 testSendToClosureField() { |
482 final String source = r""" | 503 final String source = r""" |
483 f(x) => x; | 504 f(x) => x; |
484 class A { | 505 class A { |
485 var g; | 506 var g; |
486 A(this.g); | 507 A(this.g); |
487 } | 508 } |
488 main() { | 509 main() { |
489 var foo = new A(f).g(42); | 510 var foo = new A(f).g(42); |
490 foo; | 511 foo; |
491 } | 512 } |
492 """; | 513 """; |
493 AnalysisResult result = analyze(source); | 514 return analyze(source).then((result) { |
494 result.checkNodeHasType('foo', [result.int]); | 515 result.checkNodeHasType('foo', [result.int]); |
| 516 }); |
495 } | 517 } |
496 | 518 |
497 testSendToThis1() { | 519 testSendToThis1() { |
498 final String source = r""" | 520 final String source = r""" |
499 class A { | 521 class A { |
500 A(); | 522 A(); |
501 f() => g(); | 523 f() => g(); |
502 g() => 42; | 524 g() => 42; |
503 } | 525 } |
504 main() { | 526 main() { |
505 var foo = new A().f(); | 527 var foo = new A().f(); |
506 foo; | 528 foo; |
507 } | 529 } |
508 """; | 530 """; |
509 AnalysisResult result = analyze(source); | 531 return analyze(source).then((result) { |
510 result.checkNodeHasType('foo', [result.int]); | 532 result.checkNodeHasType('foo', [result.int]); |
| 533 }); |
511 } | 534 } |
512 | 535 |
513 testSendToThis2() { | 536 testSendToThis2() { |
514 final String source = r""" | 537 final String source = r""" |
515 class A { | 538 class A { |
516 foo() => this; | 539 foo() => this; |
517 } | 540 } |
518 class B extends A { | 541 class B extends A { |
519 bar() => foo(); | 542 bar() => foo(); |
520 } | 543 } |
521 main() { | 544 main() { |
522 var x = new B().bar(); | 545 var x = new B().bar(); |
523 x; | 546 x; |
524 } | 547 } |
525 """; | 548 """; |
526 AnalysisResult result = analyze(source); | 549 return analyze(source).then((result) { |
527 result.checkNodeHasType('x', [result.base('B')]); | 550 result.checkNodeHasType('x', [result.base('B')]); |
| 551 }); |
528 } | 552 } |
529 | 553 |
530 testSendToThis3() { | 554 testSendToThis3() { |
531 final String source = r""" | 555 final String source = r""" |
532 class A { | 556 class A { |
533 bar() => 42; | 557 bar() => 42; |
534 foo() => bar(); | 558 foo() => bar(); |
535 } | 559 } |
536 class B extends A { | 560 class B extends A { |
537 bar() => "abc"; | 561 bar() => "abc"; |
538 } | 562 } |
539 main() { | 563 main() { |
540 var x = new B().foo(); | 564 var x = new B().foo(); |
541 x; | 565 x; |
542 } | 566 } |
543 """; | 567 """; |
544 AnalysisResult result = analyze(source); | 568 return analyze(source).then((AnalysisResult result) { |
545 result.checkNodeHasType('x', [result.string]); | 569 result.checkNodeHasType('x', [result.string]); |
| 570 }); |
546 } | 571 } |
547 | 572 |
548 testConstructor() { | 573 testConstructor() { |
549 final String source = r""" | 574 final String source = r""" |
550 class A { | 575 class A { |
551 var x, y, z; | 576 var x, y, z; |
552 A(this.x, a) : y = a { z = 'abc'; } | 577 A(this.x, a) : y = a { z = 'abc'; } |
553 } | 578 } |
554 main() { | 579 main() { |
555 new A(42, 'abc'); | 580 new A(42, 'abc'); |
556 new A(true, null); | 581 new A(true, null); |
557 } | 582 } |
558 """; | 583 """; |
559 AnalysisResult result = analyze(source); | 584 return analyze(source).then((result) { |
560 result.checkFieldHasType('A', 'x', [result.int, result.bool]); | 585 result.checkFieldHasType('A', 'x', [result.int, result.bool]); |
561 result.checkFieldHasType('A', 'y', [result.string, result.nullType]); | 586 result.checkFieldHasType('A', 'y', [result.string, result.nullType]); |
562 // TODO(polux): we can be smarter and infer {string} for z | 587 // TODO(polux): we can be smarter and infer {string} for z |
563 result.checkFieldHasType('A', 'z', [result.string, result.nullType]); | 588 result.checkFieldHasType('A', 'z', [result.string, result.nullType]); |
| 589 }); |
564 } | 590 } |
565 | 591 |
566 testGetters() { | 592 testGetters() { |
567 final String source = r""" | 593 final String source = r""" |
568 class A { | 594 class A { |
569 var x; | 595 var x; |
570 A(this.x); | 596 A(this.x); |
571 get y => x; | 597 get y => x; |
572 get z => y; | 598 get z => y; |
573 } | 599 } |
574 class B { | 600 class B { |
575 var x; | 601 var x; |
576 B(this.x); | 602 B(this.x); |
577 } | 603 } |
578 main() { | 604 main() { |
579 var a = new A(42); | 605 var a = new A(42); |
580 var b = new B('abc'); | 606 var b = new B('abc'); |
581 var foo = a.x; | 607 var foo = a.x; |
582 var bar = a.y; | 608 var bar = a.y; |
583 var baz = a.z; | 609 var baz = a.z; |
584 var qux = null.x; | 610 var qux = null.x; |
585 var quux = "__dynamic_for_test".x; | 611 var quux = "__dynamic_for_test".x; |
586 foo; bar; baz; qux; quux; | 612 foo; bar; baz; qux; quux; |
587 } | 613 } |
588 """; | 614 """; |
589 AnalysisResult result = analyze(source); | 615 return analyze(source).then((result) { |
590 result.checkNodeHasType('foo', [result.int]); | 616 result.checkNodeHasType('foo', [result.int]); |
591 result.checkNodeHasType('bar', [result.int]); | 617 result.checkNodeHasType('bar', [result.int]); |
592 result.checkNodeHasType('baz', [result.int]); | 618 result.checkNodeHasType('baz', [result.int]); |
593 result.checkNodeHasType('qux', []); | 619 result.checkNodeHasType('qux', []); |
594 result.checkNodeHasType('quux', [result.int, result.string]); | 620 result.checkNodeHasType('quux', [result.int, result.string]); |
| 621 }); |
595 } | 622 } |
596 | 623 |
597 testSetters() { | 624 testSetters() { |
598 final String source = r""" | 625 final String source = r""" |
599 class A { | 626 class A { |
600 var x; | 627 var x; |
601 var w; | 628 var w; |
602 A(this.x, this.w); | 629 A(this.x, this.w); |
603 set y(a) { x = a; z = a; } | 630 set y(a) { x = a; z = a; } |
604 set z(a) { w = a; } | 631 set z(a) { w = a; } |
605 } | 632 } |
606 class B { | 633 class B { |
607 var x; | 634 var x; |
608 B(this.x); | 635 B(this.x); |
609 } | 636 } |
610 main() { | 637 main() { |
611 var a = new A(42, 42); | 638 var a = new A(42, 42); |
612 var b = new B(42); | 639 var b = new B(42); |
613 a.x = 'abc'; | 640 a.x = 'abc'; |
614 a.y = true; | 641 a.y = true; |
615 null.x = 42; // should be ignored | 642 null.x = 42; // should be ignored |
616 "__dynamic_for_test".x = null; | 643 "__dynamic_for_test".x = null; |
617 "__dynamic_for_test".y = 3.14; | 644 "__dynamic_for_test".y = 3.14; |
618 } | 645 } |
619 """; | 646 """; |
620 AnalysisResult result = analyze(source); | 647 return analyze(source).then((result) { |
621 result.checkFieldHasType('B', 'x', | 648 result.checkFieldHasType('B', 'x', |
622 [result.int, // new B(42) | 649 [result.int, // new B(42) |
623 result.nullType]); // dynamic.x = null | 650 result.nullType]); // dynamic.x = null |
624 result.checkFieldHasType('A', 'x', | 651 result.checkFieldHasType('A', 'x', |
625 [result.int, // new A(42, ...) | 652 [result.int, // new A(42, ...) |
626 result.string, // a.x = 'abc' | 653 result.string, // a.x = 'abc' |
627 result.bool, // a.y = true | 654 result.bool, // a.y = true |
628 result.nullType, // dynamic.x = null | 655 result.nullType, // dynamic.x = null |
629 result.double]); // dynamic.y = 3.14 | 656 result.double]); // dynamic.y = 3.14 |
630 result.checkFieldHasType('A', 'w', | 657 result.checkFieldHasType('A', 'w', |
631 [result.int, // new A(..., 42) | 658 [result.int, // new A(..., 42) |
632 result.bool, // a.y = true | 659 result.bool, // a.y = true |
633 result.double]); // dynamic.y = double | 660 result.double]); // dynamic.y = double |
| 661 }); |
634 } | 662 } |
635 | 663 |
636 testOptionalNamedParameters() { | 664 testOptionalNamedParameters() { |
637 final String source = r""" | 665 final String source = r""" |
638 class A { | 666 class A { |
639 var x, y, z, w; | 667 var x, y, z, w; |
640 A(this.x, {this.y, this.z, this.w}); | 668 A(this.x, {this.y, this.z, this.w}); |
641 } | 669 } |
642 class B { | 670 class B { |
643 var x, y; | 671 var x, y; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
688 new B(1, 2); // too many positional arguments | 716 new B(1, 2); // too many positional arguments |
689 test.f2('abc', y: true); | 717 test.f2('abc', y: true); |
690 test.f2(1, 2); // too many positional arguments | 718 test.f2(1, 2); // too many positional arguments |
691 | 719 |
692 new C('abc', y: true); | 720 new C('abc', y: true); |
693 new C(1, z: 2); // non-existing named parameter | 721 new C(1, z: 2); // non-existing named parameter |
694 test.f3('abc', y: true); | 722 test.f3('abc', y: true); |
695 test.f3(1, z: 2); // non-existing named parameter | 723 test.f3(1, z: 2); // non-existing named parameter |
696 } | 724 } |
697 """; | 725 """; |
698 AnalysisResult result = analyze(source); | 726 return analyze(source).then((result) { |
699 | 727 |
700 final foo = result.base('Foo'); | 728 final foo = result.base('Foo'); |
701 final nil = result.nullType; | 729 final nil = result.nullType; |
702 | 730 |
703 result.checkFieldHasType('A', 'x', [result.int, result.string]); | 731 result.checkFieldHasType('A', 'x', [result.int, result.string]); |
704 result.checkFieldHasType('A', 'y', [nil]); | 732 result.checkFieldHasType('A', 'y', [nil]); |
705 result.checkFieldHasType('A', 'z', [nil, result.double]); | 733 result.checkFieldHasType('A', 'z', [nil, result.double]); |
706 result.checkFieldHasType('A', 'w', [nil, result.bool]); | 734 result.checkFieldHasType('A', 'w', [nil, result.bool]); |
707 result.checkFieldHasType('Test', 'a', [foo, result.int, result.string]); | 735 result.checkFieldHasType('Test', 'a', [foo, result.int, result.string]); |
708 result.checkFieldHasType('Test', 'b', [foo, nil]); | 736 result.checkFieldHasType('Test', 'b', [foo, nil]); |
709 result.checkFieldHasType('Test', 'c', [foo, nil, result.double]); | 737 result.checkFieldHasType('Test', 'c', [foo, nil, result.double]); |
710 result.checkFieldHasType('Test', 'd', [foo, nil, result.bool]); | 738 result.checkFieldHasType('Test', 'd', [foo, nil, result.bool]); |
711 | 739 |
712 result.checkFieldHasType('B', 'x', [result.string]); | 740 result.checkFieldHasType('B', 'x', [result.string]); |
713 result.checkFieldHasType('B', 'y', [result.bool]); | 741 result.checkFieldHasType('B', 'y', [result.bool]); |
714 result.checkFieldHasType('Test', 'e', [foo, result.string]); | 742 result.checkFieldHasType('Test', 'e', [foo, result.string]); |
715 result.checkFieldHasType('Test', 'f', [foo, result.bool]); | 743 result.checkFieldHasType('Test', 'f', [foo, result.bool]); |
716 | 744 |
717 result.checkFieldHasType('C', 'x', [result.string]); | 745 result.checkFieldHasType('C', 'x', [result.string]); |
718 result.checkFieldHasType('C', 'y', [result.bool]); | 746 result.checkFieldHasType('C', 'y', [result.bool]); |
719 result.checkFieldHasType('Test', 'g', [foo, result.string]); | 747 result.checkFieldHasType('Test', 'g', [foo, result.string]); |
720 result.checkFieldHasType('Test', 'h', [foo, result.bool]); | 748 result.checkFieldHasType('Test', 'h', [foo, result.bool]); |
| 749 }); |
721 } | 750 } |
722 | 751 |
723 testOptionalPositionalParameters() { | 752 testOptionalPositionalParameters() { |
724 final String source = r""" | 753 final String source = r""" |
725 class A { | 754 class A { |
726 var x, y, z, w; | 755 var x, y, z, w; |
727 A(this.x, [this.y, this.z, this.w]); | 756 A(this.x, [this.y, this.z, this.w]); |
728 } | 757 } |
729 class B { | 758 class B { |
730 var x, y; | 759 var x, y; |
(...skipping 29 matching lines...) Expand all Loading... |
760 new A('abc', true, 42.0); | 789 new A('abc', true, 42.0); |
761 test.f1(42); | 790 test.f1(42); |
762 test.f1('abc', true, 42.0); | 791 test.f1('abc', true, 42.0); |
763 | 792 |
764 new B('a', true); | 793 new B('a', true); |
765 new B(1, 2, 3); // too many arguments | 794 new B(1, 2, 3); // too many arguments |
766 test.f2('a', true); | 795 test.f2('a', true); |
767 test.f2(1, 2, 3); // too many arguments | 796 test.f2(1, 2, 3); // too many arguments |
768 } | 797 } |
769 """; | 798 """; |
770 AnalysisResult result = analyze(source); | 799 return analyze(source).then((result) { |
771 | 800 |
772 final foo = result.base('Foo'); | 801 final foo = result.base('Foo'); |
773 final nil = result.nullType; | 802 final nil = result.nullType; |
774 | 803 |
775 result.checkFieldHasType('A', 'x', [result.int, result.string]); | 804 result.checkFieldHasType('A', 'x', [result.int, result.string]); |
776 result.checkFieldHasType('A', 'y', [nil, result.bool]); | 805 result.checkFieldHasType('A', 'y', [nil, result.bool]); |
777 result.checkFieldHasType('A', 'z', [nil, result.double]); | 806 result.checkFieldHasType('A', 'z', [nil, result.double]); |
778 result.checkFieldHasType('A', 'w', [nil]); | 807 result.checkFieldHasType('A', 'w', [nil]); |
779 result.checkFieldHasType('Test', 'a', [foo, result.int, result.string]); | 808 result.checkFieldHasType('Test', 'a', [foo, result.int, result.string]); |
780 result.checkFieldHasType('Test', 'b', [foo, nil, result.bool]); | 809 result.checkFieldHasType('Test', 'b', [foo, nil, result.bool]); |
781 result.checkFieldHasType('Test', 'c', [foo, nil, result.double]); | 810 result.checkFieldHasType('Test', 'c', [foo, nil, result.double]); |
782 result.checkFieldHasType('Test', 'd', [foo, nil]); | 811 result.checkFieldHasType('Test', 'd', [foo, nil]); |
783 | 812 |
784 result.checkFieldHasType('B', 'x', [result.string]); | 813 result.checkFieldHasType('B', 'x', [result.string]); |
785 result.checkFieldHasType('B', 'y', [result.bool]); | 814 result.checkFieldHasType('B', 'y', [result.bool]); |
786 result.checkFieldHasType('Test', 'e', [foo, result.string]); | 815 result.checkFieldHasType('Test', 'e', [foo, result.string]); |
787 result.checkFieldHasType('Test', 'f', [foo, result.bool]); | 816 result.checkFieldHasType('Test', 'f', [foo, result.bool]); |
| 817 }); |
788 } | 818 } |
789 | 819 |
790 testListLiterals() { | 820 testListLiterals() { |
791 final String source = r""" | 821 final String source = r""" |
792 class A { | 822 class A { |
793 var x; | 823 var x; |
794 A(this.x); | 824 A(this.x); |
795 } | 825 } |
796 main() { | 826 main() { |
797 var x = []; | 827 var x = []; |
798 var y = [1, "a", null, new A(42)]; | 828 var y = [1, "a", null, new A(42)]; |
799 x; y; | 829 x; y; |
800 } | 830 } |
801 """; | 831 """; |
802 AnalysisResult result = analyze(source); | 832 return analyze(source).then((result) { |
803 result.checkNodeHasType('x', [result.growableList]); | 833 result.checkNodeHasType('x', [result.growableList]); |
804 result.checkNodeHasType('y', [result.growableList]); | 834 result.checkNodeHasType('y', [result.growableList]); |
805 result.checkFieldHasType('A', 'x', [result.int]); | 835 result.checkFieldHasType('A', 'x', [result.int]); |
| 836 }); |
806 } | 837 } |
807 | 838 |
808 testMapLiterals() { | 839 testMapLiterals() { |
809 final String source = r""" | 840 final String source = r""" |
810 class A { | 841 class A { |
811 var x; | 842 var x; |
812 A(this.x); | 843 A(this.x); |
813 } | 844 } |
814 main() { | 845 main() { |
815 var x = {}; | 846 var x = {}; |
816 var y = {'a': "foo", 'b': new A(42) }; | 847 var y = {'a': "foo", 'b': new A(42) }; |
817 x; y; | 848 x; y; |
818 } | 849 } |
819 """; | 850 """; |
820 AnalysisResult result = analyze(source); | 851 return analyze(source).then((result) { |
821 result.checkNodeHasType('x', [result.map]); | 852 result.checkNodeHasType('x', [result.map]); |
822 result.checkNodeHasType('y', [result.map]); | 853 result.checkNodeHasType('y', [result.map]); |
823 result.checkFieldHasType('A', 'x', [result.int]); | 854 result.checkFieldHasType('A', 'x', [result.int]); |
| 855 }); |
824 } | 856 } |
825 | 857 |
826 testReturn() { | 858 testReturn() { |
827 final String source = r""" | 859 final String source = r""" |
828 f() { if (true) { return 1; }; return "a"; } | 860 f() { if (true) { return 1; }; return "a"; } |
829 g() { f(); return; } | 861 g() { f(); return; } |
830 main() { | 862 main() { |
831 var x = f(); | 863 var x = f(); |
832 var y = g(); | 864 var y = g(); |
833 x; y; | 865 x; y; |
834 } | 866 } |
835 """; | 867 """; |
836 AnalysisResult result = analyze(source); | 868 return analyze(source).then((result) { |
837 result.checkNodeHasType('x', [result.int, result.string]); | 869 result.checkNodeHasType('x', [result.int, result.string]); |
838 result.checkNodeHasType('y', [result.nullType]); | 870 result.checkNodeHasType('y', [result.nullType]); |
| 871 }); |
839 } | 872 } |
840 | 873 |
841 testNoReturn() { | 874 testNoReturn() { |
842 final String source = r""" | 875 final String source = r""" |
843 f() { if (true) { return 1; }; } | 876 f() { if (true) { return 1; }; } |
844 g() { f(); } | 877 g() { f(); } |
845 main() { | 878 main() { |
846 var x = f(); | 879 var x = f(); |
847 var y = g(); | 880 var y = g(); |
848 x; y; | 881 x; y; |
849 } | 882 } |
850 """; | 883 """; |
851 AnalysisResult result = analyze(source); | 884 return analyze(source).then((result) { |
852 result.checkNodeHasType('x', [result.int, result.nullType]); | 885 result.checkNodeHasType('x', [result.int, result.nullType]); |
853 result.checkNodeHasType('y', [result.nullType]); | 886 result.checkNodeHasType('y', [result.nullType]); |
| 887 }); |
854 } | 888 } |
855 | 889 |
856 testArithmeticOperators() { | 890 testArithmeticOperators() { |
857 String source(op) { | 891 String source(op) { |
858 return """ | 892 return """ |
859 main() { | 893 main() { |
860 var a = 1 $op 2; | 894 var a = 1 $op 2; |
861 var b = 1 $op 2.0; | 895 var b = 1 $op 2.0; |
862 var c = 1.0 $op 2; | 896 var c = 1.0 $op 2; |
863 var d = 1.0 $op 2.0; | 897 var d = 1.0 $op 2.0; |
864 var e = (1 $op 2.0) $op 1; | 898 var e = (1 $op 2.0) $op 1; |
865 var f = 1 $op (1 $op 2.0); | 899 var f = 1 $op (1 $op 2.0); |
866 var g = (1 $op 2.0) $op 1.0; | 900 var g = (1 $op 2.0) $op 1.0; |
867 var h = 1.0 $op (1 $op 2); | 901 var h = 1.0 $op (1 $op 2); |
868 var i = (1 $op 2) $op 1; | 902 var i = (1 $op 2) $op 1; |
869 var j = 1 $op (1 $op 2); | 903 var j = 1 $op (1 $op 2); |
870 var k = (1.0 $op 2.0) $op 1.0; | 904 var k = (1.0 $op 2.0) $op 1.0; |
871 var l = 1.0 $op (1.0 $op 2.0); | 905 var l = 1.0 $op (1.0 $op 2.0); |
872 a; b; c; d; e; f; g; h; i; j; k; l; | 906 a; b; c; d; e; f; g; h; i; j; k; l; |
873 }"""; | 907 }"""; |
874 } | 908 } |
875 for (String op in ['+', '*', '-']) { | 909 return Future.forEach(['+', '*', '-'], (String op) { |
876 AnalysisResult result = analyze(source(op)); | 910 return analyze(source(op)).then((result) { |
877 result.checkNodeHasType('a', [result.int]); | 911 result.checkNodeHasType('a', [result.int]); |
878 result.checkNodeHasType('b', [result.num]); | 912 result.checkNodeHasType('b', [result.num]); |
879 result.checkNodeHasType('c', [result.num]); | 913 result.checkNodeHasType('c', [result.num]); |
880 result.checkNodeHasType('d', [result.double]); | 914 result.checkNodeHasType('d', [result.double]); |
881 result.checkNodeHasType('e', [result.num]); | 915 result.checkNodeHasType('e', [result.num]); |
882 result.checkNodeHasType('f', [result.num]); | 916 result.checkNodeHasType('f', [result.num]); |
883 result.checkNodeHasType('g', [result.num]); | 917 result.checkNodeHasType('g', [result.num]); |
884 result.checkNodeHasType('h', [result.num]); | 918 result.checkNodeHasType('h', [result.num]); |
885 result.checkNodeHasType('i', [result.int]); | 919 result.checkNodeHasType('i', [result.int]); |
886 result.checkNodeHasType('j', [result.int]); | 920 result.checkNodeHasType('j', [result.int]); |
887 result.checkNodeHasType('k', [result.double]); | 921 result.checkNodeHasType('k', [result.double]); |
888 result.checkNodeHasType('l', [result.double]); | 922 result.checkNodeHasType('l', [result.double]); |
889 } | 923 }); |
| 924 }); |
890 } | 925 } |
891 | 926 |
892 testBooleanOperators() { | 927 testBooleanOperators() { |
893 String source(op) { | 928 String source(op) { |
894 return """ | 929 return """ |
895 main() { | 930 main() { |
896 var a = true $op null; | 931 var a = true $op null; |
897 var b = null $op true; | 932 var b = null $op true; |
898 var c = 1 $op true; | 933 var c = 1 $op true; |
899 var d = true $op "a"; | 934 var d = true $op "a"; |
900 a; b; c; d; | 935 a; b; c; d; |
901 }"""; | 936 }"""; |
902 } | 937 } |
903 for (String op in ['&&', '||']) { | 938 return Future.forEach(['&&', '||'], (String op) { |
904 AnalysisResult result = analyze(source(op)); | 939 return analyze(source(op)).then((result) { |
905 result.checkNodeHasType('a', [result.bool]); | 940 result.checkNodeHasType('a', [result.bool]); |
906 result.checkNodeHasType('b', [result.bool]); | 941 result.checkNodeHasType('b', [result.bool]); |
907 result.checkNodeHasType('c', [result.bool]); | 942 result.checkNodeHasType('c', [result.bool]); |
908 result.checkNodeHasType('d', [result.bool]); | 943 result.checkNodeHasType('d', [result.bool]); |
909 } | 944 }); |
| 945 }); |
910 } | 946 } |
911 | 947 |
912 testBooleanOperatorsShortCirtcuit() { | 948 testBooleanOperatorsShortCirtcuit() { |
913 String source(op) { | 949 String source(op) { |
914 return """ | 950 return """ |
915 main() { | 951 main() { |
916 var x = null; | 952 var x = null; |
917 "foo" $op (x = 42); | 953 "foo" $op (x = 42); |
918 x; | 954 x; |
919 }"""; | 955 }"""; |
920 } | 956 } |
921 for (String op in ['&&', '||']) { | 957 return Future.forEach(['&&', '||'], (String op) { |
922 AnalysisResult result = analyze(source(op)); | 958 return analyze(source(op)).then((AnalysisResult result) { |
923 result.checkNodeHasType('x', [result.nullType, result.int]); | 959 result.checkNodeHasType('x', [result.nullType, result.int]); |
924 } | 960 }); |
| 961 }); |
925 } | 962 } |
926 | 963 |
927 testOperators() { | 964 testOperators() { |
928 final String source = r""" | 965 final String source = r""" |
929 class A { | 966 class A { |
930 operator <(x) => 42; | 967 operator <(x) => 42; |
931 operator <<(x) => "a"; | 968 operator <<(x) => "a"; |
932 } | 969 } |
933 main() { | 970 main() { |
934 var x = new A() < "foo"; | 971 var x = new A() < "foo"; |
935 var y = new A() << "foo"; | 972 var y = new A() << "foo"; |
936 x; y; | 973 x; y; |
937 } | 974 } |
938 """; | 975 """; |
939 AnalysisResult result = analyze(source); | 976 return analyze(source).then((result) { |
940 result.checkNodeHasType('x', [result.int]); | 977 result.checkNodeHasType('x', [result.int]); |
941 result.checkNodeHasType('y', [result.string]); | 978 result.checkNodeHasType('y', [result.string]); |
| 979 }); |
942 } | 980 } |
943 | 981 |
944 testSetIndexOperator() { | 982 testSetIndexOperator() { |
945 final String source = r""" | 983 final String source = r""" |
946 class A { | 984 class A { |
947 var witness1; | 985 var witness1; |
948 var witness2; | 986 var witness2; |
949 operator []=(i, x) { witness1 = i; witness2 = x; } | 987 operator []=(i, x) { witness1 = i; witness2 = x; } |
950 } | 988 } |
951 main() { | 989 main() { |
952 var x = new A()[42] = "abc"; | 990 var x = new A()[42] = "abc"; |
953 x; | 991 x; |
954 } | 992 } |
955 """; | 993 """; |
956 AnalysisResult result = analyze(source); | 994 return analyze(source).then((result) { |
957 result.checkNodeHasType('x', [result.string]); | 995 result.checkNodeHasType('x', [result.string]); |
958 result.checkFieldHasType('A', 'witness1', [result.int, result.nullType]); | 996 result.checkFieldHasType('A', 'witness1', [result.int, result.nullType]); |
959 result.checkFieldHasType('A', 'witness2', [result.string, result.nullType]); | 997 result.checkFieldHasType('A', 'witness2', [result.string, result.nullType]); |
| 998 }); |
960 } | 999 } |
961 | 1000 |
962 testCompoundOperators1() { | 1001 testCompoundOperators1() { |
963 final String source = r""" | 1002 final String source = r""" |
964 class A { | 1003 class A { |
965 operator +(x) => "foo"; | 1004 operator +(x) => "foo"; |
966 } | 1005 } |
967 main() { | 1006 main() { |
968 var x1 = 1; | 1007 var x1 = 1; |
969 x1++; | 1008 x1++; |
970 var x2 = 1; | 1009 var x2 = 1; |
971 ++x2; | 1010 ++x2; |
972 var x3 = 1; | 1011 var x3 = 1; |
973 x3 += 42; | 1012 x3 += 42; |
974 var x4 = new A(); | 1013 var x4 = new A(); |
975 x4++; | 1014 x4++; |
976 var x5 = new A(); | 1015 var x5 = new A(); |
977 ++x5; | 1016 ++x5; |
978 var x6 = new A(); | 1017 var x6 = new A(); |
979 x6 += true; | 1018 x6 += true; |
980 | 1019 |
981 x1; x2; x3; x4; x5; x6; | 1020 x1; x2; x3; x4; x5; x6; |
982 } | 1021 } |
983 """; | 1022 """; |
984 AnalysisResult result = analyze(source); | 1023 return analyze(source).then((result) { |
985 result.checkNodeHasType('x1', [result.int]); | 1024 result.checkNodeHasType('x1', [result.int]); |
986 result.checkNodeHasType('x2', [result.int]); | 1025 result.checkNodeHasType('x2', [result.int]); |
987 result.checkNodeHasType('x3', [result.int]); | 1026 result.checkNodeHasType('x3', [result.int]); |
988 result.checkNodeHasType('x4', [result.string]); | 1027 result.checkNodeHasType('x4', [result.string]); |
989 result.checkNodeHasType('x5', [result.string]); | 1028 result.checkNodeHasType('x5', [result.string]); |
990 result.checkNodeHasType('x6', [result.string]); | 1029 result.checkNodeHasType('x6', [result.string]); |
| 1030 }); |
991 } | 1031 } |
992 | 1032 |
993 | 1033 |
994 testCompoundOperators2() { | 1034 testCompoundOperators2() { |
995 final String source = r""" | 1035 final String source = r""" |
996 class A { | 1036 class A { |
997 var xx; | 1037 var xx; |
998 var yy; | 1038 var yy; |
999 var witness1; | 1039 var witness1; |
1000 var witness2; | 1040 var witness2; |
1001 var witness3; | 1041 var witness3; |
1002 var witness4; | 1042 var witness4; |
1003 | 1043 |
1004 A(this.xx, this.yy); | 1044 A(this.xx, this.yy); |
1005 get x { witness1 = "foo"; return xx; } | 1045 get x { witness1 = "foo"; return xx; } |
1006 set x(a) { witness2 = "foo"; xx = a; } | 1046 set x(a) { witness2 = "foo"; xx = a; } |
1007 get y { witness3 = "foo"; return yy; } | 1047 get y { witness3 = "foo"; return yy; } |
1008 set y(a) { witness4 = "foo"; yy = a; } | 1048 set y(a) { witness4 = "foo"; yy = a; } |
1009 } | 1049 } |
1010 main () { | 1050 main () { |
1011 var a = new A(1, 1); | 1051 var a = new A(1, 1); |
1012 a.x++; | 1052 a.x++; |
1013 a.y++; | 1053 a.y++; |
1014 } | 1054 } |
1015 """; | 1055 """; |
1016 AnalysisResult result = analyze(source); | 1056 return analyze(source).then((result) { |
1017 result.checkFieldHasType('A', 'xx', [result.int]); | 1057 result.checkFieldHasType('A', 'xx', [result.int]); |
1018 result.checkFieldHasType('A', 'yy', [result.int]); | 1058 result.checkFieldHasType('A', 'yy', [result.int]); |
1019 result.checkFieldHasType('A', 'witness1', [result.string, result.nullType]); | 1059 result.checkFieldHasType('A', 'witness1', [result.string, result.nullType]); |
1020 result.checkFieldHasType('A', 'witness2', [result.string, result.nullType]); | 1060 result.checkFieldHasType('A', 'witness2', [result.string, result.nullType]); |
1021 result.checkFieldHasType('A', 'witness3', [result.string, result.nullType]); | 1061 result.checkFieldHasType('A', 'witness3', [result.string, result.nullType]); |
1022 result.checkFieldHasType('A', 'witness4', [result.string, result.nullType]); | 1062 result.checkFieldHasType('A', 'witness4', [result.string, result.nullType]); |
| 1063 }); |
1023 } | 1064 } |
1024 | 1065 |
1025 testInequality() { | 1066 testInequality() { |
1026 final String source = r""" | 1067 final String source = r""" |
1027 class A { | 1068 class A { |
1028 var witness; | 1069 var witness; |
1029 operator ==(x) { witness = "foo"; return "abc"; } | 1070 operator ==(x) { witness = "foo"; return "abc"; } |
1030 } | 1071 } |
1031 class B { | 1072 class B { |
1032 operator ==(x) { throw "error"; } | 1073 operator ==(x) { throw "error"; } |
1033 } | 1074 } |
1034 main() { | 1075 main() { |
1035 var foo = 1 != 2; | 1076 var foo = 1 != 2; |
1036 var bar = new A() != 2; | 1077 var bar = new A() != 2; |
1037 var baz = new B() != 2; | 1078 var baz = new B() != 2; |
1038 foo; bar; baz; | 1079 foo; bar; baz; |
1039 } | 1080 } |
1040 """; | 1081 """; |
1041 AnalysisResult result = analyze(source); | 1082 return analyze(source).then((result) { |
1042 result.checkNodeHasType('foo', [result.bool]); | 1083 result.checkNodeHasType('foo', [result.bool]); |
1043 result.checkNodeHasType('bar', [result.bool]); | 1084 result.checkNodeHasType('bar', [result.bool]); |
1044 result.checkNodeHasType('baz', []); | 1085 result.checkNodeHasType('baz', []); |
1045 result.checkFieldHasType('A', 'witness', [result.string, result.nullType]); | 1086 result.checkFieldHasType('A', 'witness', [result.string, result.nullType]); |
| 1087 }); |
1046 } | 1088 } |
1047 | 1089 |
1048 testFieldInitialization1() { | 1090 testFieldInitialization1() { |
1049 final String source = r""" | 1091 final String source = r""" |
1050 class A { | 1092 class A { |
1051 var x; | 1093 var x; |
1052 var y = 1; | 1094 var y = 1; |
1053 } | 1095 } |
1054 class B extends A { | 1096 class B extends A { |
1055 var z = "foo"; | 1097 var z = "foo"; |
1056 } | 1098 } |
1057 main () { | 1099 main () { |
1058 new B(); | 1100 new B(); |
1059 } | 1101 } |
1060 """; | 1102 """; |
1061 AnalysisResult result = analyze(source); | 1103 return analyze(source).then((result) { |
1062 result.checkFieldHasType('A', 'x', [result.nullType]); | 1104 result.checkFieldHasType('A', 'x', [result.nullType]); |
1063 result.checkFieldHasType('A', 'y', [result.int]); | 1105 result.checkFieldHasType('A', 'y', [result.int]); |
1064 result.checkFieldHasType('B', 'z', [result.string]); | 1106 result.checkFieldHasType('B', 'z', [result.string]); |
| 1107 }); |
1065 } | 1108 } |
1066 | 1109 |
1067 testFieldInitialization2() { | 1110 testFieldInitialization2() { |
1068 final String source = r""" | 1111 final String source = r""" |
1069 var top = 42; | 1112 var top = 42; |
1070 class A { | 1113 class A { |
1071 var x = top; | 1114 var x = top; |
1072 } | 1115 } |
1073 main () { | 1116 main () { |
1074 new A(); | 1117 new A(); |
1075 } | 1118 } |
1076 """; | 1119 """; |
1077 AnalysisResult result = analyze(source); | 1120 return analyze(source).then((result) { |
1078 result.checkFieldHasType('A', 'x', [result.int]); | 1121 result.checkFieldHasType('A', 'x', [result.int]); |
| 1122 }); |
1079 } | 1123 } |
1080 | 1124 |
1081 testFieldInitialization3() { | 1125 testFieldInitialization3() { |
1082 final String source = r""" | 1126 final String source = r""" |
1083 class A { | 1127 class A { |
1084 var x; | 1128 var x; |
1085 } | 1129 } |
1086 f() => new A().x; | 1130 f() => new A().x; |
1087 class B { | 1131 class B { |
1088 var x = new A().x; | 1132 var x = new A().x; |
1089 var y = f(); | 1133 var y = f(); |
1090 } | 1134 } |
1091 main () { | 1135 main () { |
1092 var foo = new B().x; | 1136 var foo = new B().x; |
1093 var bar = new B().y; | 1137 var bar = new B().y; |
1094 new A().x = "a"; | 1138 new A().x = "a"; |
1095 foo; bar; | 1139 foo; bar; |
1096 } | 1140 } |
1097 """; | 1141 """; |
1098 AnalysisResult result = analyze(source); | 1142 return analyze(source).then((result) { |
1099 // checks that B.B is set as a reader of A.x | 1143 // checks that B.B is set as a reader of A.x |
1100 result.checkFieldHasType('B', 'x', [result.nullType, result.string]); | 1144 result.checkFieldHasType('B', 'x', [result.nullType, result.string]); |
1101 // checks that B.B is set as a caller of f | 1145 // checks that B.B is set as a caller of f |
1102 result.checkFieldHasType('B', 'y', [result.nullType, result.string]); | 1146 result.checkFieldHasType('B', 'y', [result.nullType, result.string]); |
1103 // checks that readers of x are notified by changes in x's type | 1147 // checks that readers of x are notified by changes in x's type |
1104 result.checkNodeHasType('foo', [result.nullType, result.string]); | 1148 result.checkNodeHasType('foo', [result.nullType, result.string]); |
1105 // checks that readers of y are notified by changes in y's type | 1149 // checks that readers of y are notified by changes in y's type |
1106 result.checkNodeHasType('bar', [result.nullType, result.string]); | 1150 result.checkNodeHasType('bar', [result.nullType, result.string]); |
| 1151 }); |
1107 } | 1152 } |
1108 | 1153 |
1109 testLists() { | 1154 testLists() { |
1110 final String source = r""" | 1155 final String source = r""" |
1111 class A {} | 1156 class A {} |
1112 class B {} | 1157 class B {} |
1113 class C {} | 1158 class C {} |
1114 class D {} | 1159 class D {} |
1115 class E {} | 1160 class E {} |
1116 class F {} | 1161 class F {} |
(...skipping 11 matching lines...) Expand all Loading... |
1128 var x1 = l1[1]; | 1173 var x1 = l1[1]; |
1129 var x2 = l2[1]; | 1174 var x2 = l2[1]; |
1130 var x3 = l1['foo']; // raises an error, should return empty | 1175 var x3 = l1['foo']; // raises an error, should return empty |
1131 var x4 = l1.removeAt(1); | 1176 var x4 = l1.removeAt(1); |
1132 var x5 = l2.removeAt(1); | 1177 var x5 = l2.removeAt(1); |
1133 var x6 = l1.removeAt('a'); // raises an error, should return empty | 1178 var x6 = l1.removeAt('a'); // raises an error, should return empty |
1134 var x7 = l1.removeLast(); | 1179 var x7 = l1.removeLast(); |
1135 var x8 = l2.removeLast(); | 1180 var x8 = l2.removeLast(); |
1136 x1; x2; x3; x4; x5; x6; x7; x8; | 1181 x1; x2; x3; x4; x5; x6; x7; x8; |
1137 }"""; | 1182 }"""; |
1138 AnalysisResult result = analyze(source); | 1183 return analyze(source).then((result) { |
1139 final expectedTypes = ['A', 'C', 'D', 'F', 'G'].map(result.base).toList(); | 1184 final expectedTypes = ['A', 'C', 'D', 'F', 'G'].map(result.base).toList(); |
1140 result.checkNodeHasType('x1', expectedTypes); | 1185 result.checkNodeHasType('x1', expectedTypes); |
1141 result.checkNodeHasType('x2', expectedTypes); | 1186 result.checkNodeHasType('x2', expectedTypes); |
1142 result.checkNodeHasType('x3', []); | 1187 result.checkNodeHasType('x3', []); |
1143 result.checkNodeHasType('x4', expectedTypes); | 1188 result.checkNodeHasType('x4', expectedTypes); |
1144 result.checkNodeHasType('x5', expectedTypes); | 1189 result.checkNodeHasType('x5', expectedTypes); |
1145 result.checkNodeHasType('x6', []); | 1190 result.checkNodeHasType('x6', []); |
1146 result.checkNodeHasType('x7', expectedTypes); | 1191 result.checkNodeHasType('x7', expectedTypes); |
1147 result.checkNodeHasType('x8', expectedTypes); | 1192 result.checkNodeHasType('x8', expectedTypes); |
| 1193 }); |
1148 } | 1194 } |
1149 | 1195 |
1150 testListWithCapacity() { | 1196 testListWithCapacity() { |
1151 final String source = r""" | 1197 final String source = r""" |
1152 main() { | 1198 main() { |
1153 var l = new List(10); | 1199 var l = new List(10); |
1154 var x = [][0]; | 1200 var x = [][0]; |
1155 x; | 1201 x; |
1156 }"""; | 1202 }"""; |
1157 AnalysisResult result = analyze(source); | 1203 return analyze(source).then((result) { |
1158 result.checkNodeHasType('x', [result.nullType]); | 1204 result.checkNodeHasType('x', [result.nullType]); |
| 1205 }); |
1159 } | 1206 } |
1160 | 1207 |
1161 testEmptyList() { | 1208 testEmptyList() { |
1162 final String source = r""" | 1209 final String source = r""" |
1163 main() { | 1210 main() { |
1164 var l = new List(); | 1211 var l = new List(); |
1165 var x = l[0]; | 1212 var x = l[0]; |
1166 x; | 1213 x; |
1167 }"""; | 1214 }"""; |
1168 AnalysisResult result = analyze(source); | 1215 return analyze(source).then((result) { |
1169 result.checkNodeHasType('x', []); | 1216 result.checkNodeHasType('x', []); |
| 1217 }); |
1170 } | 1218 } |
1171 | 1219 |
1172 testSendWithWrongArity() { | 1220 testSendWithWrongArity() { |
1173 final String source = r""" | 1221 final String source = r""" |
1174 f(x) { } | 1222 f(x) { } |
1175 class A { g(x) { } } | 1223 class A { g(x) { } } |
1176 main () { | 1224 main () { |
1177 var x = f(); | 1225 var x = f(); |
1178 var y = f(1, 2); | 1226 var y = f(1, 2); |
1179 var z = new A().g(); | 1227 var z = new A().g(); |
1180 var w = new A().g(1, 2); | 1228 var w = new A().g(1, 2); |
1181 x; y; z; w; | 1229 x; y; z; w; |
1182 } | 1230 } |
1183 """; | 1231 """; |
1184 AnalysisResult result = analyze(source); | 1232 return analyze(source).then((result) { |
1185 result.checkNodeHasType('x', []); | 1233 result.checkNodeHasType('x', []); |
1186 result.checkNodeHasType('y', []); | 1234 result.checkNodeHasType('y', []); |
1187 result.checkNodeHasType('z', []); | 1235 result.checkNodeHasType('z', []); |
1188 result.checkNodeHasType('w', []); | 1236 result.checkNodeHasType('w', []); |
| 1237 }); |
1189 } | 1238 } |
1190 | 1239 |
1191 testBigTypesWidening1() { | 1240 testBigTypesWidening1() { |
1192 final String source = r""" | 1241 final String source = r""" |
1193 small() => true ? 1 : 'abc'; | 1242 small() => true ? 1 : 'abc'; |
1194 big() => true ? 1 : (true ? 'abc' : false); | 1243 big() => true ? 1 : (true ? 'abc' : false); |
1195 main () { | 1244 main () { |
1196 var x = small(); | 1245 var x = small(); |
1197 var y = big(); | 1246 var y = big(); |
1198 x; y; | 1247 x; y; |
1199 } | 1248 } |
1200 """; | 1249 """; |
1201 AnalysisResult result = analyze(source, maxConcreteTypeSize: 2); | 1250 return analyze(source, maxConcreteTypeSize: 2).then((result) { |
1202 result.checkNodeHasType('x', [result.int, result.string]); | 1251 result.checkNodeHasType('x', [result.int, result.string]); |
1203 result.checkNodeHasUnknownType('y'); | 1252 result.checkNodeHasUnknownType('y'); |
| 1253 }); |
1204 } | 1254 } |
1205 | 1255 |
1206 testBigTypesWidening2() { | 1256 testBigTypesWidening2() { |
1207 final String source = r""" | 1257 final String source = r""" |
1208 class A { | 1258 class A { |
1209 var x, y; | 1259 var x, y; |
1210 A(this.x, this.y); | 1260 A(this.x, this.y); |
1211 } | 1261 } |
1212 main () { | 1262 main () { |
1213 var a = new A(1, 1); | 1263 var a = new A(1, 1); |
1214 a.x = 'abc'; | 1264 a.x = 'abc'; |
1215 a.y = 'abc'; | 1265 a.y = 'abc'; |
1216 a.y = true; | 1266 a.y = true; |
1217 } | 1267 } |
1218 """; | 1268 """; |
1219 AnalysisResult result = analyze(source, maxConcreteTypeSize: 2); | 1269 return analyze(source, maxConcreteTypeSize: 2).then((result) { |
1220 result.checkFieldHasType('A', 'x', [result.int, result.string]); | 1270 result.checkFieldHasType('A', 'x', [result.int, result.string]); |
1221 result.checkFieldHasUknownType('A', 'y'); | 1271 result.checkFieldHasUknownType('A', 'y'); |
| 1272 }); |
1222 } | 1273 } |
1223 | 1274 |
1224 testDynamicIsAbsorbing() { | 1275 testDynamicIsAbsorbing() { |
1225 final String source = r""" | 1276 final String source = r""" |
1226 main () { | 1277 main () { |
1227 var x = 1; | 1278 var x = 1; |
1228 if (true) { | 1279 if (true) { |
1229 x = "__dynamic_for_test"; | 1280 x = "__dynamic_for_test"; |
1230 } else { | 1281 } else { |
1231 x = 42; | 1282 x = 42; |
1232 } | 1283 } |
1233 x; | 1284 x; |
1234 } | 1285 } |
1235 """; | 1286 """; |
1236 AnalysisResult result = analyze(source); | 1287 return analyze(source).then((result) { |
1237 result.checkNodeHasUnknownType('x'); | 1288 result.checkNodeHasUnknownType('x'); |
| 1289 }); |
1238 } | 1290 } |
1239 | 1291 |
1240 testJsCall() { | 1292 testJsCall() { |
1241 final String source = r""" | 1293 final String source = r""" |
1242 import 'dart:foreign'; | 1294 import 'dart:foreign'; |
1243 import 'dart:helper' show Null; | 1295 import 'dart:helper' show Null; |
1244 import 'dart:interceptors'; | 1296 import 'dart:interceptors'; |
1245 | 1297 |
1246 abstract class AbstractA {} | 1298 abstract class AbstractA {} |
1247 class A extends AbstractA {} | 1299 class A extends AbstractA {} |
(...skipping 24 matching lines...) Expand all Loading... |
1272 var h = JS('bool', '1'); | 1324 var h = JS('bool', '1'); |
1273 var hNull = JS('bool|Null', '1'); | 1325 var hNull = JS('bool|Null', '1'); |
1274 var i = JS('AbstractA', '1'); | 1326 var i = JS('AbstractA', '1'); |
1275 var iNull = JS('AbstractA|Null', '1'); | 1327 var iNull = JS('AbstractA|Null', '1'); |
1276 var j = JS('X', '1'); | 1328 var j = JS('X', '1'); |
1277 | 1329 |
1278 a; b; c; cNull; d; dNull; e; eNull; f; fNull; g; gNull; h; hNull; i; | 1330 a; b; c; cNull; d; dNull; e; eNull; f; fNull; g; gNull; h; hNull; i; |
1279 iNull; j; | 1331 iNull; j; |
1280 } | 1332 } |
1281 """; | 1333 """; |
1282 AnalysisResult result = analyze(source); | 1334 return analyze(source).then((result) { |
1283 List maybe(List types) => new List.from(types)..add(result.nullType); | 1335 List maybe(List types) => new List.from(types)..add(result.nullType); |
1284 result.checkNodeHasUnknownType('a'); | 1336 result.checkNodeHasUnknownType('a'); |
1285 result.checkNodeHasUnknownType('b'); | 1337 result.checkNodeHasUnknownType('b'); |
1286 final expectedCType = [result.growableList]; | 1338 final expectedCType = [result.growableList]; |
1287 result.checkNodeHasType('c', expectedCType); | 1339 result.checkNodeHasType('c', expectedCType); |
1288 result.checkNodeHasType('cNull', maybe(expectedCType)); | 1340 result.checkNodeHasType('cNull', maybe(expectedCType)); |
1289 final expectedDType = [result.string]; | 1341 final expectedDType = [result.string]; |
1290 result.checkNodeHasType('d', expectedDType); | 1342 result.checkNodeHasType('d', expectedDType); |
1291 result.checkNodeHasType('dNull', maybe(expectedDType)); | 1343 result.checkNodeHasType('dNull', maybe(expectedDType)); |
1292 final expectedEType = [result.int]; | 1344 final expectedEType = [result.int]; |
1293 result.checkNodeHasType('e', expectedEType); | 1345 result.checkNodeHasType('e', expectedEType); |
1294 result.checkNodeHasType('eNull', maybe(expectedEType)); | 1346 result.checkNodeHasType('eNull', maybe(expectedEType)); |
1295 final expectedFType = [result.double]; | 1347 final expectedFType = [result.double]; |
1296 result.checkNodeHasType('f', expectedFType); | 1348 result.checkNodeHasType('f', expectedFType); |
1297 result.checkNodeHasType('fNull', maybe(expectedFType)); | 1349 result.checkNodeHasType('fNull', maybe(expectedFType)); |
1298 final expectedGType = [result.num]; | 1350 final expectedGType = [result.num]; |
1299 result.checkNodeHasType('g', expectedGType); | 1351 result.checkNodeHasType('g', expectedGType); |
1300 result.checkNodeHasType('gNull', maybe(expectedGType)); | 1352 result.checkNodeHasType('gNull', maybe(expectedGType)); |
1301 final expectedHType = [result.bool]; | 1353 final expectedHType = [result.bool]; |
1302 result.checkNodeHasType('h', expectedHType); | 1354 result.checkNodeHasType('h', expectedHType); |
1303 result.checkNodeHasType('hNull', maybe(expectedHType)); | 1355 result.checkNodeHasType('hNull', maybe(expectedHType)); |
1304 final expectedIType = [result.base('A'), result.base('B'), | 1356 final expectedIType = [result.base('A'), result.base('B'), |
1305 result.base('BB'), result.base('C'), | 1357 result.base('BB'), result.base('C'), |
1306 result.base('D')]; | 1358 result.base('D')]; |
1307 result.checkNodeHasType('i', expectedIType); | 1359 result.checkNodeHasType('i', expectedIType); |
1308 result.checkNodeHasType('iNull', maybe(expectedIType)); | 1360 result.checkNodeHasType('iNull', maybe(expectedIType)); |
1309 result.checkNodeHasType('j', []); | 1361 result.checkNodeHasType('j', []); |
| 1362 }); |
1310 } | 1363 } |
1311 | 1364 |
1312 testJsCallAugmentsSeenClasses() { | 1365 testJsCallAugmentsSeenClasses() { |
1313 final String source1 = r""" | 1366 final String source1 = r""" |
1314 main () { | 1367 main () { |
1315 var x = "__dynamic_for_test".truncate(); | 1368 var x = "__dynamic_for_test".truncate(); |
1316 x; | 1369 x; |
1317 } | 1370 } |
1318 """; | 1371 """; |
1319 AnalysisResult result1 = analyze(source1); | 1372 return analyze(source1).then((AnalysisResult result) { |
1320 result1.checkNodeHasType('x', []); | 1373 result.checkNodeHasType('x', []); |
| 1374 }).whenComplete(() { |
1321 | 1375 |
1322 final String source2 = r""" | 1376 final String source2 = r""" |
1323 import 'dart:foreign'; | 1377 import 'dart:foreign'; |
1324 | 1378 |
1325 main () { | 1379 main () { |
1326 var x = "__dynamic_for_test".truncate(); | 1380 var x = "__dynamic_for_test".truncate(); |
1327 JS('double', 'foo'); | 1381 JS('double', 'foo'); |
1328 x; | 1382 x; |
1329 } | 1383 } |
1330 """; | 1384 """; |
1331 AnalysisResult result2 = analyze(source2); | 1385 return analyze(source2).then((AnalysisResult result) { |
1332 result2.checkNodeHasType('x', [result2.int]); | 1386 result.checkNodeHasType('x', [result.int]); |
| 1387 }); |
| 1388 }); |
1333 } | 1389 } |
1334 | 1390 |
1335 testIsCheck() { | 1391 testIsCheck() { |
1336 final String source = r""" | 1392 final String source = r""" |
1337 main () { | 1393 main () { |
1338 var x = (1 is String); | 1394 var x = (1 is String); |
1339 x; | 1395 x; |
1340 } | 1396 } |
1341 """; | 1397 """; |
1342 AnalysisResult result = analyze(source); | 1398 return analyze(source).then((result) { |
1343 result.checkNodeHasType('x', [result.bool]); | 1399 result.checkNodeHasType('x', [result.bool]); |
| 1400 }); |
1344 } | 1401 } |
1345 | 1402 |
1346 testSeenClasses() { | 1403 testSeenClasses() { |
1347 final String source = r""" | 1404 final String source = r""" |
1348 class A { | 1405 class A { |
1349 witness() => 42; | 1406 witness() => 42; |
1350 } | 1407 } |
1351 class B { | 1408 class B { |
1352 witness() => "abc"; | 1409 witness() => "abc"; |
1353 } | 1410 } |
1354 class AFactory { | 1411 class AFactory { |
1355 onlyCalledInAFactory() => new A(); | 1412 onlyCalledInAFactory() => new A(); |
1356 } | 1413 } |
1357 class BFactory { | 1414 class BFactory { |
1358 onlyCalledInAFactory() => new B(); | 1415 onlyCalledInAFactory() => new B(); |
1359 } | 1416 } |
1360 | 1417 |
1361 main() { | 1418 main() { |
1362 new AFactory().onlyCalledInAFactory(); | 1419 new AFactory().onlyCalledInAFactory(); |
1363 new BFactory(); | 1420 new BFactory(); |
1364 // should be of type {int} and not {int, String} since B is unreachable | 1421 // should be of type {int} and not {int, String} since B is unreachable |
1365 var foo = "__dynamic_for_test".witness(); | 1422 var foo = "__dynamic_for_test".witness(); |
1366 foo; | 1423 foo; |
1367 } | 1424 } |
1368 """; | 1425 """; |
1369 AnalysisResult result = analyze(source); | 1426 return analyze(source).then((result) { |
1370 result.checkNodeHasType('foo', [result.int]); | 1427 result.checkNodeHasType('foo', [result.int]); |
| 1428 }); |
1371 } | 1429 } |
1372 | 1430 |
1373 testIntDoubleNum() { | 1431 testIntDoubleNum() { |
1374 final String source = r""" | 1432 final String source = r""" |
1375 main() { | 1433 main() { |
1376 var a = 1; | 1434 var a = 1; |
1377 var b = 1.0; | 1435 var b = 1.0; |
1378 var c = true ? 1 : 1.0; | 1436 var c = true ? 1 : 1.0; |
1379 a; b; c; | 1437 a; b; c; |
1380 } | 1438 } |
1381 """; | 1439 """; |
1382 AnalysisResult result = analyze(source); | 1440 return analyze(source).then((result) { |
1383 result.checkNodeHasType('a', [result.int]); | 1441 result.checkNodeHasType('a', [result.int]); |
1384 result.checkNodeHasType('b', [result.double]); | 1442 result.checkNodeHasType('b', [result.double]); |
1385 result.checkNodeHasType('c', [result.num]); | 1443 result.checkNodeHasType('c', [result.num]); |
| 1444 }); |
1386 } | 1445 } |
1387 | 1446 |
1388 testConcreteTypeToTypeMask() { | 1447 testConcreteTypeToTypeMask() { |
1389 final String source = r""" | 1448 final String source = r""" |
1390 class A {} | 1449 class A {} |
1391 class B extends A {} | 1450 class B extends A {} |
1392 class C extends A {} | 1451 class C extends A {} |
1393 class D implements A {} | 1452 class D implements A {} |
1394 main() { | 1453 main() { |
1395 new A(); | 1454 new A(); |
1396 new B(); | 1455 new B(); |
1397 new C(); | 1456 new C(); |
1398 new D(); | 1457 new D(); |
1399 } | 1458 } |
1400 """; | 1459 """; |
1401 AnalysisResult result = analyze(source); | 1460 return analyze(source).then((result) { |
1402 | 1461 |
1403 convert(ConcreteType type) { | 1462 convert(ConcreteType type) { |
1404 return result.compiler.typesTask.concreteTypesInferrer | 1463 return result.compiler.typesTask.concreteTypesInferrer |
1405 .concreteTypeToTypeMask(type); | 1464 .concreteTypeToTypeMask(type); |
1406 } | 1465 } |
1407 | 1466 |
1408 final nullSingleton = | 1467 final nullSingleton = |
1409 result.compiler.typesTask.concreteTypesInferrer.singletonConcreteType( | 1468 result.compiler.typesTask.concreteTypesInferrer.singletonConcreteType( |
1410 new NullBaseType()); | 1469 new NullBaseType()); |
1411 | 1470 |
1412 singleton(ClassElement element) { | 1471 singleton(ClassElement element) { |
1413 return result.compiler.typesTask.concreteTypesInferrer | 1472 return result.compiler.typesTask.concreteTypesInferrer |
1414 .singletonConcreteType(new ClassBaseType(element)); | 1473 .singletonConcreteType(new ClassBaseType(element)); |
1415 } | 1474 } |
1416 | 1475 |
1417 ClassElement a = findElement(result.compiler, 'A'); | 1476 ClassElement a = findElement(result.compiler, 'A'); |
1418 ClassElement b = findElement(result.compiler, 'B'); | 1477 ClassElement b = findElement(result.compiler, 'B'); |
1419 ClassElement c = findElement(result.compiler, 'C'); | 1478 ClassElement c = findElement(result.compiler, 'C'); |
1420 ClassElement d = findElement(result.compiler, 'D'); | 1479 ClassElement d = findElement(result.compiler, 'D'); |
1421 | 1480 |
1422 for (ClassElement cls in [a, b, c, d]) { | 1481 for (ClassElement cls in [a, b, c, d]) { |
1423 Expect.equals(convert(singleton(cls)), | 1482 Expect.equals(convert(singleton(cls)), |
1424 new TypeMask.nonNullExact(cls.rawType)); | 1483 new TypeMask.nonNullExact(cls.rawType)); |
1425 } | 1484 } |
1426 | 1485 |
1427 for (ClassElement cls in [a, b, c, d]) { | 1486 for (ClassElement cls in [a, b, c, d]) { |
1428 Expect.equals(convert(singleton(cls).union(nullSingleton)), | 1487 Expect.equals(convert(singleton(cls).union(nullSingleton)), |
1429 new TypeMask.exact(cls.rawType)); | 1488 new TypeMask.exact(cls.rawType)); |
1430 } | 1489 } |
1431 | 1490 |
1432 Expect.equals(convert(singleton(a).union(singleton(b))), | 1491 Expect.equals(convert(singleton(a).union(singleton(b))), |
1433 new TypeMask.nonNullSubclass(a.rawType)); | 1492 new TypeMask.nonNullSubclass(a.rawType)); |
1434 | 1493 |
1435 Expect.equals(convert(singleton(a).union(singleton(b)).union(nullSingleton)), | 1494 Expect.equals( |
1436 new TypeMask.subclass(a.rawType)); | 1495 convert(singleton(a).union(singleton(b)).union(nullSingleton)), |
| 1496 new TypeMask.subclass(a.rawType)); |
1437 | 1497 |
1438 Expect.equals( | 1498 Expect.equals( |
1439 convert(singleton(b).union(singleton(d))).simplify(result.compiler), | 1499 convert(singleton(b).union(singleton(d))).simplify(result.compiler), |
1440 new TypeMask.nonNullSubtype(a.rawType)); | 1500 new TypeMask.nonNullSubtype(a.rawType)); |
| 1501 }); |
1441 } | 1502 } |
1442 | 1503 |
1443 testSelectors() { | 1504 testSelectors() { |
1444 final String source = r""" | 1505 final String source = r""" |
1445 // ABC <--- A | 1506 // ABC <--- A |
1446 // `- BC <--- B | 1507 // `- BC <--- B |
1447 // `- C | 1508 // `- C |
1448 | 1509 |
1449 class ABC {} | 1510 class ABC {} |
1450 class A extends ABC {} | 1511 class A extends ABC {} |
1451 class BC extends ABC {} | 1512 class BC extends ABC {} |
1452 class B extends BC {} | 1513 class B extends BC {} |
1453 class C extends BC {} | 1514 class C extends BC {} |
1454 | 1515 |
1455 class XY {} | 1516 class XY {} |
1456 class X extends XY { foo() => new B(); } | 1517 class X extends XY { foo() => new B(); } |
1457 class Y extends XY { foo() => new C(); } | 1518 class Y extends XY { foo() => new C(); } |
1458 class Z { foo() => new A(); } | 1519 class Z { foo() => new A(); } |
1459 | 1520 |
1460 main() { | 1521 main() { |
1461 new X().foo(); | 1522 new X().foo(); |
1462 new Y().foo(); | 1523 new Y().foo(); |
1463 new Z().foo(); | 1524 new Z().foo(); |
1464 } | 1525 } |
1465 """; | 1526 """; |
1466 AnalysisResult result = analyze(source); | 1527 return analyze(source).then((result) { |
1467 | 1528 |
1468 inferredType(Selector selector) { | 1529 inferredType(Selector selector) { |
1469 return result.compiler.typesTask.concreteTypesInferrer | 1530 return result.compiler.typesTask.concreteTypesInferrer |
1470 .getTypeOfSelector(selector); | 1531 .getTypeOfSelector(selector); |
1471 } | 1532 } |
1472 | 1533 |
1473 ClassElement abc = findElement(result.compiler, 'ABC'); | 1534 ClassElement abc = findElement(result.compiler, 'ABC'); |
1474 ClassElement bc = findElement(result.compiler, 'BC'); | 1535 ClassElement bc = findElement(result.compiler, 'BC'); |
1475 ClassElement a = findElement(result.compiler, 'A'); | 1536 ClassElement a = findElement(result.compiler, 'A'); |
1476 ClassElement b = findElement(result.compiler, 'B'); | 1537 ClassElement b = findElement(result.compiler, 'B'); |
1477 ClassElement c = findElement(result.compiler, 'C'); | 1538 ClassElement c = findElement(result.compiler, 'C'); |
1478 ClassElement xy = findElement(result.compiler, 'XY'); | 1539 ClassElement xy = findElement(result.compiler, 'XY'); |
1479 ClassElement x = findElement(result.compiler, 'X'); | 1540 ClassElement x = findElement(result.compiler, 'X'); |
1480 ClassElement y = findElement(result.compiler, 'Y'); | 1541 ClassElement y = findElement(result.compiler, 'Y'); |
1481 ClassElement z = findElement(result.compiler, 'Z'); | 1542 ClassElement z = findElement(result.compiler, 'Z'); |
1482 | 1543 |
1483 Selector foo = new Selector.call(buildSourceString("foo"), null, 0); | 1544 Selector foo = new Selector.call(buildSourceString("foo"), null, 0); |
1484 | 1545 |
1485 Expect.equals( | 1546 Expect.equals( |
1486 inferredType(foo).simplify(result.compiler), | 1547 inferredType(foo).simplify(result.compiler), |
1487 new TypeMask.nonNullSubclass(abc.rawType)); | 1548 new TypeMask.nonNullSubclass(abc.rawType)); |
1488 Expect.equals( | 1549 Expect.equals( |
1489 inferredType(new TypedSelector.subclass(x.rawType, foo)), | 1550 inferredType(new TypedSelector.subclass(x.rawType, foo)), |
1490 new TypeMask.nonNullExact(b.rawType)); | 1551 new TypeMask.nonNullExact(b.rawType)); |
1491 Expect.equals( | 1552 Expect.equals( |
1492 inferredType(new TypedSelector.subclass(y.rawType, foo)), | 1553 inferredType(new TypedSelector.subclass(y.rawType, foo)), |
1493 new TypeMask.nonNullExact(c.rawType)); | 1554 new TypeMask.nonNullExact(c.rawType)); |
1494 Expect.equals( | 1555 Expect.equals( |
1495 inferredType(new TypedSelector.subclass(z.rawType, foo)), | 1556 inferredType(new TypedSelector.subclass(z.rawType, foo)), |
1496 new TypeMask.nonNullExact(a.rawType)); | 1557 new TypeMask.nonNullExact(a.rawType)); |
1497 Expect.equals( | 1558 Expect.equals( |
1498 inferredType(new TypedSelector.subclass( | 1559 inferredType(new TypedSelector.subclass( |
1499 xy.rawType, foo)).simplify(result.compiler), | 1560 xy.rawType, foo)).simplify(result.compiler), |
1500 new TypeMask.nonNullSubclass(bc.rawType)); | 1561 new TypeMask.nonNullSubclass(bc.rawType)); |
1501 | 1562 |
1502 Selector bar = new Selector.call(buildSourceString("bar"), null, 0); | 1563 Selector bar = new Selector.call(buildSourceString("bar"), null, 0); |
1503 | 1564 |
1504 Expect.isNull(inferredType(bar)); | 1565 Expect.isNull(inferredType(bar)); |
| 1566 }); |
1505 } | 1567 } |
1506 | 1568 |
1507 testMixins() { | 1569 testMixins() { |
1508 final String source = r""" | 1570 final String source = r""" |
1509 class A { | 1571 class A { |
1510 foo() => "abc"; | 1572 foo() => "abc"; |
1511 get x => 42; | 1573 get x => 42; |
1512 } | 1574 } |
1513 class B extends Object with A { | 1575 class B extends Object with A { |
1514 bar() => foo(); | 1576 bar() => foo(); |
1515 baz() => x; | 1577 baz() => x; |
1516 } | 1578 } |
1517 main() { | 1579 main() { |
1518 var b = new B(); | 1580 var b = new B(); |
1519 var x = b.foo(); | 1581 var x = b.foo(); |
1520 var y = b.bar(); | 1582 var y = b.bar(); |
1521 var z = b.x; | 1583 var z = b.x; |
1522 var w = b.baz(); | 1584 var w = b.baz(); |
1523 x; y; z; w; | 1585 x; y; z; w; |
1524 } | 1586 } |
1525 """; | 1587 """; |
1526 AnalysisResult result = analyze(source); | 1588 return analyze(source).then((result) { |
1527 result.checkNodeHasType('x', [result.string]); | 1589 result.checkNodeHasType('x', [result.string]); |
1528 result.checkNodeHasType('y', [result.string]); | 1590 result.checkNodeHasType('y', [result.string]); |
1529 result.checkNodeHasType('z', [result.int]); | 1591 result.checkNodeHasType('z', [result.int]); |
1530 result.checkNodeHasType('w', [result.int]); | 1592 result.checkNodeHasType('w', [result.int]); |
| 1593 }); |
1531 } | 1594 } |
1532 | 1595 |
1533 testClosures() { | 1596 testClosures() { |
1534 final String source = r""" | 1597 final String source = r""" |
1535 class A { | 1598 class A { |
1536 final foo = 42; | 1599 final foo = 42; |
1537 } | 1600 } |
1538 class B { | 1601 class B { |
1539 final foo = "abc"; | 1602 final foo = "abc"; |
1540 } | 1603 } |
1541 main() { | 1604 main() { |
1542 new A(); new B(); | 1605 new A(); new B(); |
1543 | 1606 |
1544 var a; | 1607 var a; |
1545 var f = (x) { | 1608 var f = (x) { |
1546 a = x.foo; | 1609 a = x.foo; |
1547 }; | 1610 }; |
1548 var b = f(42); | 1611 var b = f(42); |
1549 a; b; f; | 1612 a; b; f; |
1550 } | 1613 } |
1551 """; | 1614 """; |
1552 AnalysisResult result = analyze(source); | 1615 return analyze(source).then((AnalysisResult result) { |
1553 result.checkNodeHasType('a', [result.int, result.string]); | 1616 result.checkNodeHasType('a', [result.int, result.string]); |
1554 result.checkNodeHasType('f', [result.functionType]); | 1617 result.checkNodeHasType('f', [result.functionType]); |
1555 result.checkNodeHasUnknownType('b'); | 1618 result.checkNodeHasUnknownType('b'); |
| 1619 }); |
1556 } | 1620 } |
1557 | 1621 |
1558 testNestedFunctions() { | 1622 testNestedFunctions() { |
1559 final String source = r""" | 1623 final String source = r""" |
1560 class A { | 1624 class A { |
1561 final foo = 42; | 1625 final foo = 42; |
1562 } | 1626 } |
1563 class B { | 1627 class B { |
1564 final foo = "abc"; | 1628 final foo = "abc"; |
1565 } | 1629 } |
1566 main() { | 1630 main() { |
1567 new A(); new B(); | 1631 new A(); new B(); |
1568 | 1632 |
1569 var a; | 1633 var a; |
1570 f(x) { | 1634 f(x) { |
1571 a = x.foo; | 1635 a = x.foo; |
1572 } | 1636 } |
1573 var b = f(42); | 1637 var b = f(42); |
1574 a; b; f; | 1638 a; b; f; |
1575 } | 1639 } |
1576 """; | 1640 """; |
1577 AnalysisResult result = analyze(source); | 1641 return analyze(source).then((AnalysisResult result) { |
1578 result.checkNodeHasType('a', [result.int, result.string]); | 1642 result.checkNodeHasType('a', [result.int, result.string]); |
1579 result.checkNodeHasType('f', [result.functionType]); | 1643 result.checkNodeHasType('f', [result.functionType]); |
1580 result.checkNodeHasUnknownType('b'); | 1644 result.checkNodeHasUnknownType('b'); |
| 1645 }); |
1581 } | 1646 } |
1582 | 1647 |
1583 void main() { | 1648 void main() { |
1584 testDynamicBackDoor(); | 1649 asyncTest(() => Future.forEach([ |
1585 testVariableDeclaration(); | 1650 testDynamicBackDoor, |
1586 testLiterals(); | 1651 testVariableDeclaration, |
1587 testRedefinition(); | 1652 testLiterals, |
1588 testIfThenElse(); | 1653 testRedefinition, |
1589 testTernaryIf(); | 1654 testIfThenElse, |
1590 testWhile(); | 1655 testTernaryIf, |
1591 testDoWhile(); | 1656 testWhile, |
1592 testFor1(); | 1657 testDoWhile, |
1593 testFor2(); | 1658 testFor1, |
1594 testFor3(); | 1659 testFor2, |
1595 testForIn(); | 1660 testFor3, |
1596 testToplevelVariable(); | 1661 testForIn, |
1597 testNonRecusiveFunction(); | 1662 testToplevelVariable, |
1598 testRecusiveFunction(); | 1663 testNonRecusiveFunction, |
1599 testMutuallyRecusiveFunction(); | 1664 testRecusiveFunction, |
1600 testSimpleSend(); | 1665 testMutuallyRecusiveFunction, |
1601 // testSendToClosureField(); // closures are not yet supported | 1666 testSimpleSend, |
1602 testSendToThis1(); | 1667 // testSendToClosureField, // closures are not yet supported |
1603 testSendToThis2(); | 1668 testSendToThis1, |
1604 testSendToThis3(); | 1669 testSendToThis2, |
1605 testConstructor(); | 1670 testSendToThis3, |
1606 testGetters(); | 1671 testConstructor, |
1607 testSetters(); | 1672 testGetters, |
1608 testOptionalNamedParameters(); | 1673 testSetters, |
1609 testOptionalPositionalParameters(); | 1674 testOptionalNamedParameters, |
1610 testListLiterals(); | 1675 testOptionalPositionalParameters, |
1611 testMapLiterals(); | 1676 testListLiterals, |
1612 testReturn(); | 1677 testMapLiterals, |
1613 // testNoReturn(); // right now we infer the empty type instead of null | 1678 testReturn, |
1614 testArithmeticOperators(); | 1679 // testNoReturn, // right now we infer the empty type instead of null |
1615 testBooleanOperators(); | 1680 testArithmeticOperators, |
1616 testBooleanOperatorsShortCirtcuit(); | 1681 testBooleanOperators, |
1617 testOperators(); | 1682 testBooleanOperatorsShortCirtcuit, |
1618 testCompoundOperators1(); | 1683 testOperators, |
1619 testCompoundOperators2(); | 1684 testCompoundOperators1, |
1620 testSetIndexOperator(); | 1685 testCompoundOperators2, |
1621 testInequality(); | 1686 testSetIndexOperator, |
1622 testFieldInitialization1(); | 1687 testInequality, |
1623 testFieldInitialization2(); | 1688 testFieldInitialization1, |
1624 testFieldInitialization3(); | 1689 testFieldInitialization2, |
1625 testSendWithWrongArity(); | 1690 testFieldInitialization3, |
1626 testBigTypesWidening1(); | 1691 testSendWithWrongArity, |
1627 testBigTypesWidening2(); | 1692 testBigTypesWidening1, |
1628 testDynamicIsAbsorbing(); | 1693 testBigTypesWidening2, |
1629 testLists(); | 1694 testDynamicIsAbsorbing, |
1630 testListWithCapacity(); | 1695 testLists, |
1631 testEmptyList(); | 1696 testListWithCapacity, |
1632 testJsCall(); | 1697 testEmptyList, |
1633 testJsCallAugmentsSeenClasses(); | 1698 testJsCall, |
1634 testIsCheck(); | 1699 testJsCallAugmentsSeenClasses, |
1635 testSeenClasses(); | 1700 testIsCheck, |
1636 testIntDoubleNum(); | 1701 testSeenClasses, |
1637 testConcreteTypeToTypeMask(); | 1702 testIntDoubleNum, |
1638 testSelectors(); | 1703 testConcreteTypeToTypeMask, |
1639 testMixins(); | 1704 testSelectors, |
1640 testClosures(); | 1705 testMixins, |
1641 testNestedFunctions(); | 1706 testClosures, |
| 1707 testNestedFunctions, |
| 1708 ], (f) => f())); |
1642 } | 1709 } |
OLD | NEW |