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.simple_resolver_test; |
| 6 |
| 7 import 'package:analyzer/dart/ast/ast.dart'; |
| 8 import 'package:analyzer/dart/ast/visitor.dart'; |
| 9 import 'package:analyzer/dart/element/element.dart'; |
| 10 import 'package:analyzer/dart/element/type.dart'; |
| 11 import 'package:analyzer/src/generated/engine.dart'; |
| 12 import 'package:analyzer/src/generated/error.dart'; |
| 13 import 'package:analyzer/src/generated/java_engine.dart'; |
| 14 import 'package:analyzer/src/generated/source_io.dart'; |
| 15 import 'package:unittest/unittest.dart'; |
| 16 |
| 17 import '../reflective_tests.dart'; |
| 18 import '../utils.dart'; |
| 19 import 'resolver_test_case.dart'; |
| 20 import 'test_support.dart'; |
| 21 |
| 22 main() { |
| 23 initializeTestEnvironment(); |
| 24 runReflectiveTests(SimpleResolverTest); |
| 25 } |
| 26 |
| 27 @reflectiveTest |
| 28 class SimpleResolverTest extends ResolverTestCase { |
| 29 void fail_getter_and_setter_fromMixins_property_access() { |
| 30 // TODO(paulberry): it appears that auxiliaryElements isn't properly set on |
| 31 // a SimpleIdentifier that's inside a property access. This bug should be |
| 32 // fixed. |
| 33 Source source = addSource(''' |
| 34 class B {} |
| 35 class M1 { |
| 36 get x => null; |
| 37 set x(value) {} |
| 38 } |
| 39 class M2 { |
| 40 get x => null; |
| 41 set x(value) {} |
| 42 } |
| 43 class C extends B with M1, M2 {} |
| 44 void main() { |
| 45 new C().x += 1; |
| 46 } |
| 47 '''); |
| 48 LibraryElement library = resolve2(source); |
| 49 assertNoErrors(source); |
| 50 verify([source]); |
| 51 // Verify that both the getter and setter for "x" in "new C().x" refer to |
| 52 // the accessors defined in M2. |
| 53 FunctionDeclaration main = |
| 54 library.definingCompilationUnit.functions[0].computeNode(); |
| 55 BlockFunctionBody body = main.functionExpression.body; |
| 56 ExpressionStatement stmt = body.block.statements[0]; |
| 57 AssignmentExpression assignment = stmt.expression; |
| 58 PropertyAccess propertyAccess = assignment.leftHandSide; |
| 59 expect( |
| 60 propertyAccess.propertyName.staticElement.enclosingElement.name, 'M2'); |
| 61 expect( |
| 62 propertyAccess |
| 63 .propertyName.auxiliaryElements.staticElement.enclosingElement.name, |
| 64 'M2'); |
| 65 } |
| 66 |
| 67 void fail_staticInvocation() { |
| 68 Source source = addSource(r''' |
| 69 class A { |
| 70 static int get g => (a,b) => 0; |
| 71 } |
| 72 class B { |
| 73 f() { |
| 74 A.g(1,0); |
| 75 } |
| 76 }'''); |
| 77 computeLibrarySourceErrors(source); |
| 78 assertNoErrors(source); |
| 79 verify([source]); |
| 80 } |
| 81 |
| 82 void test_argumentResolution_required_matching() { |
| 83 Source source = addSource(r''' |
| 84 class A { |
| 85 void f() { |
| 86 g(1, 2, 3); |
| 87 } |
| 88 void g(a, b, c) {} |
| 89 }'''); |
| 90 _validateArgumentResolution(source, [0, 1, 2]); |
| 91 } |
| 92 |
| 93 void test_argumentResolution_required_tooFew() { |
| 94 Source source = addSource(r''' |
| 95 class A { |
| 96 void f() { |
| 97 g(1, 2); |
| 98 } |
| 99 void g(a, b, c) {} |
| 100 }'''); |
| 101 _validateArgumentResolution(source, [0, 1]); |
| 102 } |
| 103 |
| 104 void test_argumentResolution_required_tooMany() { |
| 105 Source source = addSource(r''' |
| 106 class A { |
| 107 void f() { |
| 108 g(1, 2, 3); |
| 109 } |
| 110 void g(a, b) {} |
| 111 }'''); |
| 112 _validateArgumentResolution(source, [0, 1, -1]); |
| 113 } |
| 114 |
| 115 void test_argumentResolution_requiredAndNamed_extra() { |
| 116 Source source = addSource(r''' |
| 117 class A { |
| 118 void f() { |
| 119 g(1, 2, c: 3, d: 4); |
| 120 } |
| 121 void g(a, b, {c}) {} |
| 122 }'''); |
| 123 _validateArgumentResolution(source, [0, 1, 2, -1]); |
| 124 } |
| 125 |
| 126 void test_argumentResolution_requiredAndNamed_matching() { |
| 127 Source source = addSource(r''' |
| 128 class A { |
| 129 void f() { |
| 130 g(1, 2, c: 3); |
| 131 } |
| 132 void g(a, b, {c}) {} |
| 133 }'''); |
| 134 _validateArgumentResolution(source, [0, 1, 2]); |
| 135 } |
| 136 |
| 137 void test_argumentResolution_requiredAndNamed_missing() { |
| 138 Source source = addSource(r''' |
| 139 class A { |
| 140 void f() { |
| 141 g(1, 2, d: 3); |
| 142 } |
| 143 void g(a, b, {c, d}) {} |
| 144 }'''); |
| 145 _validateArgumentResolution(source, [0, 1, 3]); |
| 146 } |
| 147 |
| 148 void test_argumentResolution_requiredAndPositional_fewer() { |
| 149 Source source = addSource(r''' |
| 150 class A { |
| 151 void f() { |
| 152 g(1, 2, 3); |
| 153 } |
| 154 void g(a, b, [c, d]) {} |
| 155 }'''); |
| 156 _validateArgumentResolution(source, [0, 1, 2]); |
| 157 } |
| 158 |
| 159 void test_argumentResolution_requiredAndPositional_matching() { |
| 160 Source source = addSource(r''' |
| 161 class A { |
| 162 void f() { |
| 163 g(1, 2, 3, 4); |
| 164 } |
| 165 void g(a, b, [c, d]) {} |
| 166 }'''); |
| 167 _validateArgumentResolution(source, [0, 1, 2, 3]); |
| 168 } |
| 169 |
| 170 void test_argumentResolution_requiredAndPositional_more() { |
| 171 Source source = addSource(r''' |
| 172 class A { |
| 173 void f() { |
| 174 g(1, 2, 3, 4); |
| 175 } |
| 176 void g(a, b, [c]) {} |
| 177 }'''); |
| 178 _validateArgumentResolution(source, [0, 1, 2, -1]); |
| 179 } |
| 180 |
| 181 void test_argumentResolution_setter_propagated() { |
| 182 Source source = addSource(r''' |
| 183 main() { |
| 184 var a = new A(); |
| 185 a.sss = 0; |
| 186 } |
| 187 class A { |
| 188 set sss(x) {} |
| 189 }'''); |
| 190 LibraryElement library = resolve2(source); |
| 191 CompilationUnitElement unit = library.definingCompilationUnit; |
| 192 // find "a.sss = 0" |
| 193 AssignmentExpression assignment; |
| 194 { |
| 195 FunctionElement mainElement = unit.functions[0]; |
| 196 FunctionBody mainBody = mainElement.computeNode().functionExpression.body; |
| 197 Statement statement = (mainBody as BlockFunctionBody).block.statements[1]; |
| 198 ExpressionStatement expressionStatement = |
| 199 statement as ExpressionStatement; |
| 200 assignment = expressionStatement.expression as AssignmentExpression; |
| 201 } |
| 202 // get parameter |
| 203 Expression rhs = assignment.rightHandSide; |
| 204 expect(rhs.staticParameterElement, isNull); |
| 205 ParameterElement parameter = rhs.propagatedParameterElement; |
| 206 expect(parameter, isNotNull); |
| 207 expect(parameter.displayName, "x"); |
| 208 // validate |
| 209 ClassElement classA = unit.types[0]; |
| 210 PropertyAccessorElement setter = classA.accessors[0]; |
| 211 expect(setter.parameters[0], same(parameter)); |
| 212 } |
| 213 |
| 214 void test_argumentResolution_setter_propagated_propertyAccess() { |
| 215 Source source = addSource(r''' |
| 216 main() { |
| 217 var a = new A(); |
| 218 a.b.sss = 0; |
| 219 } |
| 220 class A { |
| 221 B b = new B(); |
| 222 } |
| 223 class B { |
| 224 set sss(x) {} |
| 225 }'''); |
| 226 LibraryElement library = resolve2(source); |
| 227 CompilationUnitElement unit = library.definingCompilationUnit; |
| 228 // find "a.b.sss = 0" |
| 229 AssignmentExpression assignment; |
| 230 { |
| 231 FunctionElement mainElement = unit.functions[0]; |
| 232 FunctionBody mainBody = mainElement.computeNode().functionExpression.body; |
| 233 Statement statement = (mainBody as BlockFunctionBody).block.statements[1]; |
| 234 ExpressionStatement expressionStatement = |
| 235 statement as ExpressionStatement; |
| 236 assignment = expressionStatement.expression as AssignmentExpression; |
| 237 } |
| 238 // get parameter |
| 239 Expression rhs = assignment.rightHandSide; |
| 240 expect(rhs.staticParameterElement, isNull); |
| 241 ParameterElement parameter = rhs.propagatedParameterElement; |
| 242 expect(parameter, isNotNull); |
| 243 expect(parameter.displayName, "x"); |
| 244 // validate |
| 245 ClassElement classB = unit.types[1]; |
| 246 PropertyAccessorElement setter = classB.accessors[0]; |
| 247 expect(setter.parameters[0], same(parameter)); |
| 248 } |
| 249 |
| 250 void test_argumentResolution_setter_static() { |
| 251 Source source = addSource(r''' |
| 252 main() { |
| 253 A a = new A(); |
| 254 a.sss = 0; |
| 255 } |
| 256 class A { |
| 257 set sss(x) {} |
| 258 }'''); |
| 259 LibraryElement library = resolve2(source); |
| 260 CompilationUnitElement unit = library.definingCompilationUnit; |
| 261 // find "a.sss = 0" |
| 262 AssignmentExpression assignment; |
| 263 { |
| 264 FunctionElement mainElement = unit.functions[0]; |
| 265 FunctionBody mainBody = mainElement.computeNode().functionExpression.body; |
| 266 Statement statement = (mainBody as BlockFunctionBody).block.statements[1]; |
| 267 ExpressionStatement expressionStatement = |
| 268 statement as ExpressionStatement; |
| 269 assignment = expressionStatement.expression as AssignmentExpression; |
| 270 } |
| 271 // get parameter |
| 272 Expression rhs = assignment.rightHandSide; |
| 273 ParameterElement parameter = rhs.staticParameterElement; |
| 274 expect(parameter, isNotNull); |
| 275 expect(parameter.displayName, "x"); |
| 276 // validate |
| 277 ClassElement classA = unit.types[0]; |
| 278 PropertyAccessorElement setter = classA.accessors[0]; |
| 279 expect(setter.parameters[0], same(parameter)); |
| 280 } |
| 281 |
| 282 void test_argumentResolution_setter_static_propertyAccess() { |
| 283 Source source = addSource(r''' |
| 284 main() { |
| 285 A a = new A(); |
| 286 a.b.sss = 0; |
| 287 } |
| 288 class A { |
| 289 B b = new B(); |
| 290 } |
| 291 class B { |
| 292 set sss(x) {} |
| 293 }'''); |
| 294 LibraryElement library = resolve2(source); |
| 295 CompilationUnitElement unit = library.definingCompilationUnit; |
| 296 // find "a.b.sss = 0" |
| 297 AssignmentExpression assignment; |
| 298 { |
| 299 FunctionElement mainElement = unit.functions[0]; |
| 300 FunctionBody mainBody = mainElement.computeNode().functionExpression.body; |
| 301 Statement statement = (mainBody as BlockFunctionBody).block.statements[1]; |
| 302 ExpressionStatement expressionStatement = |
| 303 statement as ExpressionStatement; |
| 304 assignment = expressionStatement.expression as AssignmentExpression; |
| 305 } |
| 306 // get parameter |
| 307 Expression rhs = assignment.rightHandSide; |
| 308 ParameterElement parameter = rhs.staticParameterElement; |
| 309 expect(parameter, isNotNull); |
| 310 expect(parameter.displayName, "x"); |
| 311 // validate |
| 312 ClassElement classB = unit.types[1]; |
| 313 PropertyAccessorElement setter = classB.accessors[0]; |
| 314 expect(setter.parameters[0], same(parameter)); |
| 315 } |
| 316 |
| 317 void test_breakTarget_labeled() { |
| 318 // Verify that the target of the label is correctly found and is recorded |
| 319 // as the unlabeled portion of the statement. |
| 320 String text = r''' |
| 321 void f() { |
| 322 loop1: while (true) { |
| 323 loop2: for (int i = 0; i < 10; i++) { |
| 324 break loop1; |
| 325 break loop2; |
| 326 } |
| 327 } |
| 328 } |
| 329 '''; |
| 330 CompilationUnit unit = resolveSource(text); |
| 331 WhileStatement whileStatement = EngineTestCase.findNode( |
| 332 unit, text, 'while (true)', (n) => n is WhileStatement); |
| 333 ForStatement forStatement = |
| 334 EngineTestCase.findNode(unit, text, 'for', (n) => n is ForStatement); |
| 335 BreakStatement break1 = EngineTestCase.findNode( |
| 336 unit, text, 'break loop1', (n) => n is BreakStatement); |
| 337 BreakStatement break2 = EngineTestCase.findNode( |
| 338 unit, text, 'break loop2', (n) => n is BreakStatement); |
| 339 expect(break1.target, same(whileStatement)); |
| 340 expect(break2.target, same(forStatement)); |
| 341 } |
| 342 |
| 343 void test_breakTarget_unlabeledBreakFromDo() { |
| 344 String text = r''' |
| 345 void f() { |
| 346 do { |
| 347 break; |
| 348 } while (true); |
| 349 } |
| 350 '''; |
| 351 CompilationUnit unit = resolveSource(text); |
| 352 DoStatement doStatement = |
| 353 EngineTestCase.findNode(unit, text, 'do', (n) => n is DoStatement); |
| 354 BreakStatement breakStatement = EngineTestCase.findNode( |
| 355 unit, text, 'break', (n) => n is BreakStatement); |
| 356 expect(breakStatement.target, same(doStatement)); |
| 357 } |
| 358 |
| 359 void test_breakTarget_unlabeledBreakFromFor() { |
| 360 String text = r''' |
| 361 void f() { |
| 362 for (int i = 0; i < 10; i++) { |
| 363 break; |
| 364 } |
| 365 } |
| 366 '''; |
| 367 CompilationUnit unit = resolveSource(text); |
| 368 ForStatement forStatement = |
| 369 EngineTestCase.findNode(unit, text, 'for', (n) => n is ForStatement); |
| 370 BreakStatement breakStatement = EngineTestCase.findNode( |
| 371 unit, text, 'break', (n) => n is BreakStatement); |
| 372 expect(breakStatement.target, same(forStatement)); |
| 373 } |
| 374 |
| 375 void test_breakTarget_unlabeledBreakFromForEach() { |
| 376 String text = r''' |
| 377 void f() { |
| 378 for (x in []) { |
| 379 break; |
| 380 } |
| 381 } |
| 382 '''; |
| 383 CompilationUnit unit = resolveSource(text); |
| 384 ForEachStatement forStatement = EngineTestCase.findNode( |
| 385 unit, text, 'for', (n) => n is ForEachStatement); |
| 386 BreakStatement breakStatement = EngineTestCase.findNode( |
| 387 unit, text, 'break', (n) => n is BreakStatement); |
| 388 expect(breakStatement.target, same(forStatement)); |
| 389 } |
| 390 |
| 391 void test_breakTarget_unlabeledBreakFromSwitch() { |
| 392 String text = r''' |
| 393 void f() { |
| 394 while (true) { |
| 395 switch (0) { |
| 396 case 0: |
| 397 break; |
| 398 } |
| 399 } |
| 400 } |
| 401 '''; |
| 402 CompilationUnit unit = resolveSource(text); |
| 403 SwitchStatement switchStatement = EngineTestCase.findNode( |
| 404 unit, text, 'switch', (n) => n is SwitchStatement); |
| 405 BreakStatement breakStatement = EngineTestCase.findNode( |
| 406 unit, text, 'break', (n) => n is BreakStatement); |
| 407 expect(breakStatement.target, same(switchStatement)); |
| 408 } |
| 409 |
| 410 void test_breakTarget_unlabeledBreakFromWhile() { |
| 411 String text = r''' |
| 412 void f() { |
| 413 while (true) { |
| 414 break; |
| 415 } |
| 416 } |
| 417 '''; |
| 418 CompilationUnit unit = resolveSource(text); |
| 419 WhileStatement whileStatement = EngineTestCase.findNode( |
| 420 unit, text, 'while', (n) => n is WhileStatement); |
| 421 BreakStatement breakStatement = EngineTestCase.findNode( |
| 422 unit, text, 'break', (n) => n is BreakStatement); |
| 423 expect(breakStatement.target, same(whileStatement)); |
| 424 } |
| 425 |
| 426 void test_breakTarget_unlabeledBreakToOuterFunction() { |
| 427 // Verify that unlabeled break statements can't resolve to loops in an |
| 428 // outer function. |
| 429 String text = r''' |
| 430 void f() { |
| 431 while (true) { |
| 432 void g() { |
| 433 break; |
| 434 } |
| 435 } |
| 436 } |
| 437 '''; |
| 438 CompilationUnit unit = resolveSource(text); |
| 439 BreakStatement breakStatement = EngineTestCase.findNode( |
| 440 unit, text, 'break', (n) => n is BreakStatement); |
| 441 expect(breakStatement.target, isNull); |
| 442 } |
| 443 |
| 444 void test_class_definesCall() { |
| 445 Source source = addSource(r''' |
| 446 class A { |
| 447 int call(int x) { return x; } |
| 448 } |
| 449 int f(A a) { |
| 450 return a(0); |
| 451 }'''); |
| 452 computeLibrarySourceErrors(source); |
| 453 assertNoErrors(source); |
| 454 verify([source]); |
| 455 } |
| 456 |
| 457 void test_class_extends_implements() { |
| 458 Source source = addSource(r''' |
| 459 class A extends B implements C {} |
| 460 class B {} |
| 461 class C {}'''); |
| 462 computeLibrarySourceErrors(source); |
| 463 assertNoErrors(source); |
| 464 verify([source]); |
| 465 } |
| 466 |
| 467 void test_commentReference_class() { |
| 468 Source source = addSource(r''' |
| 469 f() {} |
| 470 /** [A] [new A] [A.n] [new A.n] [m] [f] */ |
| 471 class A { |
| 472 A() {} |
| 473 A.n() {} |
| 474 m() {} |
| 475 }'''); |
| 476 computeLibrarySourceErrors(source); |
| 477 assertNoErrors(source); |
| 478 verify([source]); |
| 479 } |
| 480 |
| 481 void test_commentReference_parameter() { |
| 482 Source source = addSource(r''' |
| 483 class A { |
| 484 A() {} |
| 485 A.n() {} |
| 486 /** [e] [f] */ |
| 487 m(e, f()) {} |
| 488 }'''); |
| 489 computeLibrarySourceErrors(source); |
| 490 assertNoErrors(source); |
| 491 verify([source]); |
| 492 } |
| 493 |
| 494 void test_commentReference_singleLine() { |
| 495 Source source = addSource(r''' |
| 496 /// [A] |
| 497 class A {}'''); |
| 498 computeLibrarySourceErrors(source); |
| 499 assertNoErrors(source); |
| 500 verify([source]); |
| 501 } |
| 502 |
| 503 void test_continueTarget_labeled() { |
| 504 // Verify that the target of the label is correctly found and is recorded |
| 505 // as the unlabeled portion of the statement. |
| 506 String text = r''' |
| 507 void f() { |
| 508 loop1: while (true) { |
| 509 loop2: for (int i = 0; i < 10; i++) { |
| 510 continue loop1; |
| 511 continue loop2; |
| 512 } |
| 513 } |
| 514 } |
| 515 '''; |
| 516 CompilationUnit unit = resolveSource(text); |
| 517 WhileStatement whileStatement = EngineTestCase.findNode( |
| 518 unit, text, 'while (true)', (n) => n is WhileStatement); |
| 519 ForStatement forStatement = |
| 520 EngineTestCase.findNode(unit, text, 'for', (n) => n is ForStatement); |
| 521 ContinueStatement continue1 = EngineTestCase.findNode( |
| 522 unit, text, 'continue loop1', (n) => n is ContinueStatement); |
| 523 ContinueStatement continue2 = EngineTestCase.findNode( |
| 524 unit, text, 'continue loop2', (n) => n is ContinueStatement); |
| 525 expect(continue1.target, same(whileStatement)); |
| 526 expect(continue2.target, same(forStatement)); |
| 527 } |
| 528 |
| 529 void test_continueTarget_unlabeledContinueFromDo() { |
| 530 String text = r''' |
| 531 void f() { |
| 532 do { |
| 533 continue; |
| 534 } while (true); |
| 535 } |
| 536 '''; |
| 537 CompilationUnit unit = resolveSource(text); |
| 538 DoStatement doStatement = |
| 539 EngineTestCase.findNode(unit, text, 'do', (n) => n is DoStatement); |
| 540 ContinueStatement continueStatement = EngineTestCase.findNode( |
| 541 unit, text, 'continue', (n) => n is ContinueStatement); |
| 542 expect(continueStatement.target, same(doStatement)); |
| 543 } |
| 544 |
| 545 void test_continueTarget_unlabeledContinueFromFor() { |
| 546 String text = r''' |
| 547 void f() { |
| 548 for (int i = 0; i < 10; i++) { |
| 549 continue; |
| 550 } |
| 551 } |
| 552 '''; |
| 553 CompilationUnit unit = resolveSource(text); |
| 554 ForStatement forStatement = |
| 555 EngineTestCase.findNode(unit, text, 'for', (n) => n is ForStatement); |
| 556 ContinueStatement continueStatement = EngineTestCase.findNode( |
| 557 unit, text, 'continue', (n) => n is ContinueStatement); |
| 558 expect(continueStatement.target, same(forStatement)); |
| 559 } |
| 560 |
| 561 void test_continueTarget_unlabeledContinueFromForEach() { |
| 562 String text = r''' |
| 563 void f() { |
| 564 for (x in []) { |
| 565 continue; |
| 566 } |
| 567 } |
| 568 '''; |
| 569 CompilationUnit unit = resolveSource(text); |
| 570 ForEachStatement forStatement = EngineTestCase.findNode( |
| 571 unit, text, 'for', (n) => n is ForEachStatement); |
| 572 ContinueStatement continueStatement = EngineTestCase.findNode( |
| 573 unit, text, 'continue', (n) => n is ContinueStatement); |
| 574 expect(continueStatement.target, same(forStatement)); |
| 575 } |
| 576 |
| 577 void test_continueTarget_unlabeledContinueFromWhile() { |
| 578 String text = r''' |
| 579 void f() { |
| 580 while (true) { |
| 581 continue; |
| 582 } |
| 583 } |
| 584 '''; |
| 585 CompilationUnit unit = resolveSource(text); |
| 586 WhileStatement whileStatement = EngineTestCase.findNode( |
| 587 unit, text, 'while', (n) => n is WhileStatement); |
| 588 ContinueStatement continueStatement = EngineTestCase.findNode( |
| 589 unit, text, 'continue', (n) => n is ContinueStatement); |
| 590 expect(continueStatement.target, same(whileStatement)); |
| 591 } |
| 592 |
| 593 void test_continueTarget_unlabeledContinueSkipsSwitch() { |
| 594 String text = r''' |
| 595 void f() { |
| 596 while (true) { |
| 597 switch (0) { |
| 598 case 0: |
| 599 continue; |
| 600 } |
| 601 } |
| 602 } |
| 603 '''; |
| 604 CompilationUnit unit = resolveSource(text); |
| 605 WhileStatement whileStatement = EngineTestCase.findNode( |
| 606 unit, text, 'while', (n) => n is WhileStatement); |
| 607 ContinueStatement continueStatement = EngineTestCase.findNode( |
| 608 unit, text, 'continue', (n) => n is ContinueStatement); |
| 609 expect(continueStatement.target, same(whileStatement)); |
| 610 } |
| 611 |
| 612 void test_continueTarget_unlabeledContinueToOuterFunction() { |
| 613 // Verify that unlabeled continue statements can't resolve to loops in an |
| 614 // outer function. |
| 615 String text = r''' |
| 616 void f() { |
| 617 while (true) { |
| 618 void g() { |
| 619 continue; |
| 620 } |
| 621 } |
| 622 } |
| 623 '''; |
| 624 CompilationUnit unit = resolveSource(text); |
| 625 ContinueStatement continueStatement = EngineTestCase.findNode( |
| 626 unit, text, 'continue', (n) => n is ContinueStatement); |
| 627 expect(continueStatement.target, isNull); |
| 628 } |
| 629 |
| 630 void test_empty() { |
| 631 Source source = addSource(""); |
| 632 computeLibrarySourceErrors(source); |
| 633 assertNoErrors(source); |
| 634 verify([source]); |
| 635 } |
| 636 |
| 637 void test_entryPoint_exported() { |
| 638 addNamedSource( |
| 639 "/two.dart", |
| 640 r''' |
| 641 library two; |
| 642 main() {}'''); |
| 643 Source source = addNamedSource( |
| 644 "/one.dart", |
| 645 r''' |
| 646 library one; |
| 647 export 'two.dart';'''); |
| 648 LibraryElement library = resolve2(source); |
| 649 expect(library, isNotNull); |
| 650 FunctionElement main = library.entryPoint; |
| 651 expect(main, isNotNull); |
| 652 expect(main.library, isNot(same(library))); |
| 653 assertNoErrors(source); |
| 654 verify([source]); |
| 655 } |
| 656 |
| 657 void test_entryPoint_local() { |
| 658 Source source = addNamedSource( |
| 659 "/one.dart", |
| 660 r''' |
| 661 library one; |
| 662 main() {}'''); |
| 663 LibraryElement library = resolve2(source); |
| 664 expect(library, isNotNull); |
| 665 FunctionElement main = library.entryPoint; |
| 666 expect(main, isNotNull); |
| 667 expect(main.library, same(library)); |
| 668 assertNoErrors(source); |
| 669 verify([source]); |
| 670 } |
| 671 |
| 672 void test_entryPoint_none() { |
| 673 Source source = addNamedSource("/one.dart", "library one;"); |
| 674 LibraryElement library = resolve2(source); |
| 675 expect(library, isNotNull); |
| 676 expect(library.entryPoint, isNull); |
| 677 assertNoErrors(source); |
| 678 verify([source]); |
| 679 } |
| 680 |
| 681 void test_enum_externalLibrary() { |
| 682 addNamedSource( |
| 683 "/my_lib.dart", |
| 684 r''' |
| 685 library my_lib; |
| 686 enum EEE {A, B, C}'''); |
| 687 Source source = addSource(r''' |
| 688 import 'my_lib.dart'; |
| 689 main() { |
| 690 EEE e = null; |
| 691 }'''); |
| 692 computeLibrarySourceErrors(source); |
| 693 assertNoErrors(source); |
| 694 verify([source]); |
| 695 } |
| 696 |
| 697 void test_extractedMethodAsConstant() { |
| 698 Source source = addSource(r''' |
| 699 abstract class Comparable<T> { |
| 700 int compareTo(T other); |
| 701 static int compare(Comparable a, Comparable b) => a.compareTo(b); |
| 702 } |
| 703 class A { |
| 704 void sort([compare = Comparable.compare]) {} |
| 705 }'''); |
| 706 computeLibrarySourceErrors(source); |
| 707 assertNoErrors(source); |
| 708 verify([source]); |
| 709 } |
| 710 |
| 711 void test_fieldFormalParameter() { |
| 712 Source source = addSource(r''' |
| 713 class A { |
| 714 int x; |
| 715 A(this.x) {} |
| 716 }'''); |
| 717 computeLibrarySourceErrors(source); |
| 718 assertNoErrors(source); |
| 719 verify([source]); |
| 720 } |
| 721 |
| 722 void test_forEachLoops_nonConflicting() { |
| 723 Source source = addSource(r''' |
| 724 f() { |
| 725 List list = [1,2,3]; |
| 726 for (int x in list) {} |
| 727 for (int x in list) {} |
| 728 }'''); |
| 729 computeLibrarySourceErrors(source); |
| 730 assertNoErrors(source); |
| 731 verify([source]); |
| 732 } |
| 733 |
| 734 void test_forLoops_nonConflicting() { |
| 735 Source source = addSource(r''' |
| 736 f() { |
| 737 for (int i = 0; i < 3; i++) { |
| 738 } |
| 739 for (int i = 0; i < 3; i++) { |
| 740 } |
| 741 }'''); |
| 742 computeLibrarySourceErrors(source); |
| 743 assertNoErrors(source); |
| 744 verify([source]); |
| 745 } |
| 746 |
| 747 void test_functionTypeAlias() { |
| 748 Source source = addSource(r''' |
| 749 typedef bool P(e); |
| 750 class A { |
| 751 P p; |
| 752 m(e) { |
| 753 if (p(e)) {} |
| 754 } |
| 755 }'''); |
| 756 computeLibrarySourceErrors(source); |
| 757 assertNoErrors(source); |
| 758 verify([source]); |
| 759 } |
| 760 |
| 761 void test_getter_and_setter_fromMixins_bare_identifier() { |
| 762 Source source = addSource(''' |
| 763 class B {} |
| 764 class M1 { |
| 765 get x => null; |
| 766 set x(value) {} |
| 767 } |
| 768 class M2 { |
| 769 get x => null; |
| 770 set x(value) {} |
| 771 } |
| 772 class C extends B with M1, M2 { |
| 773 void f() { |
| 774 x += 1; |
| 775 } |
| 776 } |
| 777 '''); |
| 778 LibraryElement library = resolve2(source); |
| 779 assertNoErrors(source); |
| 780 verify([source]); |
| 781 // Verify that both the getter and setter for "x" in C.f() refer to the |
| 782 // accessors defined in M2. |
| 783 ClassElement classC = library.definingCompilationUnit.types[3]; |
| 784 MethodDeclaration f = classC.getMethod('f').computeNode(); |
| 785 BlockFunctionBody body = f.body; |
| 786 ExpressionStatement stmt = body.block.statements[0]; |
| 787 AssignmentExpression assignment = stmt.expression; |
| 788 SimpleIdentifier leftHandSide = assignment.leftHandSide; |
| 789 expect(leftHandSide.staticElement.enclosingElement.name, 'M2'); |
| 790 expect(leftHandSide.auxiliaryElements.staticElement.enclosingElement.name, |
| 791 'M2'); |
| 792 } |
| 793 |
| 794 void test_getter_fromMixins_bare_identifier() { |
| 795 Source source = addSource(''' |
| 796 class B {} |
| 797 class M1 { |
| 798 get x => null; |
| 799 } |
| 800 class M2 { |
| 801 get x => null; |
| 802 } |
| 803 class C extends B with M1, M2 { |
| 804 f() { |
| 805 return x; |
| 806 } |
| 807 } |
| 808 '''); |
| 809 LibraryElement library = resolve2(source); |
| 810 assertNoErrors(source); |
| 811 verify([source]); |
| 812 // Verify that the getter for "x" in C.f() refers to the getter defined in |
| 813 // M2. |
| 814 ClassElement classC = library.definingCompilationUnit.types[3]; |
| 815 MethodDeclaration f = classC.getMethod('f').computeNode(); |
| 816 BlockFunctionBody body = f.body; |
| 817 ReturnStatement stmt = body.block.statements[0]; |
| 818 SimpleIdentifier x = stmt.expression; |
| 819 expect(x.staticElement.enclosingElement.name, 'M2'); |
| 820 } |
| 821 |
| 822 void test_getter_fromMixins_property_access() { |
| 823 Source source = addSource(''' |
| 824 class B {} |
| 825 class M1 { |
| 826 get x => null; |
| 827 } |
| 828 class M2 { |
| 829 get x => null; |
| 830 } |
| 831 class C extends B with M1, M2 {} |
| 832 void main() { |
| 833 var y = new C().x; |
| 834 } |
| 835 '''); |
| 836 LibraryElement library = resolve2(source); |
| 837 assertNoErrors(source); |
| 838 verify([source]); |
| 839 // Verify that the getter for "x" in "new C().x" refers to the getter |
| 840 // defined in M2. |
| 841 FunctionDeclaration main = |
| 842 library.definingCompilationUnit.functions[0].computeNode(); |
| 843 BlockFunctionBody body = main.functionExpression.body; |
| 844 VariableDeclarationStatement stmt = body.block.statements[0]; |
| 845 PropertyAccess propertyAccess = stmt.variables.variables[0].initializer; |
| 846 expect( |
| 847 propertyAccess.propertyName.staticElement.enclosingElement.name, 'M2'); |
| 848 } |
| 849 |
| 850 void test_getterAndSetterWithDifferentTypes() { |
| 851 Source source = addSource(r''' |
| 852 class A { |
| 853 int get f => 0; |
| 854 void set f(String s) {} |
| 855 } |
| 856 g (A a) { |
| 857 a.f = a.f.toString(); |
| 858 }'''); |
| 859 computeLibrarySourceErrors(source); |
| 860 assertErrors( |
| 861 source, [StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES]); |
| 862 verify([source]); |
| 863 } |
| 864 |
| 865 void test_hasReferenceToSuper() { |
| 866 Source source = addSource(r''' |
| 867 class A {} |
| 868 class B {toString() => super.toString();}'''); |
| 869 LibraryElement library = resolve2(source); |
| 870 expect(library, isNotNull); |
| 871 CompilationUnitElement unit = library.definingCompilationUnit; |
| 872 expect(unit, isNotNull); |
| 873 List<ClassElement> classes = unit.types; |
| 874 expect(classes, hasLength(2)); |
| 875 expect(classes[0].hasReferenceToSuper, isFalse); |
| 876 expect(classes[1].hasReferenceToSuper, isTrue); |
| 877 assertNoErrors(source); |
| 878 verify([source]); |
| 879 } |
| 880 |
| 881 void test_import_hide() { |
| 882 addNamedSource( |
| 883 "/lib1.dart", |
| 884 r''' |
| 885 library lib1; |
| 886 set foo(value) {} |
| 887 class A {}'''); |
| 888 addNamedSource( |
| 889 "/lib2.dart", |
| 890 r''' |
| 891 library lib2; |
| 892 set foo(value) {}'''); |
| 893 Source source = addNamedSource( |
| 894 "/lib3.dart", |
| 895 r''' |
| 896 import 'lib1.dart' hide foo; |
| 897 import 'lib2.dart'; |
| 898 |
| 899 main() { |
| 900 foo = 0; |
| 901 } |
| 902 A a;'''); |
| 903 computeLibrarySourceErrors(source); |
| 904 assertNoErrors(source); |
| 905 verify([source]); |
| 906 } |
| 907 |
| 908 void test_import_prefix() { |
| 909 addNamedSource( |
| 910 "/two.dart", |
| 911 r''' |
| 912 library two; |
| 913 f(int x) { |
| 914 return x * x; |
| 915 }'''); |
| 916 Source source = addNamedSource( |
| 917 "/one.dart", |
| 918 r''' |
| 919 library one; |
| 920 import 'two.dart' as _two; |
| 921 main() { |
| 922 _two.f(0); |
| 923 }'''); |
| 924 computeLibrarySourceErrors(source); |
| 925 assertNoErrors(source); |
| 926 verify([source]); |
| 927 } |
| 928 |
| 929 void test_import_spaceInUri() { |
| 930 addNamedSource( |
| 931 "/sub folder/lib.dart", |
| 932 r''' |
| 933 library lib; |
| 934 foo() {}'''); |
| 935 Source source = addNamedSource( |
| 936 "/app.dart", |
| 937 r''' |
| 938 import 'sub folder/lib.dart'; |
| 939 |
| 940 main() { |
| 941 foo(); |
| 942 }'''); |
| 943 computeLibrarySourceErrors(source); |
| 944 assertNoErrors(source); |
| 945 verify([source]); |
| 946 } |
| 947 |
| 948 void test_indexExpression_typeParameters() { |
| 949 Source source = addSource(r''' |
| 950 f() { |
| 951 List<int> a; |
| 952 a[0]; |
| 953 List<List<int>> b; |
| 954 b[0][0]; |
| 955 List<List<List<int>>> c; |
| 956 c[0][0][0]; |
| 957 }'''); |
| 958 computeLibrarySourceErrors(source); |
| 959 assertNoErrors(source); |
| 960 verify([source]); |
| 961 } |
| 962 |
| 963 void test_indexExpression_typeParameters_invalidAssignmentWarning() { |
| 964 Source source = addSource(r''' |
| 965 f() { |
| 966 List<List<int>> b; |
| 967 b[0][0] = 'hi'; |
| 968 }'''); |
| 969 computeLibrarySourceErrors(source); |
| 970 assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]); |
| 971 verify([source]); |
| 972 } |
| 973 |
| 974 void test_indirectOperatorThroughCall() { |
| 975 Source source = addSource(r''' |
| 976 class A { |
| 977 B call() { return new B(); } |
| 978 } |
| 979 |
| 980 class B { |
| 981 int operator [](int i) { return i; } |
| 982 } |
| 983 |
| 984 A f = new A(); |
| 985 |
| 986 g(int x) {} |
| 987 |
| 988 main() { |
| 989 g(f()[0]); |
| 990 }'''); |
| 991 computeLibrarySourceErrors(source); |
| 992 assertNoErrors(source); |
| 993 verify([source]); |
| 994 } |
| 995 |
| 996 void test_invoke_dynamicThroughGetter() { |
| 997 Source source = addSource(r''' |
| 998 class A { |
| 999 List get X => [() => 0]; |
| 1000 m(A a) { |
| 1001 X.last; |
| 1002 } |
| 1003 }'''); |
| 1004 computeLibrarySourceErrors(source); |
| 1005 assertNoErrors(source); |
| 1006 verify([source]); |
| 1007 } |
| 1008 |
| 1009 void test_isValidMixin_badSuperclass() { |
| 1010 Source source = addSource(r''' |
| 1011 class A extends B {} |
| 1012 class B {} |
| 1013 class C = Object with A;'''); |
| 1014 LibraryElement library = resolve2(source); |
| 1015 expect(library, isNotNull); |
| 1016 CompilationUnitElement unit = library.definingCompilationUnit; |
| 1017 expect(unit, isNotNull); |
| 1018 ClassElement a = unit.getType('A'); |
| 1019 expect(a.isValidMixin, isFalse); |
| 1020 assertErrors(source, [CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT]); |
| 1021 verify([source]); |
| 1022 } |
| 1023 |
| 1024 void test_isValidMixin_badSuperclass_withSuperMixins() { |
| 1025 resetWithOptions(new AnalysisOptionsImpl()..enableSuperMixins = true); |
| 1026 Source source = addSource(r''' |
| 1027 class A extends B {} |
| 1028 class B {} |
| 1029 class C = Object with A;'''); |
| 1030 LibraryElement library = resolve2(source); |
| 1031 expect(library, isNotNull); |
| 1032 CompilationUnitElement unit = library.definingCompilationUnit; |
| 1033 expect(unit, isNotNull); |
| 1034 ClassElement a = unit.getType('A'); |
| 1035 expect(a.isValidMixin, isTrue); |
| 1036 assertNoErrors(source); |
| 1037 verify([source]); |
| 1038 } |
| 1039 |
| 1040 void test_isValidMixin_constructor() { |
| 1041 Source source = addSource(r''' |
| 1042 class A { |
| 1043 A() {} |
| 1044 } |
| 1045 class C = Object with A;'''); |
| 1046 LibraryElement library = resolve2(source); |
| 1047 expect(library, isNotNull); |
| 1048 CompilationUnitElement unit = library.definingCompilationUnit; |
| 1049 expect(unit, isNotNull); |
| 1050 ClassElement a = unit.getType('A'); |
| 1051 expect(a.isValidMixin, isFalse); |
| 1052 assertErrors(source, [CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR]); |
| 1053 verify([source]); |
| 1054 } |
| 1055 |
| 1056 void test_isValidMixin_constructor_withSuperMixins() { |
| 1057 resetWithOptions(new AnalysisOptionsImpl()..enableSuperMixins = true); |
| 1058 Source source = addSource(r''' |
| 1059 class A { |
| 1060 A() {} |
| 1061 } |
| 1062 class C = Object with A;'''); |
| 1063 LibraryElement library = resolve2(source); |
| 1064 expect(library, isNotNull); |
| 1065 CompilationUnitElement unit = library.definingCompilationUnit; |
| 1066 expect(unit, isNotNull); |
| 1067 ClassElement a = unit.getType('A'); |
| 1068 expect(a.isValidMixin, isFalse); |
| 1069 assertErrors(source, [CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR]); |
| 1070 verify([source]); |
| 1071 } |
| 1072 |
| 1073 void test_isValidMixin_factoryConstructor() { |
| 1074 Source source = addSource(r''' |
| 1075 class A { |
| 1076 factory A() => null; |
| 1077 } |
| 1078 class C = Object with A;'''); |
| 1079 LibraryElement library = resolve2(source); |
| 1080 expect(library, isNotNull); |
| 1081 CompilationUnitElement unit = library.definingCompilationUnit; |
| 1082 expect(unit, isNotNull); |
| 1083 ClassElement a = unit.getType('A'); |
| 1084 expect(a.isValidMixin, isTrue); |
| 1085 assertNoErrors(source); |
| 1086 verify([source]); |
| 1087 } |
| 1088 |
| 1089 void test_isValidMixin_factoryConstructor_withSuperMixins() { |
| 1090 resetWithOptions(new AnalysisOptionsImpl()..enableSuperMixins = true); |
| 1091 Source source = addSource(r''' |
| 1092 class A { |
| 1093 factory A() => null; |
| 1094 } |
| 1095 class C = Object with A;'''); |
| 1096 LibraryElement library = resolve2(source); |
| 1097 expect(library, isNotNull); |
| 1098 CompilationUnitElement unit = library.definingCompilationUnit; |
| 1099 expect(unit, isNotNull); |
| 1100 ClassElement a = unit.getType('A'); |
| 1101 expect(a.isValidMixin, isTrue); |
| 1102 assertNoErrors(source); |
| 1103 verify([source]); |
| 1104 } |
| 1105 |
| 1106 void test_isValidMixin_super() { |
| 1107 Source source = addSource(r''' |
| 1108 class A { |
| 1109 toString() { |
| 1110 return super.toString(); |
| 1111 } |
| 1112 } |
| 1113 class C = Object with A;'''); |
| 1114 LibraryElement library = resolve2(source); |
| 1115 expect(library, isNotNull); |
| 1116 CompilationUnitElement unit = library.definingCompilationUnit; |
| 1117 expect(unit, isNotNull); |
| 1118 ClassElement a = unit.getType('A'); |
| 1119 expect(a.isValidMixin, isFalse); |
| 1120 assertErrors(source, [CompileTimeErrorCode.MIXIN_REFERENCES_SUPER]); |
| 1121 verify([source]); |
| 1122 } |
| 1123 |
| 1124 void test_isValidMixin_super_withSuperMixins() { |
| 1125 resetWithOptions(new AnalysisOptionsImpl()..enableSuperMixins = true); |
| 1126 Source source = addSource(r''' |
| 1127 class A { |
| 1128 toString() { |
| 1129 return super.toString(); |
| 1130 } |
| 1131 } |
| 1132 class C = Object with A;'''); |
| 1133 LibraryElement library = resolve2(source); |
| 1134 expect(library, isNotNull); |
| 1135 CompilationUnitElement unit = library.definingCompilationUnit; |
| 1136 expect(unit, isNotNull); |
| 1137 ClassElement a = unit.getType('A'); |
| 1138 expect(a.isValidMixin, isTrue); |
| 1139 assertNoErrors(source); |
| 1140 verify([source]); |
| 1141 } |
| 1142 |
| 1143 void test_isValidMixin_valid() { |
| 1144 Source source = addSource(''' |
| 1145 class A {} |
| 1146 class C = Object with A;'''); |
| 1147 LibraryElement library = resolve2(source); |
| 1148 expect(library, isNotNull); |
| 1149 CompilationUnitElement unit = library.definingCompilationUnit; |
| 1150 expect(unit, isNotNull); |
| 1151 ClassElement a = unit.getType('A'); |
| 1152 expect(a.isValidMixin, isTrue); |
| 1153 assertNoErrors(source); |
| 1154 verify([source]); |
| 1155 } |
| 1156 |
| 1157 void test_isValidMixin_valid_withSuperMixins() { |
| 1158 resetWithOptions(new AnalysisOptionsImpl()..enableSuperMixins = true); |
| 1159 Source source = addSource(''' |
| 1160 class A {} |
| 1161 class C = Object with A;'''); |
| 1162 LibraryElement library = resolve2(source); |
| 1163 expect(library, isNotNull); |
| 1164 CompilationUnitElement unit = library.definingCompilationUnit; |
| 1165 expect(unit, isNotNull); |
| 1166 ClassElement a = unit.getType('A'); |
| 1167 expect(a.isValidMixin, isTrue); |
| 1168 assertNoErrors(source); |
| 1169 verify([source]); |
| 1170 } |
| 1171 |
| 1172 void test_labels_switch() { |
| 1173 Source source = addSource(r''' |
| 1174 void doSwitch(int target) { |
| 1175 switch (target) { |
| 1176 l0: case 0: |
| 1177 continue l1; |
| 1178 l1: case 1: |
| 1179 continue l0; |
| 1180 default: |
| 1181 continue l1; |
| 1182 } |
| 1183 }'''); |
| 1184 LibraryElement library = resolve2(source); |
| 1185 expect(library, isNotNull); |
| 1186 assertNoErrors(source); |
| 1187 verify([source]); |
| 1188 } |
| 1189 |
| 1190 void test_localVariable_types_invoked() { |
| 1191 Source source = addSource(r''' |
| 1192 const A = null; |
| 1193 main() { |
| 1194 var myVar = (int p) => 'foo'; |
| 1195 myVar(42); |
| 1196 }'''); |
| 1197 LibraryElement library = resolve2(source); |
| 1198 expect(library, isNotNull); |
| 1199 CompilationUnit unit = |
| 1200 analysisContext.resolveCompilationUnit(source, library); |
| 1201 expect(unit, isNotNull); |
| 1202 List<bool> found = [false]; |
| 1203 List<CaughtException> thrownException = new List<CaughtException>(1); |
| 1204 unit.accept(new _SimpleResolverTest_localVariable_types_invoked( |
| 1205 this, found, thrownException)); |
| 1206 if (thrownException[0] != null) { |
| 1207 throw new AnalysisException( |
| 1208 "Exception", new CaughtException(thrownException[0], null)); |
| 1209 } |
| 1210 expect(found[0], isTrue); |
| 1211 } |
| 1212 |
| 1213 void test_metadata_class() { |
| 1214 Source source = addSource(r''' |
| 1215 const A = null; |
| 1216 @A class C<A> {}'''); |
| 1217 LibraryElement library = resolve2(source); |
| 1218 expect(library, isNotNull); |
| 1219 CompilationUnitElement unitElement = library.definingCompilationUnit; |
| 1220 expect(unitElement, isNotNull); |
| 1221 List<ClassElement> classes = unitElement.types; |
| 1222 expect(classes, hasLength(1)); |
| 1223 List<ElementAnnotation> annotations = classes[0].metadata; |
| 1224 expect(annotations, hasLength(1)); |
| 1225 assertNoErrors(source); |
| 1226 verify([source]); |
| 1227 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 1228 NodeList<CompilationUnitMember> declarations = unit.declarations; |
| 1229 expect(declarations, hasLength(2)); |
| 1230 Element expectedElement = (declarations[0] as TopLevelVariableDeclaration) |
| 1231 .variables |
| 1232 .variables[0] |
| 1233 .name |
| 1234 .staticElement; |
| 1235 EngineTestCase.assertInstanceOf((obj) => obj is PropertyInducingElement, |
| 1236 PropertyInducingElement, expectedElement); |
| 1237 expectedElement = (expectedElement as PropertyInducingElement).getter; |
| 1238 Element actualElement = |
| 1239 (declarations[1] as ClassDeclaration).metadata[0].name.staticElement; |
| 1240 expect(actualElement, same(expectedElement)); |
| 1241 } |
| 1242 |
| 1243 void test_metadata_field() { |
| 1244 Source source = addSource(r''' |
| 1245 const A = null; |
| 1246 class C { |
| 1247 @A int f; |
| 1248 }'''); |
| 1249 LibraryElement library = resolve2(source); |
| 1250 expect(library, isNotNull); |
| 1251 CompilationUnitElement unit = library.definingCompilationUnit; |
| 1252 expect(unit, isNotNull); |
| 1253 List<ClassElement> classes = unit.types; |
| 1254 expect(classes, hasLength(1)); |
| 1255 FieldElement field = classes[0].fields[0]; |
| 1256 List<ElementAnnotation> annotations = field.metadata; |
| 1257 expect(annotations, hasLength(1)); |
| 1258 assertNoErrors(source); |
| 1259 verify([source]); |
| 1260 } |
| 1261 |
| 1262 void test_metadata_fieldFormalParameter() { |
| 1263 Source source = addSource(r''' |
| 1264 const A = null; |
| 1265 class C { |
| 1266 int f; |
| 1267 C(@A this.f); |
| 1268 }'''); |
| 1269 LibraryElement library = resolve2(source); |
| 1270 expect(library, isNotNull); |
| 1271 CompilationUnitElement unit = library.definingCompilationUnit; |
| 1272 expect(unit, isNotNull); |
| 1273 List<ClassElement> classes = unit.types; |
| 1274 expect(classes, hasLength(1)); |
| 1275 List<ConstructorElement> constructors = classes[0].constructors; |
| 1276 expect(constructors, hasLength(1)); |
| 1277 List<ParameterElement> parameters = constructors[0].parameters; |
| 1278 expect(parameters, hasLength(1)); |
| 1279 List<ElementAnnotation> annotations = parameters[0].metadata; |
| 1280 expect(annotations, hasLength(1)); |
| 1281 assertNoErrors(source); |
| 1282 verify([source]); |
| 1283 } |
| 1284 |
| 1285 void test_metadata_function() { |
| 1286 Source source = addSource(r''' |
| 1287 const A = null; |
| 1288 @A f() {}'''); |
| 1289 LibraryElement library = resolve2(source); |
| 1290 expect(library, isNotNull); |
| 1291 CompilationUnitElement unit = library.definingCompilationUnit; |
| 1292 expect(unit, isNotNull); |
| 1293 List<FunctionElement> functions = unit.functions; |
| 1294 expect(functions, hasLength(1)); |
| 1295 List<ElementAnnotation> annotations = functions[0].metadata; |
| 1296 expect(annotations, hasLength(1)); |
| 1297 assertNoErrors(source); |
| 1298 verify([source]); |
| 1299 } |
| 1300 |
| 1301 void test_metadata_functionTypedParameter() { |
| 1302 Source source = addSource(r''' |
| 1303 const A = null; |
| 1304 f(@A int p(int x)) {}'''); |
| 1305 LibraryElement library = resolve2(source); |
| 1306 expect(library, isNotNull); |
| 1307 CompilationUnitElement unit = library.definingCompilationUnit; |
| 1308 expect(unit, isNotNull); |
| 1309 List<FunctionElement> functions = unit.functions; |
| 1310 expect(functions, hasLength(1)); |
| 1311 List<ParameterElement> parameters = functions[0].parameters; |
| 1312 expect(parameters, hasLength(1)); |
| 1313 List<ElementAnnotation> annotations1 = parameters[0].metadata; |
| 1314 expect(annotations1, hasLength(1)); |
| 1315 assertNoErrors(source); |
| 1316 verify([source]); |
| 1317 } |
| 1318 |
| 1319 void test_metadata_libraryDirective() { |
| 1320 Source source = addSource(r''' |
| 1321 @A library lib; |
| 1322 const A = null;'''); |
| 1323 LibraryElement library = resolve2(source); |
| 1324 expect(library, isNotNull); |
| 1325 List<ElementAnnotation> annotations = library.metadata; |
| 1326 expect(annotations, hasLength(1)); |
| 1327 assertNoErrors(source); |
| 1328 verify([source]); |
| 1329 } |
| 1330 |
| 1331 void test_metadata_method() { |
| 1332 Source source = addSource(r''' |
| 1333 const A = null; |
| 1334 class C { |
| 1335 @A void m() {} |
| 1336 }'''); |
| 1337 LibraryElement library = resolve2(source); |
| 1338 expect(library, isNotNull); |
| 1339 CompilationUnitElement unit = library.definingCompilationUnit; |
| 1340 expect(unit, isNotNull); |
| 1341 List<ClassElement> classes = unit.types; |
| 1342 expect(classes, hasLength(1)); |
| 1343 MethodElement method = classes[0].methods[0]; |
| 1344 List<ElementAnnotation> annotations = method.metadata; |
| 1345 expect(annotations, hasLength(1)); |
| 1346 assertNoErrors(source); |
| 1347 verify([source]); |
| 1348 } |
| 1349 |
| 1350 void test_metadata_namedParameter() { |
| 1351 Source source = addSource(r''' |
| 1352 const A = null; |
| 1353 f({@A int p : 0}) {}'''); |
| 1354 LibraryElement library = resolve2(source); |
| 1355 expect(library, isNotNull); |
| 1356 CompilationUnitElement unit = library.definingCompilationUnit; |
| 1357 expect(unit, isNotNull); |
| 1358 List<FunctionElement> functions = unit.functions; |
| 1359 expect(functions, hasLength(1)); |
| 1360 List<ParameterElement> parameters = functions[0].parameters; |
| 1361 expect(parameters, hasLength(1)); |
| 1362 List<ElementAnnotation> annotations1 = parameters[0].metadata; |
| 1363 expect(annotations1, hasLength(1)); |
| 1364 assertNoErrors(source); |
| 1365 verify([source]); |
| 1366 } |
| 1367 |
| 1368 void test_metadata_positionalParameter() { |
| 1369 Source source = addSource(r''' |
| 1370 const A = null; |
| 1371 f([@A int p = 0]) {}'''); |
| 1372 LibraryElement library = resolve2(source); |
| 1373 expect(library, isNotNull); |
| 1374 CompilationUnitElement unit = library.definingCompilationUnit; |
| 1375 expect(unit, isNotNull); |
| 1376 List<FunctionElement> functions = unit.functions; |
| 1377 expect(functions, hasLength(1)); |
| 1378 List<ParameterElement> parameters = functions[0].parameters; |
| 1379 expect(parameters, hasLength(1)); |
| 1380 List<ElementAnnotation> annotations1 = parameters[0].metadata; |
| 1381 expect(annotations1, hasLength(1)); |
| 1382 assertNoErrors(source); |
| 1383 verify([source]); |
| 1384 } |
| 1385 |
| 1386 void test_metadata_simpleParameter() { |
| 1387 Source source = addSource(r''' |
| 1388 const A = null; |
| 1389 f(@A p1, @A int p2) {}'''); |
| 1390 LibraryElement library = resolve2(source); |
| 1391 expect(library, isNotNull); |
| 1392 CompilationUnitElement unit = library.definingCompilationUnit; |
| 1393 expect(unit, isNotNull); |
| 1394 List<FunctionElement> functions = unit.functions; |
| 1395 expect(functions, hasLength(1)); |
| 1396 List<ParameterElement> parameters = functions[0].parameters; |
| 1397 expect(parameters, hasLength(2)); |
| 1398 List<ElementAnnotation> annotations1 = parameters[0].metadata; |
| 1399 expect(annotations1, hasLength(1)); |
| 1400 List<ElementAnnotation> annotations2 = parameters[1].metadata; |
| 1401 expect(annotations2, hasLength(1)); |
| 1402 assertNoErrors(source); |
| 1403 verify([source]); |
| 1404 } |
| 1405 |
| 1406 void test_metadata_typedef() { |
| 1407 Source source = addSource(r''' |
| 1408 const A = null; |
| 1409 @A typedef F<A>();'''); |
| 1410 LibraryElement library = resolve2(source); |
| 1411 expect(library, isNotNull); |
| 1412 CompilationUnitElement unitElement = library.definingCompilationUnit; |
| 1413 expect(unitElement, isNotNull); |
| 1414 List<FunctionTypeAliasElement> aliases = unitElement.functionTypeAliases; |
| 1415 expect(aliases, hasLength(1)); |
| 1416 List<ElementAnnotation> annotations = aliases[0].metadata; |
| 1417 expect(annotations, hasLength(1)); |
| 1418 assertNoErrors(source); |
| 1419 verify([source]); |
| 1420 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 1421 NodeList<CompilationUnitMember> declarations = unit.declarations; |
| 1422 expect(declarations, hasLength(2)); |
| 1423 Element expectedElement = (declarations[0] as TopLevelVariableDeclaration) |
| 1424 .variables |
| 1425 .variables[0] |
| 1426 .name |
| 1427 .staticElement; |
| 1428 EngineTestCase.assertInstanceOf((obj) => obj is PropertyInducingElement, |
| 1429 PropertyInducingElement, expectedElement); |
| 1430 expectedElement = (expectedElement as PropertyInducingElement).getter; |
| 1431 Element actualElement = |
| 1432 (declarations[1] as FunctionTypeAlias).metadata[0].name.staticElement; |
| 1433 expect(actualElement, same(expectedElement)); |
| 1434 } |
| 1435 |
| 1436 void test_method_fromMixin() { |
| 1437 Source source = addSource(r''' |
| 1438 class B { |
| 1439 bar() => 1; |
| 1440 } |
| 1441 class A { |
| 1442 foo() => 2; |
| 1443 } |
| 1444 |
| 1445 class C extends B with A { |
| 1446 bar() => super.bar(); |
| 1447 foo() => super.foo(); |
| 1448 }'''); |
| 1449 computeLibrarySourceErrors(source); |
| 1450 assertNoErrors(source); |
| 1451 verify([source]); |
| 1452 } |
| 1453 |
| 1454 void test_method_fromMixins() { |
| 1455 Source source = addSource(''' |
| 1456 class B {} |
| 1457 class M1 { |
| 1458 void f() {} |
| 1459 } |
| 1460 class M2 { |
| 1461 void f() {} |
| 1462 } |
| 1463 class C extends B with M1, M2 {} |
| 1464 void main() { |
| 1465 new C().f(); |
| 1466 } |
| 1467 '''); |
| 1468 LibraryElement library = resolve2(source); |
| 1469 assertNoErrors(source); |
| 1470 verify([source]); |
| 1471 // Verify that the "f" in "new C().f()" refers to the "f" defined in M2. |
| 1472 FunctionDeclaration main = |
| 1473 library.definingCompilationUnit.functions[0].computeNode(); |
| 1474 BlockFunctionBody body = main.functionExpression.body; |
| 1475 ExpressionStatement stmt = body.block.statements[0]; |
| 1476 MethodInvocation expr = stmt.expression; |
| 1477 expect(expr.methodName.staticElement.enclosingElement.name, 'M2'); |
| 1478 } |
| 1479 |
| 1480 void test_method_fromMixins_bare_identifier() { |
| 1481 Source source = addSource(''' |
| 1482 class B {} |
| 1483 class M1 { |
| 1484 void f() {} |
| 1485 } |
| 1486 class M2 { |
| 1487 void f() {} |
| 1488 } |
| 1489 class C extends B with M1, M2 { |
| 1490 void g() { |
| 1491 f(); |
| 1492 } |
| 1493 } |
| 1494 '''); |
| 1495 LibraryElement library = resolve2(source); |
| 1496 assertNoErrors(source); |
| 1497 verify([source]); |
| 1498 // Verify that the call to f() in C.g() refers to the method defined in M2. |
| 1499 ClassElement classC = library.definingCompilationUnit.types[3]; |
| 1500 MethodDeclaration g = classC.getMethod('g').computeNode(); |
| 1501 BlockFunctionBody body = g.body; |
| 1502 ExpressionStatement stmt = body.block.statements[0]; |
| 1503 MethodInvocation invocation = stmt.expression; |
| 1504 SimpleIdentifier methodName = invocation.methodName; |
| 1505 expect(methodName.staticElement.enclosingElement.name, 'M2'); |
| 1506 } |
| 1507 |
| 1508 void test_method_fromMixins_invked_from_outside_class() { |
| 1509 Source source = addSource(''' |
| 1510 class B {} |
| 1511 class M1 { |
| 1512 void f() {} |
| 1513 } |
| 1514 class M2 { |
| 1515 void f() {} |
| 1516 } |
| 1517 class C extends B with M1, M2 {} |
| 1518 void main() { |
| 1519 new C().f(); |
| 1520 } |
| 1521 '''); |
| 1522 LibraryElement library = resolve2(source); |
| 1523 assertNoErrors(source); |
| 1524 verify([source]); |
| 1525 // Verify that the call to f() in "new C().f()" refers to the method |
| 1526 // defined in M2. |
| 1527 FunctionDeclaration main = |
| 1528 library.definingCompilationUnit.functions[0].computeNode(); |
| 1529 BlockFunctionBody body = main.functionExpression.body; |
| 1530 ExpressionStatement stmt = body.block.statements[0]; |
| 1531 MethodInvocation invocation = stmt.expression; |
| 1532 expect(invocation.methodName.staticElement.enclosingElement.name, 'M2'); |
| 1533 } |
| 1534 |
| 1535 void test_method_fromSuperclassMixin() { |
| 1536 Source source = addSource(r''' |
| 1537 class A { |
| 1538 void m1() {} |
| 1539 } |
| 1540 class B extends Object with A { |
| 1541 } |
| 1542 class C extends B { |
| 1543 } |
| 1544 f(C c) { |
| 1545 c.m1(); |
| 1546 }'''); |
| 1547 computeLibrarySourceErrors(source); |
| 1548 assertNoErrors(source); |
| 1549 verify([source]); |
| 1550 } |
| 1551 |
| 1552 void test_methodCascades() { |
| 1553 Source source = addSource(r''' |
| 1554 class A { |
| 1555 void m1() {} |
| 1556 void m2() {} |
| 1557 void m() { |
| 1558 A a = new A(); |
| 1559 a..m1() |
| 1560 ..m2(); |
| 1561 } |
| 1562 }'''); |
| 1563 computeLibrarySourceErrors(source); |
| 1564 assertNoErrors(source); |
| 1565 verify([source]); |
| 1566 } |
| 1567 |
| 1568 void test_methodCascades_withSetter() { |
| 1569 Source source = addSource(r''' |
| 1570 class A { |
| 1571 String name; |
| 1572 void m1() {} |
| 1573 void m2() {} |
| 1574 void m() { |
| 1575 A a = new A(); |
| 1576 a..m1() |
| 1577 ..name = 'name' |
| 1578 ..m2(); |
| 1579 } |
| 1580 }'''); |
| 1581 computeLibrarySourceErrors(source); |
| 1582 // failing with error code: INVOCATION_OF_NON_FUNCTION |
| 1583 assertNoErrors(source); |
| 1584 verify([source]); |
| 1585 } |
| 1586 |
| 1587 void test_resolveAgainstNull() { |
| 1588 Source source = addSource(r''' |
| 1589 f(var p) { |
| 1590 return null == p; |
| 1591 }'''); |
| 1592 computeLibrarySourceErrors(source); |
| 1593 assertNoErrors(source); |
| 1594 } |
| 1595 |
| 1596 void test_setter_fromMixins_bare_identifier() { |
| 1597 Source source = addSource(''' |
| 1598 class B {} |
| 1599 class M1 { |
| 1600 set x(value) {} |
| 1601 } |
| 1602 class M2 { |
| 1603 set x(value) {} |
| 1604 } |
| 1605 class C extends B with M1, M2 { |
| 1606 void f() { |
| 1607 x = 1; |
| 1608 } |
| 1609 } |
| 1610 '''); |
| 1611 LibraryElement library = resolve2(source); |
| 1612 assertNoErrors(source); |
| 1613 verify([source]); |
| 1614 // Verify that the setter for "x" in C.f() refers to the setter defined in |
| 1615 // M2. |
| 1616 ClassElement classC = library.definingCompilationUnit.types[3]; |
| 1617 MethodDeclaration f = classC.getMethod('f').computeNode(); |
| 1618 BlockFunctionBody body = f.body; |
| 1619 ExpressionStatement stmt = body.block.statements[0]; |
| 1620 AssignmentExpression assignment = stmt.expression; |
| 1621 SimpleIdentifier leftHandSide = assignment.leftHandSide; |
| 1622 expect(leftHandSide.staticElement.enclosingElement.name, 'M2'); |
| 1623 } |
| 1624 |
| 1625 void test_setter_fromMixins_property_access() { |
| 1626 Source source = addSource(''' |
| 1627 class B {} |
| 1628 class M1 { |
| 1629 set x(value) {} |
| 1630 } |
| 1631 class M2 { |
| 1632 set x(value) {} |
| 1633 } |
| 1634 class C extends B with M1, M2 {} |
| 1635 void main() { |
| 1636 new C().x = 1; |
| 1637 } |
| 1638 '''); |
| 1639 LibraryElement library = resolve2(source); |
| 1640 assertNoErrors(source); |
| 1641 verify([source]); |
| 1642 // Verify that the setter for "x" in "new C().x" refers to the setter |
| 1643 // defined in M2. |
| 1644 FunctionDeclaration main = |
| 1645 library.definingCompilationUnit.functions[0].computeNode(); |
| 1646 BlockFunctionBody body = main.functionExpression.body; |
| 1647 ExpressionStatement stmt = body.block.statements[0]; |
| 1648 AssignmentExpression assignment = stmt.expression; |
| 1649 PropertyAccess propertyAccess = assignment.leftHandSide; |
| 1650 expect( |
| 1651 propertyAccess.propertyName.staticElement.enclosingElement.name, 'M2'); |
| 1652 } |
| 1653 |
| 1654 void test_setter_inherited() { |
| 1655 Source source = addSource(r''' |
| 1656 class A { |
| 1657 int get x => 0; |
| 1658 set x(int p) {} |
| 1659 } |
| 1660 class B extends A { |
| 1661 int get x => super.x == null ? 0 : super.x; |
| 1662 int f() => x = 1; |
| 1663 }'''); |
| 1664 computeLibrarySourceErrors(source); |
| 1665 assertNoErrors(source); |
| 1666 verify([source]); |
| 1667 } |
| 1668 |
| 1669 void test_setter_static() { |
| 1670 Source source = addSource(r''' |
| 1671 set s(x) { |
| 1672 } |
| 1673 |
| 1674 main() { |
| 1675 s = 123; |
| 1676 }'''); |
| 1677 computeLibrarySourceErrors(source); |
| 1678 assertNoErrors(source); |
| 1679 verify([source]); |
| 1680 } |
| 1681 |
| 1682 /** |
| 1683 * Resolve the given source and verify that the arguments in a specific method
invocation were |
| 1684 * correctly resolved. |
| 1685 * |
| 1686 * The source is expected to be source for a compilation unit, the first decla
ration is expected |
| 1687 * to be a class, the first member of which is expected to be a method with a
block body, and the |
| 1688 * first statement in the body is expected to be an expression statement whose
expression is a |
| 1689 * method invocation. It is the arguments to that method invocation that are t
ested. The method |
| 1690 * invocation can contain errors. |
| 1691 * |
| 1692 * The arguments were resolved correctly if the number of expressions in the l
ist matches the |
| 1693 * length of the array of indices and if, for each index in the array of indic
es, the parameter to |
| 1694 * which the argument expression was resolved is the parameter in the invoked
method's list of |
| 1695 * parameters at that index. Arguments that should not be resolved to a parame
ter because of an |
| 1696 * error can be denoted by including a negative index in the array of indices. |
| 1697 * |
| 1698 * @param source the source to be resolved |
| 1699 * @param indices the array of indices used to associate arguments with parame
ters |
| 1700 * @throws Exception if the source could not be resolved or if the structure o
f the source is not |
| 1701 * valid |
| 1702 */ |
| 1703 void _validateArgumentResolution(Source source, List<int> indices) { |
| 1704 LibraryElement library = resolve2(source); |
| 1705 expect(library, isNotNull); |
| 1706 ClassElement classElement = library.definingCompilationUnit.types[0]; |
| 1707 List<ParameterElement> parameters = classElement.methods[1].parameters; |
| 1708 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 1709 expect(unit, isNotNull); |
| 1710 ClassDeclaration classDeclaration = |
| 1711 unit.declarations[0] as ClassDeclaration; |
| 1712 MethodDeclaration methodDeclaration = |
| 1713 classDeclaration.members[0] as MethodDeclaration; |
| 1714 Block block = (methodDeclaration.body as BlockFunctionBody).block; |
| 1715 ExpressionStatement statement = block.statements[0] as ExpressionStatement; |
| 1716 MethodInvocation invocation = statement.expression as MethodInvocation; |
| 1717 NodeList<Expression> arguments = invocation.argumentList.arguments; |
| 1718 int argumentCount = arguments.length; |
| 1719 expect(argumentCount, indices.length); |
| 1720 for (int i = 0; i < argumentCount; i++) { |
| 1721 Expression argument = arguments[i]; |
| 1722 ParameterElement element = argument.staticParameterElement; |
| 1723 int index = indices[i]; |
| 1724 if (index < 0) { |
| 1725 expect(element, isNull); |
| 1726 } else { |
| 1727 expect(element, same(parameters[index])); |
| 1728 } |
| 1729 } |
| 1730 } |
| 1731 } |
| 1732 |
| 1733 class _SimpleResolverTest_localVariable_types_invoked |
| 1734 extends RecursiveAstVisitor<Object> { |
| 1735 final SimpleResolverTest test; |
| 1736 |
| 1737 List<bool> found; |
| 1738 |
| 1739 List<CaughtException> thrownException; |
| 1740 |
| 1741 _SimpleResolverTest_localVariable_types_invoked( |
| 1742 this.test, this.found, this.thrownException) |
| 1743 : super(); |
| 1744 |
| 1745 @override |
| 1746 Object visitSimpleIdentifier(SimpleIdentifier node) { |
| 1747 if (node.name == "myVar" && node.parent is MethodInvocation) { |
| 1748 try { |
| 1749 found[0] = true; |
| 1750 // check static type |
| 1751 DartType staticType = node.staticType; |
| 1752 expect(staticType, same(test.typeProvider.dynamicType)); |
| 1753 // check propagated type |
| 1754 FunctionType propagatedType = node.propagatedType as FunctionType; |
| 1755 expect(propagatedType.returnType, test.typeProvider.stringType); |
| 1756 } on AnalysisException catch (e, stackTrace) { |
| 1757 thrownException[0] = new CaughtException(e, stackTrace); |
| 1758 } |
| 1759 } |
| 1760 return null; |
| 1761 } |
| 1762 } |
OLD | NEW |