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