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