OLD | NEW |
(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 } |
OLD | NEW |