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

Side by Side Diff: pkg/analyzer/test/generated/strong_mode_test.dart

Issue 1782463002: Split resolver_test.dart into smaller files. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 library analyzer.test.generated.strong_mode_test;
6
7 import 'package:analyzer/dart/ast/ast.dart';
8 import 'package:analyzer/dart/element/element.dart';
9 import 'package:analyzer/dart/element/type.dart';
10 import 'package:analyzer/src/dart/element/element.dart';
11 import 'package:analyzer/src/generated/engine.dart';
12 import 'package:analyzer/src/generated/error.dart';
13 import 'package:analyzer/src/generated/source_io.dart';
14 import 'package:unittest/unittest.dart';
15
16 import '../reflective_tests.dart';
17 import '../utils.dart';
18 import 'resolver_test_case.dart';
19
20 main() {
21 initializeTestEnvironment();
22 runReflectiveTests(StrongModeDownwardsInferenceTest);
23 runReflectiveTests(StrongModeStaticTypeAnalyzer2Test);
24 runReflectiveTests(StrongModeTypePropagationTest);
25 }
26
27 /**
28 * Strong mode static analyzer downwards inference tests
29 */
30 @reflectiveTest
31 class StrongModeDownwardsInferenceTest extends ResolverTestCase {
32 TypeAssertions _assertions;
33
34 Asserter<DartType> _isDynamic;
35 Asserter<InterfaceType> _isFutureOfDynamic;
36 Asserter<InterfaceType> _isFutureOfInt;
37 Asserter<DartType> _isInt;
38 Asserter<DartType> _isNum;
39 Asserter<DartType> _isString;
40
41 AsserterBuilder2<Asserter<DartType>, Asserter<DartType>, DartType>
42 _isFunction2Of;
43 AsserterBuilder<List<Asserter<DartType>>, InterfaceType> _isFutureOf;
44 AsserterBuilderBuilder<Asserter<DartType>, List<Asserter<DartType>>, DartType>
45 _isInstantiationOf;
46 AsserterBuilder<Asserter<DartType>, InterfaceType> _isListOf;
47 AsserterBuilder2<Asserter<DartType>, Asserter<DartType>, InterfaceType>
48 _isMapOf;
49 AsserterBuilder<List<Asserter<DartType>>, InterfaceType> _isStreamOf;
50 AsserterBuilder<DartType, DartType> _isType;
51
52 AsserterBuilder<Element, DartType> _hasElement;
53 AsserterBuilder<DartType, DartType> _sameElement;
54
55 @override
56 void setUp() {
57 super.setUp();
58 AnalysisOptionsImpl options = new AnalysisOptionsImpl();
59 options.strongMode = true;
60 resetWithOptions(options);
61 _assertions = new TypeAssertions(typeProvider);
62 _isType = _assertions.isType;
63 _hasElement = _assertions.hasElement;
64 _isInstantiationOf = _assertions.isInstantiationOf;
65 _isInt = _assertions.isInt;
66 _isNum = _assertions.isNum;
67 _isString = _assertions.isString;
68 _isDynamic = _assertions.isDynamic;
69 _isListOf = _assertions.isListOf;
70 _isMapOf = _assertions.isMapOf;
71 _isFunction2Of = _assertions.isFunction2Of;
72 _sameElement = _assertions.sameElement;
73 _isFutureOf = _isInstantiationOf(_sameElement(typeProvider.futureType));
74 _isFutureOfDynamic = _isFutureOf([_isDynamic]);
75 _isFutureOfInt = _isFutureOf([_isInt]);
76 _isStreamOf = _isInstantiationOf(_sameElement(typeProvider.streamType));
77 }
78
79 void test_async_method_propagation() {
80 String code = r'''
81 import "dart:async";
82 class A {
83 Future f0() => new Future.value(3);
84 Future f1() async => new Future.value(3);
85 Future f2() async => await new Future.value(3);
86
87 Future<int> f3() => new Future.value(3);
88 Future<int> f4() async => new Future.value(3);
89 Future<int> f5() async => await new Future.value(3);
90
91 Future g0() { return new Future.value(3); }
92 Future g1() async { return new Future.value(3); }
93 Future g2() async { return await new Future.value(3); }
94
95 Future<int> g3() { return new Future.value(3); }
96 Future<int> g4() async { return new Future.value(3); }
97 Future<int> g5() async { return await new Future.value(3); }
98 }
99 ''';
100 CompilationUnit unit = resolveSource(code);
101
102 void check(String name, Asserter<InterfaceType> typeTest) {
103 MethodDeclaration test = AstFinder.getMethodInClass(unit, "A", name);
104 FunctionBody body = test.body;
105 Expression returnExp;
106 if (body is ExpressionFunctionBody) {
107 returnExp = body.expression;
108 } else {
109 ReturnStatement stmt = (body as BlockFunctionBody).block.statements[0];
110 returnExp = stmt.expression;
111 }
112 DartType type = returnExp.staticType;
113 if (returnExp is AwaitExpression) {
114 type = returnExp.expression.staticType;
115 }
116 typeTest(type);
117 }
118
119 check("f0", _isFutureOfDynamic);
120 check("f1", _isFutureOfDynamic);
121 check("f2", _isFutureOfDynamic);
122
123 check("f3", _isFutureOfInt);
124 // This should be int when we handle the implicit Future<T> | T union
125 // https://github.com/dart-lang/sdk/issues/25322
126 check("f4", _isFutureOfDynamic);
127 check("f5", _isFutureOfInt);
128
129 check("g0", _isFutureOfDynamic);
130 check("g1", _isFutureOfDynamic);
131 check("g2", _isFutureOfDynamic);
132
133 check("g3", _isFutureOfInt);
134 // This should be int when we handle the implicit Future<T> | T union
135 // https://github.com/dart-lang/sdk/issues/25322
136 check("g4", _isFutureOfDynamic);
137 check("g5", _isFutureOfInt);
138 }
139
140 void test_async_propagation() {
141 String code = r'''
142 import "dart:async";
143
144 Future f0() => new Future.value(3);
145 Future f1() async => new Future.value(3);
146 Future f2() async => await new Future.value(3);
147
148 Future<int> f3() => new Future.value(3);
149 Future<int> f4() async => new Future.value(3);
150 Future<int> f5() async => await new Future.value(3);
151
152 Future g0() { return new Future.value(3); }
153 Future g1() async { return new Future.value(3); }
154 Future g2() async { return await new Future.value(3); }
155
156 Future<int> g3() { return new Future.value(3); }
157 Future<int> g4() async { return new Future.value(3); }
158 Future<int> g5() async { return await new Future.value(3); }
159 ''';
160 CompilationUnit unit = resolveSource(code);
161
162 void check(String name, Asserter<InterfaceType> typeTest) {
163 FunctionDeclaration test = AstFinder.getTopLevelFunction(unit, name);
164 FunctionBody body = test.functionExpression.body;
165 Expression returnExp;
166 if (body is ExpressionFunctionBody) {
167 returnExp = body.expression;
168 } else {
169 ReturnStatement stmt = (body as BlockFunctionBody).block.statements[0];
170 returnExp = stmt.expression;
171 }
172 DartType type = returnExp.staticType;
173 if (returnExp is AwaitExpression) {
174 type = returnExp.expression.staticType;
175 }
176 typeTest(type);
177 }
178
179 check("f0", _isFutureOfDynamic);
180 check("f1", _isFutureOfDynamic);
181 check("f2", _isFutureOfDynamic);
182
183 check("f3", _isFutureOfInt);
184 // This should be int when we handle the implicit Future<T> | T union
185 // https://github.com/dart-lang/sdk/issues/25322
186 check("f4", _isFutureOfDynamic);
187 check("f5", _isFutureOfInt);
188
189 check("g0", _isFutureOfDynamic);
190 check("g1", _isFutureOfDynamic);
191 check("g2", _isFutureOfDynamic);
192
193 check("g3", _isFutureOfInt);
194 // This should be int when we handle the implicit Future<T> | T union
195 // https://github.com/dart-lang/sdk/issues/25322
196 check("g4", _isFutureOfDynamic);
197 check("g5", _isFutureOfInt);
198 }
199
200 void test_async_star_method_propagation() {
201 String code = r'''
202 import "dart:async";
203 class A {
204 Stream g0() async* { yield []; }
205 Stream g1() async* { yield* new Stream(); }
206
207 Stream<List<int>> g2() async* { yield []; }
208 Stream<List<int>> g3() async* { yield* new Stream(); }
209 }
210 ''';
211 CompilationUnit unit = resolveSource(code);
212
213 void check(String name, Asserter<InterfaceType> typeTest) {
214 MethodDeclaration test = AstFinder.getMethodInClass(unit, "A", name);
215 BlockFunctionBody body = test.body;
216 YieldStatement stmt = body.block.statements[0];
217 Expression exp = stmt.expression;
218 typeTest(exp.staticType);
219 }
220
221 check("g0", _isListOf(_isDynamic));
222 check("g1", _isStreamOf([_isDynamic]));
223
224 check("g2", _isListOf(_isInt));
225 check("g3", _isStreamOf([_isListOf(_isInt)]));
226 }
227
228 void test_async_star_propagation() {
229 String code = r'''
230 import "dart:async";
231
232 Stream g0() async* { yield []; }
233 Stream g1() async* { yield* new Stream(); }
234
235 Stream<List<int>> g2() async* { yield []; }
236 Stream<List<int>> g3() async* { yield* new Stream(); }
237 ''';
238 CompilationUnit unit = resolveSource(code);
239
240 void check(String name, Asserter<InterfaceType> typeTest) {
241 FunctionDeclaration test = AstFinder.getTopLevelFunction(unit, name);
242 BlockFunctionBody body = test.functionExpression.body;
243 YieldStatement stmt = body.block.statements[0];
244 Expression exp = stmt.expression;
245 typeTest(exp.staticType);
246 }
247
248 check("g0", _isListOf(_isDynamic));
249 check("g1", _isStreamOf([_isDynamic]));
250
251 check("g2", _isListOf(_isInt));
252 check("g3", _isStreamOf([_isListOf(_isInt)]));
253 }
254
255 void test_cascadeExpression() {
256 String code = r'''
257 class A<T> {
258 List<T> map(T a, List<T> mapper(T x)) => mapper(a);
259 }
260
261 void main () {
262 A<int> a = new A()..map(0, (x) => [x]);
263 }
264 ''';
265 CompilationUnit unit = resolveSource(code);
266 List<Statement> statements =
267 AstFinder.getStatementsInTopLevelFunction(unit, "main");
268 CascadeExpression fetch(int i) {
269 VariableDeclarationStatement stmt = statements[i];
270 VariableDeclaration decl = stmt.variables.variables[0];
271 CascadeExpression exp = decl.initializer;
272 return exp;
273 }
274 Element elementA = AstFinder.getClass(unit, "A").element;
275
276 CascadeExpression cascade = fetch(0);
277 _isInstantiationOf(_hasElement(elementA))([_isInt])(cascade.staticType);
278 MethodInvocation invoke = cascade.cascadeSections[0];
279 FunctionExpression function = invoke.argumentList.arguments[1];
280 ExecutableElement f0 = function.element;
281 _isListOf(_isInt)(f0.type.returnType);
282 expect(f0.type.normalParameterTypes[0], typeProvider.intType);
283 }
284
285 void test_constructorInitializer_propagation() {
286 String code = r'''
287 class A {
288 List<String> x;
289 A() : this.x = [];
290 }
291 ''';
292 CompilationUnit unit = resolveSource(code);
293 ConstructorDeclaration constructor =
294 AstFinder.getConstructorInClass(unit, "A", null);
295 ConstructorFieldInitializer assignment = constructor.initializers[0];
296 Expression exp = assignment.expression;
297 _isListOf(_isString)(exp.staticType);
298 }
299
300 void test_factoryConstructor_propagation() {
301 String code = r'''
302 class A<T> {
303 factory A() { return new B(); }
304 }
305 class B<S> extends A<S> {}
306 ''';
307 CompilationUnit unit = resolveSource(code);
308
309 ConstructorDeclaration constructor =
310 AstFinder.getConstructorInClass(unit, "A", null);
311 BlockFunctionBody body = constructor.body;
312 ReturnStatement stmt = body.block.statements[0];
313 InstanceCreationExpression exp = stmt.expression;
314 ClassElement elementB = AstFinder.getClass(unit, "B").element;
315 ClassElement elementA = AstFinder.getClass(unit, "A").element;
316 expect(exp.constructorName.type.type.element, elementB);
317 _isInstantiationOf(_hasElement(elementB))(
318 [_isType(elementA.typeParameters[0].type)])(exp.staticType);
319 }
320
321 void test_fieldDeclaration_propagation() {
322 String code = r'''
323 class A {
324 List<String> f0 = ["hello"];
325 }
326 ''';
327 CompilationUnit unit = resolveSource(code);
328
329 VariableDeclaration field = AstFinder.getFieldInClass(unit, "A", "f0");
330
331 _isListOf(_isString)(field.initializer.staticType);
332 }
333
334 void test_functionDeclaration_body_propagation() {
335 String code = r'''
336 typedef T Function2<S, T>(S x);
337
338 List<int> test1() => [];
339
340 Function2<int, int> test2 (int x) {
341 Function2<String, int> inner() {
342 return (x) => x.length;
343 }
344 return (x) => x;
345 }
346 ''';
347 CompilationUnit unit = resolveSource(code);
348
349 Asserter<InterfaceType> assertListOfInt = _isListOf(_isInt);
350
351 FunctionDeclaration test1 = AstFinder.getTopLevelFunction(unit, "test1");
352 ExpressionFunctionBody body = test1.functionExpression.body;
353 assertListOfInt(body.expression.staticType);
354
355 List<Statement> statements =
356 AstFinder.getStatementsInTopLevelFunction(unit, "test2");
357
358 FunctionDeclaration inner =
359 (statements[0] as FunctionDeclarationStatement).functionDeclaration;
360 BlockFunctionBody body0 = inner.functionExpression.body;
361 ReturnStatement return0 = body0.block.statements[0];
362 Expression anon0 = return0.expression;
363 FunctionType type0 = anon0.staticType;
364 expect(type0.returnType, typeProvider.intType);
365 expect(type0.normalParameterTypes[0], typeProvider.stringType);
366
367 FunctionExpression anon1 = (statements[1] as ReturnStatement).expression;
368 FunctionType type1 = anon1.element.type;
369 expect(type1.returnType, typeProvider.intType);
370 expect(type1.normalParameterTypes[0], typeProvider.intType);
371 }
372
373 void test_functionLiteral_assignment_typedArguments() {
374 String code = r'''
375 typedef T Function2<S, T>(S x);
376
377 void main () {
378 Function2<int, String> l0 = (int x) => null;
379 Function2<int, String> l1 = (int x) => "hello";
380 Function2<int, String> l2 = (String x) => "hello";
381 Function2<int, String> l3 = (int x) => 3;
382 Function2<int, String> l4 = (int x) {return 3;};
383 }
384 ''';
385 CompilationUnit unit = resolveSource(code);
386 List<Statement> statements =
387 AstFinder.getStatementsInTopLevelFunction(unit, "main");
388 DartType literal(int i) {
389 VariableDeclarationStatement stmt = statements[i];
390 VariableDeclaration decl = stmt.variables.variables[0];
391 FunctionExpression exp = decl.initializer;
392 return exp.element.type;
393 }
394 _isFunction2Of(_isInt, _isString)(literal(0));
395 _isFunction2Of(_isInt, _isString)(literal(1));
396 _isFunction2Of(_isString, _isString)(literal(2));
397 _isFunction2Of(_isInt, _isInt)(literal(3));
398 _isFunction2Of(_isInt, _isString)(literal(4));
399 }
400
401 void test_functionLiteral_assignment_unTypedArguments() {
402 String code = r'''
403 typedef T Function2<S, T>(S x);
404
405 void main () {
406 Function2<int, String> l0 = (x) => null;
407 Function2<int, String> l1 = (x) => "hello";
408 Function2<int, String> l2 = (x) => "hello";
409 Function2<int, String> l3 = (x) => 3;
410 Function2<int, String> l4 = (x) {return 3;};
411 }
412 ''';
413 CompilationUnit unit = resolveSource(code);
414 List<Statement> statements =
415 AstFinder.getStatementsInTopLevelFunction(unit, "main");
416 DartType literal(int i) {
417 VariableDeclarationStatement stmt = statements[i];
418 VariableDeclaration decl = stmt.variables.variables[0];
419 FunctionExpression exp = decl.initializer;
420 return exp.element.type;
421 }
422 _isFunction2Of(_isInt, _isString)(literal(0));
423 _isFunction2Of(_isInt, _isString)(literal(1));
424 _isFunction2Of(_isInt, _isString)(literal(2));
425 _isFunction2Of(_isInt, _isInt)(literal(3));
426 _isFunction2Of(_isInt, _isString)(literal(4));
427 }
428
429 void test_functionLiteral_body_propagation() {
430 String code = r'''
431 typedef T Function2<S, T>(S x);
432
433 void main () {
434 Function2<int, List<String>> l0 = (int x) => ["hello"];
435 Function2<int, List<String>> l1 = (String x) => ["hello"];
436 Function2<int, List<String>> l2 = (int x) => [3];
437 Function2<int, List<String>> l3 = (int x) {return [3];};
438 }
439 ''';
440 CompilationUnit unit = resolveSource(code);
441 List<Statement> statements =
442 AstFinder.getStatementsInTopLevelFunction(unit, "main");
443 Expression functionReturnValue(int i) {
444 VariableDeclarationStatement stmt = statements[i];
445 VariableDeclaration decl = stmt.variables.variables[0];
446 FunctionExpression exp = decl.initializer;
447 FunctionBody body = exp.body;
448 if (body is ExpressionFunctionBody) {
449 return body.expression;
450 } else {
451 Statement stmt = (body as BlockFunctionBody).block.statements[0];
452 return (stmt as ReturnStatement).expression;
453 }
454 }
455 Asserter<InterfaceType> assertListOfString = _isListOf(_isString);
456 assertListOfString(functionReturnValue(0).staticType);
457 assertListOfString(functionReturnValue(1).staticType);
458 assertListOfString(functionReturnValue(2).staticType);
459 assertListOfString(functionReturnValue(3).staticType);
460 }
461
462 void test_functionLiteral_functionExpressionInvocation_typedArguments() {
463 String code = r'''
464 class Mapper<F, T> {
465 T map(T mapper(F x)) => mapper(null);
466 }
467
468 void main () {
469 (new Mapper<int, String>().map)((int x) => null);
470 (new Mapper<int, String>().map)((int x) => "hello");
471 (new Mapper<int, String>().map)((String x) => "hello");
472 (new Mapper<int, String>().map)((int x) => 3);
473 (new Mapper<int, String>().map)((int x) {return 3;});
474 }
475 ''';
476 CompilationUnit unit = resolveSource(code);
477 List<Statement> statements =
478 AstFinder.getStatementsInTopLevelFunction(unit, "main");
479 DartType literal(int i) {
480 ExpressionStatement stmt = statements[i];
481 FunctionExpressionInvocation invk = stmt.expression;
482 FunctionExpression exp = invk.argumentList.arguments[0];
483 return exp.element.type;
484 }
485 _isFunction2Of(_isInt, _isString)(literal(0));
486 _isFunction2Of(_isInt, _isString)(literal(1));
487 _isFunction2Of(_isString, _isString)(literal(2));
488 _isFunction2Of(_isInt, _isInt)(literal(3));
489 _isFunction2Of(_isInt, _isString)(literal(4));
490 }
491
492 void test_functionLiteral_functionExpressionInvocation_unTypedArguments() {
493 String code = r'''
494 class Mapper<F, T> {
495 T map(T mapper(F x)) => mapper(null);
496 }
497
498 void main () {
499 (new Mapper<int, String>().map)((x) => null);
500 (new Mapper<int, String>().map)((x) => "hello");
501 (new Mapper<int, String>().map)((x) => "hello");
502 (new Mapper<int, String>().map)((x) => 3);
503 (new Mapper<int, String>().map)((x) {return 3;});
504 }
505 ''';
506 CompilationUnit unit = resolveSource(code);
507 List<Statement> statements =
508 AstFinder.getStatementsInTopLevelFunction(unit, "main");
509 DartType literal(int i) {
510 ExpressionStatement stmt = statements[i];
511 FunctionExpressionInvocation invk = stmt.expression;
512 FunctionExpression exp = invk.argumentList.arguments[0];
513 return exp.element.type;
514 }
515 _isFunction2Of(_isInt, _isString)(literal(0));
516 _isFunction2Of(_isInt, _isString)(literal(1));
517 _isFunction2Of(_isInt, _isString)(literal(2));
518 _isFunction2Of(_isInt, _isInt)(literal(3));
519 _isFunction2Of(_isInt, _isString)(literal(4));
520 }
521
522 void test_functionLiteral_functionInvocation_typedArguments() {
523 String code = r'''
524 String map(String mapper(int x)) => mapper(null);
525
526 void main () {
527 map((int x) => null);
528 map((int x) => "hello");
529 map((String x) => "hello");
530 map((int x) => 3);
531 map((int x) {return 3;});
532 }
533 ''';
534 CompilationUnit unit = resolveSource(code);
535 List<Statement> statements =
536 AstFinder.getStatementsInTopLevelFunction(unit, "main");
537 DartType literal(int i) {
538 ExpressionStatement stmt = statements[i];
539 MethodInvocation invk = stmt.expression;
540 FunctionExpression exp = invk.argumentList.arguments[0];
541 return exp.element.type;
542 }
543 _isFunction2Of(_isInt, _isString)(literal(0));
544 _isFunction2Of(_isInt, _isString)(literal(1));
545 _isFunction2Of(_isString, _isString)(literal(2));
546 _isFunction2Of(_isInt, _isInt)(literal(3));
547 _isFunction2Of(_isInt, _isString)(literal(4));
548 }
549
550 void test_functionLiteral_functionInvocation_unTypedArguments() {
551 String code = r'''
552 String map(String mapper(int x)) => mapper(null);
553
554 void main () {
555 map((x) => null);
556 map((x) => "hello");
557 map((x) => "hello");
558 map((x) => 3);
559 map((x) {return 3;});
560 }
561 ''';
562 CompilationUnit unit = resolveSource(code);
563 List<Statement> statements =
564 AstFinder.getStatementsInTopLevelFunction(unit, "main");
565 DartType literal(int i) {
566 ExpressionStatement stmt = statements[i];
567 MethodInvocation invk = stmt.expression;
568 FunctionExpression exp = invk.argumentList.arguments[0];
569 return exp.element.type;
570 }
571 _isFunction2Of(_isInt, _isString)(literal(0));
572 _isFunction2Of(_isInt, _isString)(literal(1));
573 _isFunction2Of(_isInt, _isString)(literal(2));
574 _isFunction2Of(_isInt, _isInt)(literal(3));
575 _isFunction2Of(_isInt, _isString)(literal(4));
576 }
577
578 void test_functionLiteral_methodInvocation_typedArguments() {
579 String code = r'''
580 class Mapper<F, T> {
581 T map(T mapper(F x)) => mapper(null);
582 }
583
584 void main () {
585 new Mapper<int, String>().map((int x) => null);
586 new Mapper<int, String>().map((int x) => "hello");
587 new Mapper<int, String>().map((String x) => "hello");
588 new Mapper<int, String>().map((int x) => 3);
589 new Mapper<int, String>().map((int x) {return 3;});
590 }
591 ''';
592 CompilationUnit unit = resolveSource(code);
593 List<Statement> statements =
594 AstFinder.getStatementsInTopLevelFunction(unit, "main");
595 DartType literal(int i) {
596 ExpressionStatement stmt = statements[i];
597 MethodInvocation invk = stmt.expression;
598 FunctionExpression exp = invk.argumentList.arguments[0];
599 return exp.element.type;
600 }
601 _isFunction2Of(_isInt, _isString)(literal(0));
602 _isFunction2Of(_isInt, _isString)(literal(1));
603 _isFunction2Of(_isString, _isString)(literal(2));
604 _isFunction2Of(_isInt, _isInt)(literal(3));
605 _isFunction2Of(_isInt, _isString)(literal(4));
606 }
607
608 void test_functionLiteral_methodInvocation_unTypedArguments() {
609 String code = r'''
610 class Mapper<F, T> {
611 T map(T mapper(F x)) => mapper(null);
612 }
613
614 void main () {
615 new Mapper<int, String>().map((x) => null);
616 new Mapper<int, String>().map((x) => "hello");
617 new Mapper<int, String>().map((x) => "hello");
618 new Mapper<int, String>().map((x) => 3);
619 new Mapper<int, String>().map((x) {return 3;});
620 }
621 ''';
622 CompilationUnit unit = resolveSource(code);
623 List<Statement> statements =
624 AstFinder.getStatementsInTopLevelFunction(unit, "main");
625 DartType literal(int i) {
626 ExpressionStatement stmt = statements[i];
627 MethodInvocation invk = stmt.expression;
628 FunctionExpression exp = invk.argumentList.arguments[0];
629 return exp.element.type;
630 }
631 _isFunction2Of(_isInt, _isString)(literal(0));
632 _isFunction2Of(_isInt, _isString)(literal(1));
633 _isFunction2Of(_isInt, _isString)(literal(2));
634 _isFunction2Of(_isInt, _isInt)(literal(3));
635 _isFunction2Of(_isInt, _isString)(literal(4));
636 }
637
638 void test_functionLiteral_unTypedArgument_propagation() {
639 String code = r'''
640 typedef T Function2<S, T>(S x);
641
642 void main () {
643 Function2<int, int> l0 = (x) => x;
644 Function2<int, int> l1 = (x) => x+1;
645 Function2<int, String> l2 = (x) => x;
646 Function2<int, String> l3 = (x) => x.toLowerCase();
647 Function2<String, String> l4 = (x) => x.toLowerCase();
648 }
649 ''';
650 CompilationUnit unit = resolveSource(code);
651 List<Statement> statements =
652 AstFinder.getStatementsInTopLevelFunction(unit, "main");
653 Expression functionReturnValue(int i) {
654 VariableDeclarationStatement stmt = statements[i];
655 VariableDeclaration decl = stmt.variables.variables[0];
656 FunctionExpression exp = decl.initializer;
657 FunctionBody body = exp.body;
658 if (body is ExpressionFunctionBody) {
659 return body.expression;
660 } else {
661 Statement stmt = (body as BlockFunctionBody).block.statements[0];
662 return (stmt as ReturnStatement).expression;
663 }
664 }
665 expect(functionReturnValue(0).staticType, typeProvider.intType);
666 expect(functionReturnValue(1).staticType, typeProvider.intType);
667 expect(functionReturnValue(2).staticType, typeProvider.intType);
668 expect(functionReturnValue(3).staticType, typeProvider.dynamicType);
669 expect(functionReturnValue(4).staticType, typeProvider.stringType);
670 }
671
672 void test_inference_hints() {
673 Source source = addSource(r'''
674 void main () {
675 var x = 3;
676 List<int> l0 = [];
677 }
678 ''');
679 resolve2(source);
680 assertNoErrors(source);
681 verify([source]);
682 }
683
684 void test_instanceCreation() {
685 String code = r'''
686 class A<S, T> {
687 S x;
688 T y;
689 A(this.x, this.y);
690 A.named(this.x, this.y);
691 }
692
693 class B<S, T> extends A<T, S> {
694 B(S y, T x) : super(x, y);
695 B.named(S y, T x) : super.named(x, y);
696 }
697
698 class C<S> extends B<S, S> {
699 C(S a) : super(a, a);
700 C.named(S a) : super.named(a, a);
701 }
702
703 class D<S, T> extends B<T, int> {
704 D(T a) : super(a, 3);
705 D.named(T a) : super.named(a, 3);
706 }
707
708 class E<S, T> extends A<C<S>, T> {
709 E(T a) : super(null, a);
710 }
711
712 class F<S, T> extends A<S, T> {
713 F(S x, T y, {List<S> a, List<T> b}) : super(x, y);
714 F.named(S x, T y, [S a, T b]) : super(a, b);
715 }
716
717 void test0() {
718 A<int, String> a0 = new A(3, "hello");
719 A<int, String> a1 = new A.named(3, "hello");
720 A<int, String> a2 = new A<int, String>(3, "hello");
721 A<int, String> a3 = new A<int, String>.named(3, "hello");
722 A<int, String> a4 = new A<int, dynamic>(3, "hello");
723 A<int, String> a5 = new A<dynamic, dynamic>.named(3, "hello");
724 }
725 void test1() {
726 A<int, String> a0 = new A("hello", 3);
727 A<int, String> a1 = new A.named("hello", 3);
728 }
729 void test2() {
730 A<int, String> a0 = new B("hello", 3);
731 A<int, String> a1 = new B.named("hello", 3);
732 A<int, String> a2 = new B<String, int>("hello", 3);
733 A<int, String> a3 = new B<String, int>.named("hello", 3);
734 A<int, String> a4 = new B<String, dynamic>("hello", 3);
735 A<int, String> a5 = new B<dynamic, dynamic>.named("hello", 3);
736 }
737 void test3() {
738 A<int, String> a0 = new B(3, "hello");
739 A<int, String> a1 = new B.named(3, "hello");
740 }
741 void test4() {
742 A<int, int> a0 = new C(3);
743 A<int, int> a1 = new C.named(3);
744 A<int, int> a2 = new C<int>(3);
745 A<int, int> a3 = new C<int>.named(3);
746 A<int, int> a4 = new C<dynamic>(3);
747 A<int, int> a5 = new C<dynamic>.named(3);
748 }
749 void test5() {
750 A<int, int> a0 = new C("hello");
751 A<int, int> a1 = new C.named("hello");
752 }
753 void test6() {
754 A<int, String> a0 = new D("hello");
755 A<int, String> a1 = new D.named("hello");
756 A<int, String> a2 = new D<int, String>("hello");
757 A<int, String> a3 = new D<String, String>.named("hello");
758 A<int, String> a4 = new D<num, dynamic>("hello");
759 A<int, String> a5 = new D<dynamic, dynamic>.named("hello");
760 }
761 void test7() {
762 A<int, String> a0 = new D(3);
763 A<int, String> a1 = new D.named(3);
764 }
765 void test8() {
766 // Currently we only allow variable constraints. Test that we reject.
767 A<C<int>, String> a0 = new E("hello");
768 }
769 void test9() { // Check named and optional arguments
770 A<int, String> a0 = new F(3, "hello", a: [3], b: ["hello"]);
771 A<int, String> a1 = new F(3, "hello", a: ["hello"], b:[3]);
772 A<int, String> a2 = new F.named(3, "hello", 3, "hello");
773 A<int, String> a3 = new F.named(3, "hello");
774 A<int, String> a4 = new F.named(3, "hello", "hello", 3);
775 A<int, String> a5 = new F.named(3, "hello", "hello");
776 }
777 }''';
778 CompilationUnit unit = resolveSource(code);
779
780 Expression rhs(VariableDeclarationStatement stmt) {
781 VariableDeclaration decl = stmt.variables.variables[0];
782 Expression exp = decl.initializer;
783 return exp;
784 }
785
786 void hasType(Asserter<DartType> assertion, Expression exp) =>
787 assertion(exp.staticType);
788
789 Element elementA = AstFinder.getClass(unit, "A").element;
790 Element elementB = AstFinder.getClass(unit, "B").element;
791 Element elementC = AstFinder.getClass(unit, "C").element;
792 Element elementD = AstFinder.getClass(unit, "D").element;
793 Element elementE = AstFinder.getClass(unit, "E").element;
794 Element elementF = AstFinder.getClass(unit, "F").element;
795
796 AsserterBuilder<List<Asserter<DartType>>, DartType> assertAOf =
797 _isInstantiationOf(_hasElement(elementA));
798 AsserterBuilder<List<Asserter<DartType>>, DartType> assertBOf =
799 _isInstantiationOf(_hasElement(elementB));
800 AsserterBuilder<List<Asserter<DartType>>, DartType> assertCOf =
801 _isInstantiationOf(_hasElement(elementC));
802 AsserterBuilder<List<Asserter<DartType>>, DartType> assertDOf =
803 _isInstantiationOf(_hasElement(elementD));
804 AsserterBuilder<List<Asserter<DartType>>, DartType> assertEOf =
805 _isInstantiationOf(_hasElement(elementE));
806 AsserterBuilder<List<Asserter<DartType>>, DartType> assertFOf =
807 _isInstantiationOf(_hasElement(elementF));
808
809 {
810 List<Statement> statements =
811 AstFinder.getStatementsInTopLevelFunction(unit, "test0");
812
813 hasType(assertAOf([_isInt, _isString]), rhs(statements[0]));
814 hasType(assertAOf([_isInt, _isString]), rhs(statements[0]));
815 hasType(assertAOf([_isInt, _isString]), rhs(statements[1]));
816 hasType(assertAOf([_isInt, _isString]), rhs(statements[2]));
817 hasType(assertAOf([_isInt, _isString]), rhs(statements[3]));
818 hasType(assertAOf([_isInt, _isDynamic]), rhs(statements[4]));
819 hasType(assertAOf([_isDynamic, _isDynamic]), rhs(statements[5]));
820 }
821
822 {
823 List<Statement> statements =
824 AstFinder.getStatementsInTopLevelFunction(unit, "test1");
825 hasType(assertAOf([_isInt, _isString]), rhs(statements[0]));
826 hasType(assertAOf([_isInt, _isString]), rhs(statements[1]));
827 }
828
829 {
830 List<Statement> statements =
831 AstFinder.getStatementsInTopLevelFunction(unit, "test2");
832 hasType(assertBOf([_isString, _isInt]), rhs(statements[0]));
833 hasType(assertBOf([_isString, _isInt]), rhs(statements[1]));
834 hasType(assertBOf([_isString, _isInt]), rhs(statements[2]));
835 hasType(assertBOf([_isString, _isInt]), rhs(statements[3]));
836 hasType(assertBOf([_isString, _isDynamic]), rhs(statements[4]));
837 hasType(assertBOf([_isDynamic, _isDynamic]), rhs(statements[5]));
838 }
839
840 {
841 List<Statement> statements =
842 AstFinder.getStatementsInTopLevelFunction(unit, "test3");
843 hasType(assertBOf([_isString, _isInt]), rhs(statements[0]));
844 hasType(assertBOf([_isString, _isInt]), rhs(statements[1]));
845 }
846
847 {
848 List<Statement> statements =
849 AstFinder.getStatementsInTopLevelFunction(unit, "test4");
850 hasType(assertCOf([_isInt]), rhs(statements[0]));
851 hasType(assertCOf([_isInt]), rhs(statements[1]));
852 hasType(assertCOf([_isInt]), rhs(statements[2]));
853 hasType(assertCOf([_isInt]), rhs(statements[3]));
854 hasType(assertCOf([_isDynamic]), rhs(statements[4]));
855 hasType(assertCOf([_isDynamic]), rhs(statements[5]));
856 }
857
858 {
859 List<Statement> statements =
860 AstFinder.getStatementsInTopLevelFunction(unit, "test5");
861 hasType(assertCOf([_isInt]), rhs(statements[0]));
862 hasType(assertCOf([_isInt]), rhs(statements[1]));
863 }
864
865 {
866 // The first type parameter is not constrained by the
867 // context. We could choose a tighter type, but currently
868 // we just use dynamic.
869 List<Statement> statements =
870 AstFinder.getStatementsInTopLevelFunction(unit, "test6");
871 hasType(assertDOf([_isDynamic, _isString]), rhs(statements[0]));
872 hasType(assertDOf([_isDynamic, _isString]), rhs(statements[1]));
873 hasType(assertDOf([_isInt, _isString]), rhs(statements[2]));
874 hasType(assertDOf([_isString, _isString]), rhs(statements[3]));
875 hasType(assertDOf([_isNum, _isDynamic]), rhs(statements[4]));
876 hasType(assertDOf([_isDynamic, _isDynamic]), rhs(statements[5]));
877 }
878
879 {
880 List<Statement> statements =
881 AstFinder.getStatementsInTopLevelFunction(unit, "test7");
882 hasType(assertDOf([_isDynamic, _isString]), rhs(statements[0]));
883 hasType(assertDOf([_isDynamic, _isString]), rhs(statements[1]));
884 }
885
886 {
887 List<Statement> statements =
888 AstFinder.getStatementsInTopLevelFunction(unit, "test8");
889 hasType(assertEOf([_isDynamic, _isDynamic]), rhs(statements[0]));
890 }
891
892 {
893 List<Statement> statements =
894 AstFinder.getStatementsInTopLevelFunction(unit, "test9");
895 hasType(assertFOf([_isInt, _isString]), rhs(statements[0]));
896 hasType(assertFOf([_isInt, _isString]), rhs(statements[1]));
897 hasType(assertFOf([_isInt, _isString]), rhs(statements[2]));
898 hasType(assertFOf([_isInt, _isString]), rhs(statements[3]));
899 hasType(assertFOf([_isInt, _isString]), rhs(statements[4]));
900 hasType(assertFOf([_isInt, _isString]), rhs(statements[5]));
901 }
902 }
903
904 void test_listLiteral_nested() {
905 String code = r'''
906 void main () {
907 List<List<int>> l0 = [[]];
908 Iterable<List<int>> l1 = [[3]];
909 Iterable<List<int>> l2 = [[3], [4]];
910 List<List<int>> l3 = [["hello", 3], []];
911 }
912 ''';
913 CompilationUnit unit = resolveSource(code);
914 List<Statement> statements =
915 AstFinder.getStatementsInTopLevelFunction(unit, "main");
916 ListLiteral literal(int i) {
917 VariableDeclarationStatement stmt = statements[i];
918 VariableDeclaration decl = stmt.variables.variables[0];
919 ListLiteral exp = decl.initializer;
920 return exp;
921 }
922
923 Asserter<InterfaceType> assertListOfInt = _isListOf(_isInt);
924 Asserter<InterfaceType> assertListOfListOfInt = _isListOf(assertListOfInt);
925
926 assertListOfListOfInt(literal(0).staticType);
927 assertListOfListOfInt(literal(1).staticType);
928 assertListOfListOfInt(literal(2).staticType);
929 assertListOfListOfInt(literal(3).staticType);
930
931 assertListOfInt(literal(1).elements[0].staticType);
932 assertListOfInt(literal(2).elements[0].staticType);
933 assertListOfInt(literal(3).elements[0].staticType);
934 }
935
936 void test_listLiteral_simple() {
937 String code = r'''
938 void main () {
939 List<int> l0 = [];
940 List<int> l1 = [3];
941 List<int> l2 = ["hello"];
942 List<int> l3 = ["hello", 3];
943 }
944 ''';
945 CompilationUnit unit = resolveSource(code);
946 List<Statement> statements =
947 AstFinder.getStatementsInTopLevelFunction(unit, "main");
948 DartType literal(int i) {
949 VariableDeclarationStatement stmt = statements[i];
950 VariableDeclaration decl = stmt.variables.variables[0];
951 ListLiteral exp = decl.initializer;
952 return exp.staticType;
953 }
954
955 Asserter<InterfaceType> assertListOfInt = _isListOf(_isInt);
956
957 assertListOfInt(literal(0));
958 assertListOfInt(literal(1));
959 assertListOfInt(literal(2));
960 assertListOfInt(literal(3));
961 }
962
963 void test_listLiteral_simple_const() {
964 String code = r'''
965 void main () {
966 const List<int> c0 = const [];
967 const List<int> c1 = const [3];
968 const List<int> c2 = const ["hello"];
969 const List<int> c3 = const ["hello", 3];
970 }
971 ''';
972 CompilationUnit unit = resolveSource(code);
973 List<Statement> statements =
974 AstFinder.getStatementsInTopLevelFunction(unit, "main");
975 DartType literal(int i) {
976 VariableDeclarationStatement stmt = statements[i];
977 VariableDeclaration decl = stmt.variables.variables[0];
978 ListLiteral exp = decl.initializer;
979 return exp.staticType;
980 }
981
982 Asserter<InterfaceType> assertListOfInt = _isListOf(_isInt);
983
984 assertListOfInt(literal(0));
985 assertListOfInt(literal(1));
986 assertListOfInt(literal(2));
987 assertListOfInt(literal(3));
988 }
989
990 void test_listLiteral_simple_disabled() {
991 String code = r'''
992 void main () {
993 List<int> l0 = <num>[];
994 List<int> l1 = <num>[3];
995 List<int> l2 = <String>["hello"];
996 List<int> l3 = <dynamic>["hello", 3];
997 }
998 ''';
999 CompilationUnit unit = resolveSource(code);
1000 List<Statement> statements =
1001 AstFinder.getStatementsInTopLevelFunction(unit, "main");
1002 DartType literal(int i) {
1003 VariableDeclarationStatement stmt = statements[i];
1004 VariableDeclaration decl = stmt.variables.variables[0];
1005 ListLiteral exp = decl.initializer;
1006 return exp.staticType;
1007 }
1008
1009 _isListOf(_isNum)(literal(0));
1010 _isListOf(_isNum)(literal(1));
1011 _isListOf(_isString)(literal(2));
1012 _isListOf(_isDynamic)(literal(3));
1013 }
1014
1015 void test_listLiteral_simple_subtype() {
1016 String code = r'''
1017 void main () {
1018 Iterable<int> l0 = [];
1019 Iterable<int> l1 = [3];
1020 Iterable<int> l2 = ["hello"];
1021 Iterable<int> l3 = ["hello", 3];
1022 }
1023 ''';
1024 CompilationUnit unit = resolveSource(code);
1025 List<Statement> statements =
1026 AstFinder.getStatementsInTopLevelFunction(unit, "main");
1027 DartType literal(int i) {
1028 VariableDeclarationStatement stmt = statements[i];
1029 VariableDeclaration decl = stmt.variables.variables[0];
1030 ListLiteral exp = decl.initializer;
1031 return exp.staticType;
1032 }
1033
1034 Asserter<InterfaceType> assertListOfInt = _isListOf(_isInt);
1035
1036 assertListOfInt(literal(0));
1037 assertListOfInt(literal(1));
1038 assertListOfInt(literal(2));
1039 assertListOfInt(literal(3));
1040 }
1041
1042 void test_mapLiteral_nested() {
1043 String code = r'''
1044 void main () {
1045 Map<int, List<String>> l0 = {};
1046 Map<int, List<String>> l1 = {3: ["hello"]};
1047 Map<int, List<String>> l2 = {"hello": ["hello"]};
1048 Map<int, List<String>> l3 = {3: [3]};
1049 Map<int, List<String>> l4 = {3:["hello"], "hello": [3]};
1050 }
1051 ''';
1052 CompilationUnit unit = resolveSource(code);
1053 List<Statement> statements =
1054 AstFinder.getStatementsInTopLevelFunction(unit, "main");
1055 MapLiteral literal(int i) {
1056 VariableDeclarationStatement stmt = statements[i];
1057 VariableDeclaration decl = stmt.variables.variables[0];
1058 MapLiteral exp = decl.initializer;
1059 return exp;
1060 }
1061
1062 Asserter<InterfaceType> assertListOfString = _isListOf(_isString);
1063 Asserter<InterfaceType> assertMapOfIntToListOfString =
1064 _isMapOf(_isInt, assertListOfString);
1065
1066 assertMapOfIntToListOfString(literal(0).staticType);
1067 assertMapOfIntToListOfString(literal(1).staticType);
1068 assertMapOfIntToListOfString(literal(2).staticType);
1069 assertMapOfIntToListOfString(literal(3).staticType);
1070 assertMapOfIntToListOfString(literal(4).staticType);
1071
1072 assertListOfString(literal(1).entries[0].value.staticType);
1073 assertListOfString(literal(2).entries[0].value.staticType);
1074 assertListOfString(literal(3).entries[0].value.staticType);
1075 assertListOfString(literal(4).entries[0].value.staticType);
1076 }
1077
1078 void test_mapLiteral_simple() {
1079 String code = r'''
1080 void main () {
1081 Map<int, String> l0 = {};
1082 Map<int, String> l1 = {3: "hello"};
1083 Map<int, String> l2 = {"hello": "hello"};
1084 Map<int, String> l3 = {3: 3};
1085 Map<int, String> l4 = {3:"hello", "hello": 3};
1086 }
1087 ''';
1088 CompilationUnit unit = resolveSource(code);
1089 List<Statement> statements =
1090 AstFinder.getStatementsInTopLevelFunction(unit, "main");
1091 DartType literal(int i) {
1092 VariableDeclarationStatement stmt = statements[i];
1093 VariableDeclaration decl = stmt.variables.variables[0];
1094 MapLiteral exp = decl.initializer;
1095 return exp.staticType;
1096 }
1097
1098 Asserter<InterfaceType> assertMapOfIntToString =
1099 _isMapOf(_isInt, _isString);
1100
1101 assertMapOfIntToString(literal(0));
1102 assertMapOfIntToString(literal(1));
1103 assertMapOfIntToString(literal(2));
1104 assertMapOfIntToString(literal(3));
1105 }
1106
1107 void test_mapLiteral_simple_disabled() {
1108 String code = r'''
1109 void main () {
1110 Map<int, String> l0 = <int, dynamic>{};
1111 Map<int, String> l1 = <int, dynamic>{3: "hello"};
1112 Map<int, String> l2 = <int, dynamic>{"hello": "hello"};
1113 Map<int, String> l3 = <int, dynamic>{3: 3};
1114 }
1115 ''';
1116 CompilationUnit unit = resolveSource(code);
1117 List<Statement> statements =
1118 AstFinder.getStatementsInTopLevelFunction(unit, "main");
1119 DartType literal(int i) {
1120 VariableDeclarationStatement stmt = statements[i];
1121 VariableDeclaration decl = stmt.variables.variables[0];
1122 MapLiteral exp = decl.initializer;
1123 return exp.staticType;
1124 }
1125
1126 Asserter<InterfaceType> assertMapOfIntToDynamic =
1127 _isMapOf(_isInt, _isDynamic);
1128
1129 assertMapOfIntToDynamic(literal(0));
1130 assertMapOfIntToDynamic(literal(1));
1131 assertMapOfIntToDynamic(literal(2));
1132 assertMapOfIntToDynamic(literal(3));
1133 }
1134
1135 void test_methodDeclaration_body_propagation() {
1136 String code = r'''
1137 class A {
1138 List<String> m0(int x) => ["hello"];
1139 List<String> m1(int x) {return [3];};
1140 }
1141 ''';
1142 CompilationUnit unit = resolveSource(code);
1143 Expression methodReturnValue(String methodName) {
1144 MethodDeclaration method =
1145 AstFinder.getMethodInClass(unit, "A", methodName);
1146 FunctionBody body = method.body;
1147 if (body is ExpressionFunctionBody) {
1148 return body.expression;
1149 } else {
1150 Statement stmt = (body as BlockFunctionBody).block.statements[0];
1151 return (stmt as ReturnStatement).expression;
1152 }
1153 }
1154 Asserter<InterfaceType> assertListOfString = _isListOf(_isString);
1155 assertListOfString(methodReturnValue("m0").staticType);
1156 assertListOfString(methodReturnValue("m1").staticType);
1157 }
1158
1159 void test_redirectingConstructor_propagation() {
1160 String code = r'''
1161 class A {
1162 A() : this.named([]);
1163 A.named(List<String> x);
1164 }
1165 ''';
1166 CompilationUnit unit = resolveSource(code);
1167
1168 ConstructorDeclaration constructor =
1169 AstFinder.getConstructorInClass(unit, "A", null);
1170 RedirectingConstructorInvocation invocation = constructor.initializers[0];
1171 Expression exp = invocation.argumentList.arguments[0];
1172 _isListOf(_isString)(exp.staticType);
1173 }
1174
1175 void test_superConstructorInvocation_propagation() {
1176 String code = r'''
1177 class B {
1178 B(List<String>);
1179 }
1180 class A extends B {
1181 A() : super([]);
1182 }
1183 ''';
1184 CompilationUnit unit = resolveSource(code);
1185
1186 ConstructorDeclaration constructor =
1187 AstFinder.getConstructorInClass(unit, "A", null);
1188 SuperConstructorInvocation invocation = constructor.initializers[0];
1189 Expression exp = invocation.argumentList.arguments[0];
1190 _isListOf(_isString)(exp.staticType);
1191 }
1192
1193 void test_sync_star_method_propagation() {
1194 String code = r'''
1195 import "dart:async";
1196 class A {
1197 Iterable f0() sync* { yield []; }
1198 Iterable f1() sync* { yield* new List(); }
1199
1200 Iterable<List<int>> f2() sync* { yield []; }
1201 Iterable<List<int>> f3() sync* { yield* new List(); }
1202 }
1203 ''';
1204 CompilationUnit unit = resolveSource(code);
1205
1206 void check(String name, Asserter<InterfaceType> typeTest) {
1207 MethodDeclaration test = AstFinder.getMethodInClass(unit, "A", name);
1208 BlockFunctionBody body = test.body;
1209 YieldStatement stmt = body.block.statements[0];
1210 Expression exp = stmt.expression;
1211 typeTest(exp.staticType);
1212 }
1213
1214 check("f0", _isListOf(_isDynamic));
1215 check("f1", _isListOf(_isDynamic));
1216
1217 check("f2", _isListOf(_isInt));
1218 check("f3", _isListOf(_isListOf(_isInt)));
1219 }
1220
1221 void test_sync_star_propagation() {
1222 String code = r'''
1223 import "dart:async";
1224
1225 Iterable f0() sync* { yield []; }
1226 Iterable f1() sync* { yield* new List(); }
1227
1228 Iterable<List<int>> f2() sync* { yield []; }
1229 Iterable<List<int>> f3() sync* { yield* new List(); }
1230 ''';
1231 CompilationUnit unit = resolveSource(code);
1232
1233 void check(String name, Asserter<InterfaceType> typeTest) {
1234 FunctionDeclaration test = AstFinder.getTopLevelFunction(unit, name);
1235 BlockFunctionBody body = test.functionExpression.body;
1236 YieldStatement stmt = body.block.statements[0];
1237 Expression exp = stmt.expression;
1238 typeTest(exp.staticType);
1239 }
1240
1241 check("f0", _isListOf(_isDynamic));
1242 check("f1", _isListOf(_isDynamic));
1243
1244 check("f2", _isListOf(_isInt));
1245 check("f3", _isListOf(_isListOf(_isInt)));
1246 }
1247 }
1248
1249 /**
1250 * Strong mode static analyzer end to end tests
1251 */
1252 @reflectiveTest
1253 class StrongModeStaticTypeAnalyzer2Test extends StaticTypeAnalyzer2TestShared {
1254 void fail_genericMethod_tearoff_instantiated() {
1255 resolveTestUnit(r'''
1256 class C<E> {
1257 /*=T*/ f/*<T>*/(E e) => null;
1258 static /*=T*/ g/*<T>*/(/*=T*/ e) => null;
1259 static final h = g;
1260 }
1261
1262 /*=T*/ topF/*<T>*/(/*=T*/ e) => null;
1263 var topG = topF;
1264 void test/*<S>*/(/*=T*/ pf/*<T>*/(/*=T*/ e)) {
1265 var c = new C<int>();
1266 /*=T*/ lf/*<T>*/(/*=T*/ e) => null;
1267 var methodTearOffInst = c.f/*<int>*/;
1268 var staticTearOffInst = C.g/*<int>*/;
1269 var staticFieldTearOffInst = C.h/*<int>*/;
1270 var topFunTearOffInst = topF/*<int>*/;
1271 var topFieldTearOffInst = topG/*<int>*/;
1272 var localTearOffInst = lf/*<int>*/;
1273 var paramTearOffInst = pf/*<int>*/;
1274 }
1275 ''');
1276 expectIdentifierType('methodTearOffInst', "(int) → int");
1277 expectIdentifierType('staticTearOffInst', "(int) → int");
1278 expectIdentifierType('staticFieldTearOffInst', "(int) → int");
1279 expectIdentifierType('topFunTearOffInst', "(int) → int");
1280 expectIdentifierType('topFieldTearOffInst', "(int) → int");
1281 expectIdentifierType('localTearOffInst', "(int) → int");
1282 expectIdentifierType('paramTearOffInst', "(int) → int");
1283 }
1284
1285 void setUp() {
1286 super.setUp();
1287 AnalysisOptionsImpl options = new AnalysisOptionsImpl();
1288 options.strongMode = true;
1289 resetWithOptions(options);
1290 }
1291
1292 void test_dynamicObjectGetter_hashCode() {
1293 String code = r'''
1294 main() {
1295 dynamic a = null;
1296 var foo = a.hashCode;
1297 }
1298 ''';
1299 resolveTestUnit(code);
1300 expectInitializerType('foo', 'int', isNull);
1301 }
1302
1303 void test_dynamicObjectMethod_toString() {
1304 String code = r'''
1305 main() {
1306 dynamic a = null;
1307 var foo = a.toString();
1308 }
1309 ''';
1310 resolveTestUnit(code);
1311 expectInitializerType('foo', 'String', isNull);
1312 }
1313
1314 void test_genericFunction() {
1315 resolveTestUnit(r'/*=T*/ f/*<T>*/(/*=T*/ x) => null;');
1316 expectFunctionType('f', '<T>(T) → T',
1317 elementTypeParams: '[T]', typeFormals: '[T]');
1318 SimpleIdentifier f = findIdentifier('f');
1319 FunctionElementImpl e = f.staticElement;
1320 FunctionType ft = e.type.instantiate([typeProvider.stringType]);
1321 expect(ft.toString(), '(String) → String');
1322 }
1323
1324 void test_genericFunction_bounds() {
1325 resolveTestUnit(r'/*=T*/ f/*<T extends num>*/(/*=T*/ x) => null;');
1326 expectFunctionType('f', '<T extends num>(T) → T',
1327 elementTypeParams: '[T extends num]', typeFormals: '[T extends num]');
1328 }
1329
1330 void test_genericFunction_parameter() {
1331 resolveTestUnit(r'''
1332 void g(/*=T*/ f/*<T>*/(/*=T*/ x)) {}
1333 ''');
1334 expectFunctionType('f', '<T>(T) → T',
1335 elementTypeParams: '[T]', typeFormals: '[T]');
1336 SimpleIdentifier f = findIdentifier('f');
1337 ParameterElementImpl e = f.staticElement;
1338 FunctionType type = e.type;
1339 FunctionType ft = type.instantiate([typeProvider.stringType]);
1340 expect(ft.toString(), '(String) → String');
1341 }
1342
1343 void test_genericFunction_static() {
1344 resolveTestUnit(r'''
1345 class C<E> {
1346 static /*=T*/ f/*<T>*/(/*=T*/ x) => null;
1347 }
1348 ''');
1349 expectFunctionType('f', '<T>(T) → T',
1350 elementTypeParams: '[T]', typeFormals: '[T]');
1351 SimpleIdentifier f = findIdentifier('f');
1352 MethodElementImpl e = f.staticElement;
1353 FunctionType ft = e.type.instantiate([typeProvider.stringType]);
1354 expect(ft.toString(), '(String) → String');
1355 }
1356
1357 void test_genericFunction_typedef() {
1358 String code = r'''
1359 typedef T F<T>(T x);
1360 F f0;
1361
1362 class C {
1363 static F f1;
1364 F f2;
1365 void g(F f3) {
1366 F f4;
1367 f0(3);
1368 f1(3);
1369 f2(3);
1370 f3(3);
1371 f4(3);
1372 }
1373 }
1374
1375 class D<S> {
1376 static F f1;
1377 F f2;
1378 void g(F f3) {
1379 F f4;
1380 f0(3);
1381 f1(3);
1382 f2(3);
1383 f3(3);
1384 f4(3);
1385 }
1386 }
1387 ''';
1388 resolveTestUnit(code);
1389
1390 checkBody(String className) {
1391 List<Statement> statements =
1392 AstFinder.getStatementsInMethod(testUnit, className, "g");
1393
1394 for (int i = 1; i <= 5; i++) {
1395 Expression exp = (statements[i] as ExpressionStatement).expression;
1396 expect(exp.staticType, typeProvider.dynamicType);
1397 }
1398 }
1399
1400 checkBody("C");
1401 checkBody("D");
1402 }
1403
1404 void test_genericMethod() {
1405 resolveTestUnit(r'''
1406 class C<E> {
1407 List/*<T>*/ f/*<T>*/(E e) => null;
1408 }
1409 main() {
1410 C<String> cOfString;
1411 }
1412 ''');
1413 expectFunctionType('f', '<T>(E) → List<T>',
1414 elementTypeParams: '[T]',
1415 typeParams: '[E]',
1416 typeArgs: '[E]',
1417 typeFormals: '[T]');
1418 SimpleIdentifier c = findIdentifier('cOfString');
1419 FunctionType ft = (c.staticType as InterfaceType).getMethod('f').type;
1420 expect(ft.toString(), '<T>(String) → List<T>');
1421 ft = ft.instantiate([typeProvider.intType]);
1422 expect(ft.toString(), '(String) → List<int>');
1423 expect('${ft.typeArguments}/${ft.typeParameters}', '[String, int]/[E, T]');
1424 }
1425
1426 void test_genericMethod_explicitTypeParams() {
1427 resolveTestUnit(r'''
1428 class C<E> {
1429 List/*<T>*/ f/*<T>*/(E e) => null;
1430 }
1431 main() {
1432 C<String> cOfString;
1433 var x = cOfString.f/*<int>*/('hi');
1434 }
1435 ''');
1436 MethodInvocation f = findIdentifier('f/*<int>*/').parent;
1437 FunctionType ft = f.staticInvokeType;
1438 expect(ft.toString(), '(String) → List<int>');
1439 expect('${ft.typeArguments}/${ft.typeParameters}', '[String, int]/[E, T]');
1440
1441 SimpleIdentifier x = findIdentifier('x');
1442 expect(x.staticType,
1443 typeProvider.listType.instantiate([typeProvider.intType]));
1444 }
1445
1446 void test_genericMethod_functionExpressionInvocation_explicit() {
1447 resolveTestUnit(r'''
1448 class C<E> {
1449 /*=T*/ f/*<T>*/(/*=T*/ e) => null;
1450 static /*=T*/ g/*<T>*/(/*=T*/ e) => null;
1451 static final h = g;
1452 }
1453
1454 /*=T*/ topF/*<T>*/(/*=T*/ e) => null;
1455 var topG = topF;
1456 void test/*<S>*/(/*=T*/ pf/*<T>*/(/*=T*/ e)) {
1457 var c = new C<int>();
1458 /*=T*/ lf/*<T>*/(/*=T*/ e) => null;
1459
1460 var lambdaCall = (/*<E>*/(/*=E*/ e) => e)/*<int>*/(3);
1461 var methodCall = (c.f)/*<int>*/(3);
1462 var staticCall = (C.g)/*<int>*/(3);
1463 var staticFieldCall = (C.h)/*<int>*/(3);
1464 var topFunCall = (topF)/*<int>*/(3);
1465 var topFieldCall = (topG)/*<int>*/(3);
1466 var localCall = (lf)/*<int>*/(3);
1467 var paramCall = (pf)/*<int>*/(3);
1468 }
1469 ''');
1470 expectIdentifierType('methodCall', "int");
1471 expectIdentifierType('staticCall', "int");
1472 expectIdentifierType('staticFieldCall', "int");
1473 expectIdentifierType('topFunCall', "int");
1474 expectIdentifierType('topFieldCall', "int");
1475 expectIdentifierType('localCall', "int");
1476 expectIdentifierType('paramCall', "int");
1477 expectIdentifierType('lambdaCall', "int");
1478 }
1479
1480 void test_genericMethod_functionExpressionInvocation_inferred() {
1481 resolveTestUnit(r'''
1482 class C<E> {
1483 /*=T*/ f/*<T>*/(/*=T*/ e) => null;
1484 static /*=T*/ g/*<T>*/(/*=T*/ e) => null;
1485 static final h = g;
1486 }
1487
1488 /*=T*/ topF/*<T>*/(/*=T*/ e) => null;
1489 var topG = topF;
1490 void test/*<S>*/(/*=T*/ pf/*<T>*/(/*=T*/ e)) {
1491 var c = new C<int>();
1492 /*=T*/ lf/*<T>*/(/*=T*/ e) => null;
1493
1494 var lambdaCall = (/*<E>*/(/*=E*/ e) => e)(3);
1495 var methodCall = (c.f)(3);
1496 var staticCall = (C.g)(3);
1497 var staticFieldCall = (C.h)(3);
1498 var topFunCall = (topF)(3);
1499 var topFieldCall = (topG)(3);
1500 var localCall = (lf)(3);
1501 var paramCall = (pf)(3);
1502 }
1503 ''');
1504 expectIdentifierType('methodCall', "int");
1505 expectIdentifierType('staticCall', "int");
1506 expectIdentifierType('staticFieldCall', "int");
1507 expectIdentifierType('topFunCall', "int");
1508 expectIdentifierType('topFieldCall', "int");
1509 expectIdentifierType('localCall', "int");
1510 expectIdentifierType('paramCall', "int");
1511 expectIdentifierType('lambdaCall', "int");
1512 }
1513
1514 void test_genericMethod_functionInvocation_explicit() {
1515 resolveTestUnit(r'''
1516 class C<E> {
1517 /*=T*/ f/*<T>*/(/*=T*/ e) => null;
1518 static /*=T*/ g/*<T>*/(/*=T*/ e) => null;
1519 static final h = g;
1520 }
1521
1522 /*=T*/ topF/*<T>*/(/*=T*/ e) => null;
1523 var topG = topF;
1524 void test/*<S>*/(/*=T*/ pf/*<T>*/(/*=T*/ e)) {
1525 var c = new C<int>();
1526 /*=T*/ lf/*<T>*/(/*=T*/ e) => null;
1527 var methodCall = c.f/*<int>*/(3);
1528 var staticCall = C.g/*<int>*/(3);
1529 var staticFieldCall = C.h/*<int>*/(3);
1530 var topFunCall = topF/*<int>*/(3);
1531 var topFieldCall = topG/*<int>*/(3);
1532 var localCall = lf/*<int>*/(3);
1533 var paramCall = pf/*<int>*/(3);
1534 }
1535 ''');
1536 expectIdentifierType('methodCall', "int");
1537 expectIdentifierType('staticCall', "int");
1538 expectIdentifierType('staticFieldCall', "int");
1539 expectIdentifierType('topFunCall', "int");
1540 expectIdentifierType('topFieldCall', "int");
1541 expectIdentifierType('localCall', "int");
1542 expectIdentifierType('paramCall', "int");
1543 }
1544
1545 void test_genericMethod_functionInvocation_inferred() {
1546 resolveTestUnit(r'''
1547 class C<E> {
1548 /*=T*/ f/*<T>*/(/*=T*/ e) => null;
1549 static /*=T*/ g/*<T>*/(/*=T*/ e) => null;
1550 static final h = g;
1551 }
1552
1553 /*=T*/ topF/*<T>*/(/*=T*/ e) => null;
1554 var topG = topF;
1555 void test/*<S>*/(/*=T*/ pf/*<T>*/(/*=T*/ e)) {
1556 var c = new C<int>();
1557 /*=T*/ lf/*<T>*/(/*=T*/ e) => null;
1558 var methodCall = c.f(3);
1559 var staticCall = C.g(3);
1560 var staticFieldCall = C.h(3);
1561 var topFunCall = topF(3);
1562 var topFieldCall = topG(3);
1563 var localCall = lf(3);
1564 var paramCall = pf(3);
1565 }
1566 ''');
1567 expectIdentifierType('methodCall', "int");
1568 expectIdentifierType('staticCall', "int");
1569 expectIdentifierType('staticFieldCall', "int");
1570 expectIdentifierType('topFunCall', "int");
1571 expectIdentifierType('topFieldCall', "int");
1572 expectIdentifierType('localCall', "int");
1573 expectIdentifierType('paramCall', "int");
1574 }
1575
1576 void test_genericMethod_functionTypedParameter() {
1577 resolveTestUnit(r'''
1578 class C<E> {
1579 List/*<T>*/ f/*<T>*/(/*=T*/ f(E e)) => null;
1580 }
1581 main() {
1582 C<String> cOfString;
1583 }
1584 ''');
1585 expectFunctionType('f', '<T>((E) → T) → List<T>',
1586 elementTypeParams: '[T]',
1587 typeParams: '[E]',
1588 typeArgs: '[E]',
1589 typeFormals: '[T]');
1590
1591 SimpleIdentifier c = findIdentifier('cOfString');
1592 FunctionType ft = (c.staticType as InterfaceType).getMethod('f').type;
1593 expect(ft.toString(), '<T>((String) → T) → List<T>');
1594 ft = ft.instantiate([typeProvider.intType]);
1595 expect(ft.toString(), '((String) → int) → List<int>');
1596 }
1597
1598 void test_genericMethod_implicitDynamic() {
1599 // Regression test for:
1600 // https://github.com/dart-lang/sdk/issues/25100#issuecomment-162047588
1601 // These should not cause any hints or warnings.
1602 resolveTestUnit(r'''
1603 class List<E> {
1604 /*=T*/ map/*<T>*/(/*=T*/ f(E e)) => null;
1605 }
1606 void foo() {
1607 List list = null;
1608 list.map((e) => e);
1609 list.map((e) => 3);
1610 }''');
1611 expectIdentifierType('map((e) => e);', '<T>((dynamic) → T) → T', isNull);
1612 expectIdentifierType('map((e) => 3);', '<T>((dynamic) → T) → T', isNull);
1613
1614 MethodInvocation m1 = findIdentifier('map((e) => e);').parent;
1615 expect(m1.staticInvokeType.toString(), '((dynamic) → dynamic) → dynamic');
1616 MethodInvocation m2 = findIdentifier('map((e) => 3);').parent;
1617 expect(m2.staticInvokeType.toString(), '((dynamic) → int) → int');
1618 }
1619
1620 void test_genericMethod_max_doubleDouble() {
1621 String code = r'''
1622 import 'dart:math';
1623 main() {
1624 var foo = max(1.0, 2.0);
1625 }
1626 ''';
1627 resolveTestUnit(code);
1628 expectInitializerType('foo', 'double', isNull);
1629 }
1630
1631 void test_genericMethod_max_doubleDouble_prefixed() {
1632 String code = r'''
1633 import 'dart:math' as math;
1634 main() {
1635 var foo = math.max(1.0, 2.0);
1636 }
1637 ''';
1638 resolveTestUnit(code);
1639 expectInitializerType('foo', 'double', isNull);
1640 }
1641
1642 void test_genericMethod_max_doubleInt() {
1643 String code = r'''
1644 import 'dart:math';
1645 main() {
1646 var foo = max(1.0, 2);
1647 }
1648 ''';
1649 resolveTestUnit(code);
1650 expectInitializerType('foo', 'num', isNull);
1651 }
1652
1653 void test_genericMethod_max_intDouble() {
1654 String code = r'''
1655 import 'dart:math';
1656 main() {
1657 var foo = max(1, 2.0);
1658 }
1659 ''';
1660 resolveTestUnit(code);
1661 expectInitializerType('foo', 'num', isNull);
1662 }
1663
1664 void test_genericMethod_max_intInt() {
1665 String code = r'''
1666 import 'dart:math';
1667 main() {
1668 var foo = max(1, 2);
1669 }
1670 ''';
1671 resolveTestUnit(code);
1672 expectInitializerType('foo', 'int', isNull);
1673 }
1674
1675 void test_genericMethod_nestedBound() {
1676 String code = r'''
1677 class Foo<T extends num> {
1678 void method/*<U extends T>*/(dynamic/*=U*/ u) {
1679 u.abs();
1680 }
1681 }
1682 ''';
1683 // Just validate that there is no warning on the call to `.abs()`.
1684 resolveTestUnit(code);
1685 }
1686
1687 void test_genericMethod_nestedCapture() {
1688 resolveTestUnit(r'''
1689 class C<T> {
1690 /*=T*/ f/*<S>*/(/*=S*/ x) {
1691 new C<S>().f/*<int>*/(3);
1692 new C<S>().f; // tear-off
1693 return null;
1694 }
1695 }
1696 ''');
1697 MethodInvocation f = findIdentifier('f/*<int>*/(3);').parent;
1698 expect(f.staticInvokeType.toString(), '(int) → S');
1699 FunctionType ft = f.staticInvokeType;
1700 expect('${ft.typeArguments}/${ft.typeParameters}', '[S, int]/[T, S]');
1701
1702 expectIdentifierType('f;', '<S₀>(S₀) → S');
1703 }
1704
1705 void test_genericMethod_nestedFunctions() {
1706 resolveTestUnit(r'''
1707 /*=S*/ f/*<S>*/(/*=S*/ x) {
1708 g/*<S>*/(/*=S*/ x) => f;
1709 return null;
1710 }
1711 ''');
1712 expectIdentifierType('f', '<S>(S) → S');
1713 expectIdentifierType('g', '<S>(S) → dynamic');
1714 }
1715
1716 void test_genericMethod_override() {
1717 resolveTestUnit(r'''
1718 class C {
1719 /*=T*/ f/*<T>*/(/*=T*/ x) => null;
1720 }
1721 class D extends C {
1722 /*=T*/ f/*<T>*/(/*=T*/ x) => null; // from D
1723 }
1724 ''');
1725 expectFunctionType('f/*<T>*/(/*=T*/ x) => null; // from D', '<T>(T) → T',
1726 elementTypeParams: '[T]', typeFormals: '[T]');
1727 SimpleIdentifier f =
1728 findIdentifier('f/*<T>*/(/*=T*/ x) => null; // from D');
1729 MethodElementImpl e = f.staticElement;
1730 FunctionType ft = e.type.instantiate([typeProvider.stringType]);
1731 expect(ft.toString(), '(String) → String');
1732 }
1733
1734 void test_genericMethod_override_bounds() {
1735 resolveTestUnit(r'''
1736 class A {}
1737 class B extends A {}
1738 class C {
1739 /*=T*/ f/*<T extends B>*/(/*=T*/ x) => null;
1740 }
1741 class D extends C {
1742 /*=T*/ f/*<T extends A>*/(/*=T*/ x) => null;
1743 }
1744 ''');
1745 }
1746
1747 void test_genericMethod_override_invalidReturnType() {
1748 Source source = addSource(r'''
1749 class C {
1750 Iterable/*<T>*/ f/*<T>*/(/*=T*/ x) => null;
1751 }
1752 class D extends C {
1753 String f/*<S>*/(/*=S*/ x) => null;
1754 }''');
1755 // TODO(jmesserly): we can't use assertErrors because STRONG_MODE_* errors
1756 // from CodeChecker don't have working equality.
1757 List<AnalysisError> errors = analysisContext2.computeErrors(source);
1758
1759 // Sort errors by name.
1760 errors.sort((AnalysisError e1, AnalysisError e2) =>
1761 e1.errorCode.name.compareTo(e2.errorCode.name));
1762
1763 expect(errors.map((e) => e.errorCode.name), [
1764 'INVALID_METHOD_OVERRIDE_RETURN_TYPE',
1765 'STRONG_MODE_INVALID_METHOD_OVERRIDE'
1766 ]);
1767 expect(errors[0].message, contains('Iterable<S>'),
1768 reason: 'errors should be in terms of the type parameters '
1769 'at the error location');
1770 verify([source]);
1771 }
1772
1773 void test_genericMethod_override_invalidTypeParamBounds() {
1774 Source source = addSource(r'''
1775 class A {}
1776 class B extends A {}
1777 class C {
1778 /*=T*/ f/*<T extends A>*/(/*=T*/ x) => null;
1779 }
1780 class D extends C {
1781 /*=T*/ f/*<T extends B>*/(/*=T*/ x) => null;
1782 }''');
1783 // TODO(jmesserly): this is modified code from assertErrors, which we can't
1784 // use directly because STRONG_MODE_* errors don't have working equality.
1785 List<AnalysisError> errors = analysisContext2.computeErrors(source);
1786 List errorNames = errors.map((e) => e.errorCode.name).toList();
1787 expect(errorNames, hasLength(2));
1788 expect(errorNames, contains('STRONG_MODE_INVALID_METHOD_OVERRIDE'));
1789 expect(
1790 errorNames, contains('INVALID_METHOD_OVERRIDE_TYPE_PARAMETER_BOUND'));
1791 verify([source]);
1792 }
1793
1794 void test_genericMethod_override_invalidTypeParamCount() {
1795 Source source = addSource(r'''
1796 class C {
1797 /*=T*/ f/*<T>*/(/*=T*/ x) => null;
1798 }
1799 class D extends C {
1800 /*=S*/ f/*<T, S>*/(/*=T*/ x) => null;
1801 }''');
1802 // TODO(jmesserly): we can't use assertErrors because STRONG_MODE_* errors
1803 // from CodeChecker don't have working equality.
1804 List<AnalysisError> errors = analysisContext2.computeErrors(source);
1805 expect(errors.map((e) => e.errorCode.name), [
1806 'STRONG_MODE_INVALID_METHOD_OVERRIDE',
1807 'INVALID_METHOD_OVERRIDE_TYPE_PARAMETERS'
1808 ]);
1809 verify([source]);
1810 }
1811
1812 void test_genericMethod_propagatedType_promotion() {
1813 // Regression test for:
1814 // https://github.com/dart-lang/sdk/issues/25340
1815
1816 // Note, after https://github.com/dart-lang/sdk/issues/25486 the original
1817 // example won't work, as we now compute a static type and therefore discard
1818 // the propagated type. So a new test was created that doesn't run under
1819 // strong mode.
1820 resolveTestUnit(r'''
1821 abstract class Iter {
1822 List/*<S>*/ map/*<S>*/(/*=S*/ f(x));
1823 }
1824 class C {}
1825 C toSpan(dynamic element) {
1826 if (element is Iter) {
1827 var y = element.map(toSpan);
1828 }
1829 return null;
1830 }''');
1831 expectIdentifierType('y = ', 'List<C>', isNull);
1832 }
1833
1834 void test_genericMethod_tearoff() {
1835 resolveTestUnit(r'''
1836 class C<E> {
1837 /*=T*/ f/*<T>*/(E e) => null;
1838 static /*=T*/ g/*<T>*/(/*=T*/ e) => null;
1839 static final h = g;
1840 }
1841
1842 /*=T*/ topF/*<T>*/(/*=T*/ e) => null;
1843 var topG = topF;
1844 void test/*<S>*/(/*=T*/ pf/*<T>*/(/*=T*/ e)) {
1845 var c = new C<int>();
1846 /*=T*/ lf/*<T>*/(/*=T*/ e) => null;
1847 var methodTearOff = c.f;
1848 var staticTearOff = C.g;
1849 var staticFieldTearOff = C.h;
1850 var topFunTearOff = topF;
1851 var topFieldTearOff = topG;
1852 var localTearOff = lf;
1853 var paramTearOff = pf;
1854 }
1855 ''');
1856 expectIdentifierType('methodTearOff', "<T>(int) → T");
1857 expectIdentifierType('staticTearOff', "<T>(T) → T");
1858 expectIdentifierType('staticFieldTearOff', "<T>(T) → T");
1859 expectIdentifierType('topFunTearOff', "<T>(T) → T");
1860 expectIdentifierType('topFieldTearOff', "<T>(T) → T");
1861 expectIdentifierType('localTearOff', "<T>(T) → T");
1862 expectIdentifierType('paramTearOff', "<T>(T) → T");
1863 }
1864
1865 void test_genericMethod_then() {
1866 String code = r'''
1867 import 'dart:async';
1868 String toString(int x) => x.toString();
1869 main() {
1870 Future<int> bar = null;
1871 var foo = bar.then(toString);
1872 }
1873 ''';
1874 resolveTestUnit(code);
1875 expectInitializerType('foo', 'Future<String>', isNull);
1876 }
1877
1878 void test_genericMethod_then_prefixed() {
1879 String code = r'''
1880 import 'dart:async' as async;
1881 String toString(int x) => x.toString();
1882 main() {
1883 async.Future<int> bar = null;
1884 var foo = bar.then(toString);
1885 }
1886 ''';
1887 resolveTestUnit(code);
1888 expectInitializerType('foo', 'Future<String>', isNull);
1889 }
1890
1891 void test_genericMethod_then_propagatedType() {
1892 // Regression test for https://github.com/dart-lang/sdk/issues/25482.
1893 String code = r'''
1894 import 'dart:async';
1895 void main() {
1896 Future<String> p;
1897 var foo = p.then((r) => new Future<String>.value(3));
1898 }
1899 ''';
1900 // This should produce no hints or warnings.
1901 resolveTestUnit(code);
1902 expectInitializerType('foo', 'Future<String>', isNull);
1903 }
1904
1905 void test_implicitBounds() {
1906 String code = r'''
1907 class A<T> {}
1908
1909 class B<T extends num> {}
1910
1911 class C<S extends int, T extends B<S>, U extends B> {}
1912
1913 void test() {
1914 //
1915 A ai;
1916 B bi;
1917 C ci;
1918 var aa = new A();
1919 var bb = new B();
1920 var cc = new C();
1921 }
1922 ''';
1923 resolveTestUnit(code);
1924 expectIdentifierType('ai', "A<dynamic>");
1925 expectIdentifierType('bi', "B<num>");
1926 expectIdentifierType('ci', "C<int, B<int>, B<num>>");
1927 expectIdentifierType('aa', "A<dynamic>");
1928 expectIdentifierType('bb', "B<num>");
1929 expectIdentifierType('cc', "C<int, B<int>, B<num>>");
1930 }
1931
1932 void test_setterWithDynamicTypeIsError() {
1933 Source source = addSource(r'''
1934 class A {
1935 dynamic set f(String s) => null;
1936 }
1937 dynamic set g(int x) => null;
1938 ''');
1939 computeLibrarySourceErrors(source);
1940 assertErrors(source, [
1941 StaticWarningCode.NON_VOID_RETURN_FOR_SETTER,
1942 StaticWarningCode.NON_VOID_RETURN_FOR_SETTER
1943 ]);
1944 verify([source]);
1945 }
1946
1947 void test_setterWithExplicitVoidType_returningVoid() {
1948 Source source = addSource(r'''
1949 void returnsVoid() {}
1950 class A {
1951 void set f(String s) => returnsVoid();
1952 }
1953 void set g(int x) => returnsVoid();
1954 ''');
1955 computeLibrarySourceErrors(source);
1956 assertNoErrors(source);
1957 verify([source]);
1958 }
1959
1960 void test_setterWithNoVoidType() {
1961 Source source = addSource(r'''
1962 class A {
1963 set f(String s) {
1964 return '42';
1965 }
1966 }
1967 set g(int x) => 42;
1968 ''');
1969 computeLibrarySourceErrors(source);
1970 assertErrors(source, [
1971 StaticTypeWarningCode.RETURN_OF_INVALID_TYPE,
1972 StaticTypeWarningCode.RETURN_OF_INVALID_TYPE
1973 ]);
1974 verify([source]);
1975 }
1976
1977 void test_setterWithNoVoidType_returningVoid() {
1978 Source source = addSource(r'''
1979 void returnsVoid() {}
1980 class A {
1981 set f(String s) => returnsVoid();
1982 }
1983 set g(int x) => returnsVoid();
1984 ''');
1985 computeLibrarySourceErrors(source);
1986 assertNoErrors(source);
1987 verify([source]);
1988 }
1989
1990 void test_setterWithOtherTypeIsError() {
1991 Source source = addSource(r'''
1992 class A {
1993 String set f(String s) => null;
1994 }
1995 Object set g(x) => null;
1996 ''');
1997 computeLibrarySourceErrors(source);
1998 assertErrors(source, [
1999 StaticWarningCode.NON_VOID_RETURN_FOR_SETTER,
2000 StaticWarningCode.NON_VOID_RETURN_FOR_SETTER
2001 ]);
2002 verify([source]);
2003 }
2004
2005 void test_ternaryOperator_null_left() {
2006 String code = r'''
2007 main() {
2008 var foo = (true) ? null : 3;
2009 }
2010 ''';
2011 resolveTestUnit(code);
2012 expectInitializerType('foo', 'int', isNull);
2013 }
2014
2015 void test_ternaryOperator_null_right() {
2016 String code = r'''
2017 main() {
2018 var foo = (true) ? 3 : null;
2019 }
2020 ''';
2021 resolveTestUnit(code);
2022 expectInitializerType('foo', 'int', isNull);
2023 }
2024 }
2025
2026 @reflectiveTest
2027 class StrongModeTypePropagationTest extends ResolverTestCase {
2028 @override
2029 void setUp() {
2030 super.setUp();
2031 AnalysisOptionsImpl options = new AnalysisOptionsImpl();
2032 options.strongMode = true;
2033 resetWithOptions(options);
2034 }
2035
2036 void test_foreachInference_dynamic_disabled() {
2037 String code = r'''
2038 main() {
2039 var list = <int>[];
2040 for (dynamic v in list) {
2041 v; // marker
2042 }
2043 }''';
2044 assertPropagatedIterationType(
2045 code, typeProvider.dynamicType, typeProvider.intType);
2046 assertTypeOfMarkedExpression(
2047 code, typeProvider.dynamicType, typeProvider.intType);
2048 }
2049
2050 void test_foreachInference_reusedVar_disabled() {
2051 String code = r'''
2052 main() {
2053 var list = <int>[];
2054 var v;
2055 for (v in list) {
2056 v; // marker
2057 }
2058 }''';
2059 assertPropagatedIterationType(
2060 code, typeProvider.dynamicType, typeProvider.intType);
2061 assertTypeOfMarkedExpression(
2062 code, typeProvider.dynamicType, typeProvider.intType);
2063 }
2064
2065 void test_foreachInference_var() {
2066 String code = r'''
2067 main() {
2068 var list = <int>[];
2069 for (var v in list) {
2070 v; // marker
2071 }
2072 }''';
2073 assertPropagatedIterationType(code, typeProvider.intType, null);
2074 assertTypeOfMarkedExpression(code, typeProvider.intType, null);
2075 }
2076
2077 void test_foreachInference_var_iterable() {
2078 String code = r'''
2079 main() {
2080 Iterable<int> list = <int>[];
2081 for (var v in list) {
2082 v; // marker
2083 }
2084 }''';
2085 assertPropagatedIterationType(code, typeProvider.intType, null);
2086 assertTypeOfMarkedExpression(code, typeProvider.intType, null);
2087 }
2088
2089 void test_foreachInference_var_stream() {
2090 String code = r'''
2091 import 'dart:async';
2092 main() async {
2093 Stream<int> stream = null;
2094 await for (var v in stream) {
2095 v; // marker
2096 }
2097 }''';
2098 assertPropagatedIterationType(code, typeProvider.intType, null);
2099 assertTypeOfMarkedExpression(code, typeProvider.intType, null);
2100 }
2101
2102 void test_localVariableInference_bottom_disabled() {
2103 String code = r'''
2104 main() {
2105 var v = null;
2106 v; // marker
2107 }''';
2108 assertPropagatedAssignedType(code, typeProvider.dynamicType, null);
2109 assertTypeOfMarkedExpression(code, typeProvider.dynamicType, null);
2110 }
2111
2112 void test_localVariableInference_constant() {
2113 String code = r'''
2114 main() {
2115 var v = 3;
2116 v; // marker
2117 }''';
2118 assertPropagatedAssignedType(code, typeProvider.intType, null);
2119 assertTypeOfMarkedExpression(code, typeProvider.intType, null);
2120 }
2121
2122 void test_localVariableInference_declaredType_disabled() {
2123 String code = r'''
2124 main() {
2125 dynamic v = 3;
2126 v; // marker
2127 }''';
2128 assertPropagatedAssignedType(
2129 code, typeProvider.dynamicType, typeProvider.intType);
2130 assertTypeOfMarkedExpression(
2131 code, typeProvider.dynamicType, typeProvider.intType);
2132 }
2133
2134 void test_localVariableInference_noInitializer_disabled() {
2135 String code = r'''
2136 main() {
2137 var v;
2138 v = 3;
2139 v; // marker
2140 }''';
2141 assertPropagatedAssignedType(
2142 code, typeProvider.dynamicType, typeProvider.intType);
2143 assertTypeOfMarkedExpression(
2144 code, typeProvider.dynamicType, typeProvider.intType);
2145 }
2146
2147 void test_localVariableInference_transitive_field_inferred_lexical() {
2148 String code = r'''
2149 class A {
2150 final x = 3;
2151 f() {
2152 var v = x;
2153 return v; // marker
2154 }
2155 }
2156 main() {
2157 }
2158 ''';
2159 assertPropagatedAssignedType(code, typeProvider.intType, null);
2160 assertTypeOfMarkedExpression(code, typeProvider.intType, null);
2161 }
2162
2163 void test_localVariableInference_transitive_field_inferred_reversed() {
2164 String code = r'''
2165 class A {
2166 f() {
2167 var v = x;
2168 return v; // marker
2169 }
2170 final x = 3;
2171 }
2172 main() {
2173 }
2174 ''';
2175 assertPropagatedAssignedType(code, typeProvider.intType, null);
2176 assertTypeOfMarkedExpression(code, typeProvider.intType, null);
2177 }
2178
2179 void test_localVariableInference_transitive_field_lexical() {
2180 String code = r'''
2181 class A {
2182 int x = 3;
2183 f() {
2184 var v = x;
2185 return v; // marker
2186 }
2187 }
2188 main() {
2189 }
2190 ''';
2191 assertPropagatedAssignedType(code, typeProvider.intType, null);
2192 assertTypeOfMarkedExpression(code, typeProvider.intType, null);
2193 }
2194
2195 void test_localVariableInference_transitive_field_reversed() {
2196 String code = r'''
2197 class A {
2198 f() {
2199 var v = x;
2200 return v; // marker
2201 }
2202 int x = 3;
2203 }
2204 main() {
2205 }
2206 ''';
2207 assertPropagatedAssignedType(code, typeProvider.intType, null);
2208 assertTypeOfMarkedExpression(code, typeProvider.intType, null);
2209 }
2210
2211 void test_localVariableInference_transitive_list_local() {
2212 String code = r'''
2213 main() {
2214 var x = <int>[3];
2215 var v = x[0];
2216 v; // marker
2217 }''';
2218 assertPropagatedAssignedType(code, typeProvider.intType, null);
2219 assertTypeOfMarkedExpression(code, typeProvider.intType, null);
2220 }
2221
2222 void test_localVariableInference_transitive_local() {
2223 String code = r'''
2224 main() {
2225 var x = 3;
2226 var v = x;
2227 v; // marker
2228 }''';
2229 assertPropagatedAssignedType(code, typeProvider.intType, null);
2230 assertTypeOfMarkedExpression(code, typeProvider.intType, null);
2231 }
2232
2233 void test_localVariableInference_transitive_toplevel_inferred_lexical() {
2234 String code = r'''
2235 final x = 3;
2236 main() {
2237 var v = x;
2238 v; // marker
2239 }
2240 ''';
2241 assertPropagatedAssignedType(code, typeProvider.intType, null);
2242 assertTypeOfMarkedExpression(code, typeProvider.intType, null);
2243 }
2244
2245 void test_localVariableInference_transitive_toplevel_inferred_reversed() {
2246 String code = r'''
2247 main() {
2248 var v = x;
2249 v; // marker
2250 }
2251 final x = 3;
2252 ''';
2253 assertPropagatedAssignedType(code, typeProvider.intType, null);
2254 assertTypeOfMarkedExpression(code, typeProvider.intType, null);
2255 }
2256
2257 void test_localVariableInference_transitive_toplevel_lexical() {
2258 String code = r'''
2259 int x = 3;
2260 main() {
2261 var v = x;
2262 v; // marker
2263 }
2264 ''';
2265 assertPropagatedAssignedType(code, typeProvider.intType, null);
2266 assertTypeOfMarkedExpression(code, typeProvider.intType, null);
2267 }
2268
2269 void test_localVariableInference_transitive_toplevel_reversed() {
2270 String code = r'''
2271 main() {
2272 var v = x;
2273 v; // marker
2274 }
2275 int x = 3;
2276 ''';
2277 assertPropagatedAssignedType(code, typeProvider.intType, null);
2278 assertTypeOfMarkedExpression(code, typeProvider.intType, null);
2279 }
2280 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698