| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2014, 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 import 'package:analyzer/analyzer.dart'; | |
| 6 import 'package:analyzer/file_system/file_system.dart'; | |
| 7 import 'package:analyzer/file_system/memory_file_system.dart'; | |
| 8 import 'package:analyzer/src/generated/element.dart'; | |
| 9 import 'package:analyzer/src/generated/engine.dart'; | |
| 10 import 'package:analyzer/src/generated/sdk.dart'; | |
| 11 import 'package:analyzer/src/generated/source.dart'; | |
| 12 import 'package:analyzer/src/generated/source_io.dart'; | |
| 13 import 'package:analyzer2dart/src/identifier_semantics.dart'; | |
| 14 import 'package:unittest/unittest.dart'; | |
| 15 | |
| 16 import 'mock_sdk.dart'; | |
| 17 | |
| 18 main() { | |
| 19 test('Call function defined at top level', () { | |
| 20 Helper helper = new Helper(''' | |
| 21 g() {} | |
| 22 | |
| 23 f() { | |
| 24 g(); | |
| 25 } | |
| 26 '''); | |
| 27 helper.checkStaticMethod('g()', null, 'g', true, isInvoke: true); | |
| 28 }); | |
| 29 | |
| 30 test('Call function defined at top level via prefix', () { | |
| 31 Helper helper = new Helper(''' | |
| 32 import 'lib.dart' as l; | |
| 33 | |
| 34 f() { | |
| 35 l.g(); | |
| 36 } | |
| 37 '''); | |
| 38 helper.addFile('/lib.dart', ''' | |
| 39 library lib; | |
| 40 | |
| 41 g() {} | |
| 42 '''); | |
| 43 helper.checkStaticMethod('l.g()', null, 'g', true, isInvoke: true); | |
| 44 }); | |
| 45 | |
| 46 test('Call method defined statically in class from inside class', () { | |
| 47 Helper helper = new Helper(''' | |
| 48 class A { | |
| 49 static g() {} | |
| 50 | |
| 51 f() { | |
| 52 g(); | |
| 53 } | |
| 54 } | |
| 55 '''); | |
| 56 helper.checkStaticMethod('g()', 'A', 'g', true, isInvoke: true); | |
| 57 }); | |
| 58 | |
| 59 test('Call method defined statically in class from outside class', () { | |
| 60 Helper helper = new Helper(''' | |
| 61 class A { | |
| 62 static g() {} | |
| 63 } | |
| 64 f() { | |
| 65 A.g(); | |
| 66 } | |
| 67 '''); | |
| 68 helper.checkStaticMethod('A.g()', 'A', 'g', true, isInvoke: true); | |
| 69 }); | |
| 70 | |
| 71 test( | |
| 72 'Call method defined statically in class from outside class via prefix', | |
| 73 () { | |
| 74 Helper helper = new Helper(''' | |
| 75 import 'lib.dart' as l; | |
| 76 | |
| 77 f() { | |
| 78 l.A.g(); | |
| 79 } | |
| 80 '''); | |
| 81 helper.addFile('/lib.dart', ''' | |
| 82 library lib; | |
| 83 | |
| 84 class A { | |
| 85 static g() {} | |
| 86 } | |
| 87 '''); | |
| 88 helper.checkStaticMethod('l.A.g()', 'A', 'g', true, isInvoke: true); | |
| 89 }); | |
| 90 | |
| 91 test('Call method defined dynamically in class from inside class', () { | |
| 92 Helper helper = new Helper(''' | |
| 93 class A { | |
| 94 g() {} | |
| 95 | |
| 96 f() { | |
| 97 g(); | |
| 98 } | |
| 99 } | |
| 100 '''); | |
| 101 helper.checkDynamic('g()', null, 'g', isInvoke: true); | |
| 102 }); | |
| 103 | |
| 104 test( | |
| 105 'Call method defined dynamically in class from outside class via typed var
', | |
| 106 () { | |
| 107 Helper helper = new Helper(''' | |
| 108 class A { | |
| 109 g() {} | |
| 110 } | |
| 111 f(A a) { | |
| 112 a.g(); | |
| 113 } | |
| 114 '''); | |
| 115 helper.checkDynamic('a.g()', 'a', 'g', isInvoke: true); | |
| 116 }); | |
| 117 | |
| 118 test( | |
| 119 'Call method defined dynamically in class from outside class via typed exp
ression', | |
| 120 () { | |
| 121 Helper helper = new Helper(''' | |
| 122 class A { | |
| 123 g() {} | |
| 124 } | |
| 125 A h() => null; | |
| 126 f() { | |
| 127 h().g(); | |
| 128 } | |
| 129 '''); | |
| 130 helper.checkDynamic('h().g()', 'h()', 'g', isInvoke: true); | |
| 131 }); | |
| 132 | |
| 133 test( | |
| 134 'Call method defined dynamically in class from outside class via dynamic v
ar', | |
| 135 () { | |
| 136 Helper helper = new Helper(''' | |
| 137 f(a) { | |
| 138 a.g(); | |
| 139 } | |
| 140 '''); | |
| 141 helper.checkDynamic('a.g()', 'a', 'g', isInvoke: true); | |
| 142 }); | |
| 143 | |
| 144 test( | |
| 145 'Call method defined dynamically in class from outside class via dynamic e
xpression', | |
| 146 () { | |
| 147 Helper helper = new Helper(''' | |
| 148 h() => null; | |
| 149 f() { | |
| 150 h().g(); | |
| 151 } | |
| 152 '''); | |
| 153 helper.checkDynamic('h().g()', 'h()', 'g', isInvoke: true); | |
| 154 }); | |
| 155 | |
| 156 test('Call method defined locally', () { | |
| 157 Helper helper = new Helper(''' | |
| 158 f() { | |
| 159 g() {} | |
| 160 g(); | |
| 161 } | |
| 162 '''); | |
| 163 helper.checkLocalFunction('g()', 'g', isInvoke: true); | |
| 164 }); | |
| 165 | |
| 166 test('Call method undefined at top level', () { | |
| 167 Helper helper = new Helper(''' | |
| 168 f() { | |
| 169 g(); | |
| 170 } | |
| 171 '''); | |
| 172 // Undefined top level invocations are treated as dynamic. | |
| 173 // TODO(paulberry): not sure if this is a good idea. In general, when such | |
| 174 // a call appears inside an instance method, it is dynamic, because "this" | |
| 175 // might be an instance of a derived class that implements g(). However, | |
| 176 // in this case, we are not inside an instance method, so we know that the | |
| 177 // target is undefined. | |
| 178 helper.checkDynamic('g()', null, 'g', isInvoke: true); | |
| 179 }); | |
| 180 | |
| 181 test('Call method undefined at top level via prefix', () { | |
| 182 Helper helper = new Helper(''' | |
| 183 import 'lib.dart' as l; | |
| 184 | |
| 185 f() { | |
| 186 l.g(); | |
| 187 } | |
| 188 '''); | |
| 189 helper.addFile('/lib.dart', ''' | |
| 190 library lib; | |
| 191 '''); | |
| 192 // Undefined top level invocations are treated as dynamic. | |
| 193 // TODO(paulberry): not sure if this is a good idea, for similar reasons to | |
| 194 // the case above. | |
| 195 helper.checkDynamic('l.g()', null, 'g', isInvoke: true); | |
| 196 }); | |
| 197 | |
| 198 test('Call method undefined statically in class from outside class', () { | |
| 199 Helper helper = new Helper(''' | |
| 200 class A {} | |
| 201 | |
| 202 f() { | |
| 203 A.g(); | |
| 204 } | |
| 205 '''); | |
| 206 helper.checkStaticMethod('A.g()', 'A', 'g', false, isInvoke: true); | |
| 207 }); | |
| 208 | |
| 209 test( | |
| 210 'Call method undefined statically in class from outside class via prefix', | |
| 211 () { | |
| 212 Helper helper = new Helper(''' | |
| 213 import 'lib.dart' as l; | |
| 214 | |
| 215 f() { | |
| 216 l.A.g(); | |
| 217 } | |
| 218 '''); | |
| 219 helper.addFile('/lib.dart', ''' | |
| 220 library lib; | |
| 221 | |
| 222 class A {} | |
| 223 '''); | |
| 224 helper.checkStaticMethod('l.A.g()', 'A', 'g', false, isInvoke: true); | |
| 225 }); | |
| 226 | |
| 227 test('Call method undefined dynamically in class from inside class', () { | |
| 228 Helper helper = new Helper(''' | |
| 229 class A { | |
| 230 f() { | |
| 231 g(); | |
| 232 } | |
| 233 } | |
| 234 '''); | |
| 235 helper.checkDynamic('g()', null, 'g', isInvoke: true); | |
| 236 }); | |
| 237 | |
| 238 test( | |
| 239 'Call method undefined dynamically in class from outside class via typed v
ar', | |
| 240 () { | |
| 241 Helper helper = new Helper(''' | |
| 242 class A {} | |
| 243 | |
| 244 f(A a) { | |
| 245 a.g(); | |
| 246 } | |
| 247 '''); | |
| 248 helper.checkDynamic('a.g()', 'a', 'g', isInvoke: true); | |
| 249 }); | |
| 250 | |
| 251 test( | |
| 252 'Call method undefined dynamically in class from outside class via typed e
xpression', | |
| 253 () { | |
| 254 Helper helper = new Helper(''' | |
| 255 class A {} | |
| 256 | |
| 257 A h() => null; | |
| 258 | |
| 259 f() { | |
| 260 h().g(); | |
| 261 } | |
| 262 '''); | |
| 263 helper.checkDynamic('h().g()', 'h()', 'g', isInvoke: true); | |
| 264 }); | |
| 265 | |
| 266 test('Call variable defined at top level', () { | |
| 267 Helper helper = new Helper(''' | |
| 268 var x; | |
| 269 | |
| 270 f() { | |
| 271 x(); | |
| 272 } | |
| 273 '''); | |
| 274 helper.checkStaticField('x()', null, 'x', isInvoke: true); | |
| 275 }); | |
| 276 | |
| 277 test('Call variable defined at top level via prefix', () { | |
| 278 Helper helper = new Helper(''' | |
| 279 import 'lib.dart' as l; | |
| 280 | |
| 281 f() { | |
| 282 return l.x(); | |
| 283 } | |
| 284 '''); | |
| 285 helper.addFile('/lib.dart', ''' | |
| 286 library lib; | |
| 287 | |
| 288 var x; | |
| 289 '''); | |
| 290 helper.checkStaticField('l.x()', null, 'x', isInvoke: true); | |
| 291 }); | |
| 292 | |
| 293 test('Call field defined statically in class from inside class', () { | |
| 294 Helper helper = new Helper(''' | |
| 295 class A { | |
| 296 static var x; | |
| 297 | |
| 298 f() { | |
| 299 return x(); | |
| 300 } | |
| 301 } | |
| 302 '''); | |
| 303 helper.checkStaticField('x()', 'A', 'x', isInvoke: true); | |
| 304 }); | |
| 305 | |
| 306 test('Call field defined statically in class from outside class', () { | |
| 307 Helper helper = new Helper(''' | |
| 308 class A { | |
| 309 static var x; | |
| 310 } | |
| 311 | |
| 312 f() { | |
| 313 return A.x(); | |
| 314 } | |
| 315 '''); | |
| 316 helper.checkStaticField('A.x()', 'A', 'x', isInvoke: true); | |
| 317 }); | |
| 318 | |
| 319 test( | |
| 320 'Call field defined statically in class from outside class via prefix', | |
| 321 () { | |
| 322 Helper helper = new Helper(''' | |
| 323 import 'lib.dart' as l; | |
| 324 | |
| 325 f() { | |
| 326 return l.A.x(); | |
| 327 } | |
| 328 '''); | |
| 329 helper.addFile('/lib.dart', ''' | |
| 330 library lib; | |
| 331 | |
| 332 class A { | |
| 333 static var x; | |
| 334 } | |
| 335 '''); | |
| 336 helper.checkStaticField('l.A.x()', 'A', 'x', isInvoke: true); | |
| 337 }); | |
| 338 | |
| 339 test('Call field defined dynamically in class from inside class', () { | |
| 340 Helper helper = new Helper(''' | |
| 341 class A { | |
| 342 var x; | |
| 343 | |
| 344 f() { | |
| 345 return x(); | |
| 346 } | |
| 347 } | |
| 348 '''); | |
| 349 helper.checkDynamic('x()', null, 'x', isInvoke: true); | |
| 350 }); | |
| 351 | |
| 352 test( | |
| 353 'Call field defined dynamically in class from outside class via typed var'
, | |
| 354 () { | |
| 355 Helper helper = new Helper(''' | |
| 356 class A { | |
| 357 var x; | |
| 358 } | |
| 359 | |
| 360 f(A a) { | |
| 361 return a.x(); | |
| 362 } | |
| 363 '''); | |
| 364 helper.checkDynamic('a.x()', 'a', 'x', isInvoke: true); | |
| 365 }); | |
| 366 | |
| 367 test( | |
| 368 'Call field defined dynamically in class from outside class via typed expr
ession', | |
| 369 () { | |
| 370 Helper helper = new Helper(''' | |
| 371 class A { | |
| 372 var x; | |
| 373 } | |
| 374 | |
| 375 A h() => null; | |
| 376 | |
| 377 f() { | |
| 378 return h().x(); | |
| 379 } | |
| 380 '''); | |
| 381 helper.checkDynamic('h().x()', 'h()', 'x', isInvoke: true); | |
| 382 }); | |
| 383 | |
| 384 test( | |
| 385 'Call field defined dynamically in class from outside class via dynamic va
r', | |
| 386 () { | |
| 387 Helper helper = new Helper(''' | |
| 388 f(a) { | |
| 389 return a.x(); | |
| 390 } | |
| 391 '''); | |
| 392 helper.checkDynamic('a.x()', 'a', 'x', isInvoke: true); | |
| 393 }); | |
| 394 | |
| 395 test( | |
| 396 'Call field defined dynamically in class from outside class via dynamic ex
pression', | |
| 397 () { | |
| 398 Helper helper = new Helper(''' | |
| 399 h() => null; | |
| 400 | |
| 401 f() { | |
| 402 return h().x(); | |
| 403 } | |
| 404 '''); | |
| 405 helper.checkDynamic('h().x()', 'h()', 'x', isInvoke: true); | |
| 406 }); | |
| 407 | |
| 408 test('Call variable defined locally', () { | |
| 409 Helper helper = new Helper(''' | |
| 410 f() { | |
| 411 var x; | |
| 412 return x(); | |
| 413 } | |
| 414 '''); | |
| 415 helper.checkLocalVariable('x()', 'x', isInvoke: true); | |
| 416 }); | |
| 417 | |
| 418 test('Call variable defined in parameter', () { | |
| 419 Helper helper = new Helper(''' | |
| 420 f(x) { | |
| 421 return x(); | |
| 422 } | |
| 423 '''); | |
| 424 helper.checkParameter('x()', 'x', isInvoke: true); | |
| 425 }); | |
| 426 | |
| 427 test('Call accessor defined at top level', () { | |
| 428 Helper helper = new Helper(''' | |
| 429 get x => null; | |
| 430 | |
| 431 f() { | |
| 432 return x(); | |
| 433 } | |
| 434 '''); | |
| 435 helper.checkStaticProperty('x()', null, 'x', true, isInvoke: true); | |
| 436 }); | |
| 437 | |
| 438 test('Call accessor defined at top level via prefix', () { | |
| 439 Helper helper = new Helper(''' | |
| 440 import 'lib.dart' as l; | |
| 441 | |
| 442 f() { | |
| 443 return l.x(); | |
| 444 } | |
| 445 '''); | |
| 446 helper.addFile('/lib.dart', ''' | |
| 447 library lib; | |
| 448 | |
| 449 get x => null; | |
| 450 '''); | |
| 451 helper.checkStaticProperty('l.x()', null, 'x', true, isInvoke: true); | |
| 452 }); | |
| 453 | |
| 454 test('Call accessor defined statically in class from inside class', () { | |
| 455 Helper helper = new Helper(''' | |
| 456 class A { | |
| 457 static get x => null; | |
| 458 | |
| 459 f() { | |
| 460 return x(); | |
| 461 } | |
| 462 } | |
| 463 '''); | |
| 464 helper.checkStaticProperty('x()', 'A', 'x', true, isInvoke: true); | |
| 465 }); | |
| 466 | |
| 467 test('Call accessor defined statically in class from outside class', () { | |
| 468 Helper helper = new Helper(''' | |
| 469 class A { | |
| 470 static get x => null; | |
| 471 } | |
| 472 | |
| 473 f() { | |
| 474 return A.x(); | |
| 475 } | |
| 476 '''); | |
| 477 helper.checkStaticProperty('A.x()', 'A', 'x', true, isInvoke: true); | |
| 478 }); | |
| 479 | |
| 480 test( | |
| 481 'Call accessor defined statically in class from outside class via prefix', | |
| 482 () { | |
| 483 Helper helper = new Helper(''' | |
| 484 import 'lib.dart' as l; | |
| 485 | |
| 486 f() { | |
| 487 return l.A.x(); | |
| 488 } | |
| 489 '''); | |
| 490 helper.addFile('/lib.dart', ''' | |
| 491 library lib; | |
| 492 | |
| 493 class A { | |
| 494 static get x => null; | |
| 495 } | |
| 496 '''); | |
| 497 helper.checkStaticProperty('l.A.x()', 'A', 'x', true, isInvoke: true); | |
| 498 }); | |
| 499 | |
| 500 test('Call accessor defined dynamically in class from inside class', () { | |
| 501 Helper helper = new Helper(''' | |
| 502 class A { | |
| 503 get x => null; | |
| 504 | |
| 505 f() { | |
| 506 return x(); | |
| 507 } | |
| 508 } | |
| 509 '''); | |
| 510 helper.checkDynamic('x()', null, 'x', isInvoke: true); | |
| 511 }); | |
| 512 | |
| 513 test( | |
| 514 'Call accessor defined dynamically in class from outside class via typed v
ar', | |
| 515 () { | |
| 516 Helper helper = new Helper(''' | |
| 517 class A { | |
| 518 get x => null; | |
| 519 } | |
| 520 | |
| 521 f(A a) { | |
| 522 return a.x(); | |
| 523 } | |
| 524 '''); | |
| 525 helper.checkDynamic('a.x()', 'a', 'x', isInvoke: true); | |
| 526 }); | |
| 527 | |
| 528 test( | |
| 529 'Call accessor defined dynamically in class from outside class via typed e
xpression', | |
| 530 () { | |
| 531 Helper helper = new Helper(''' | |
| 532 class A { | |
| 533 get x => null; | |
| 534 } | |
| 535 | |
| 536 A h() => null; | |
| 537 | |
| 538 f() { | |
| 539 return h().x(); | |
| 540 } | |
| 541 '''); | |
| 542 helper.checkDynamic('h().x()', 'h()', 'x', isInvoke: true); | |
| 543 }); | |
| 544 | |
| 545 test( | |
| 546 'Call accessor defined dynamically in class from outside class via dynamic
var', | |
| 547 () { | |
| 548 Helper helper = new Helper(''' | |
| 549 f(a) { | |
| 550 return a.x(); | |
| 551 } | |
| 552 '''); | |
| 553 helper.checkDynamic('a.x()', 'a', 'x', isInvoke: true); | |
| 554 }); | |
| 555 | |
| 556 test( | |
| 557 'Call accessor defined dynamically in class from outside class via dynamic
expression', | |
| 558 () { | |
| 559 Helper helper = new Helper(''' | |
| 560 h() => null; | |
| 561 | |
| 562 f() { | |
| 563 return h().x(); | |
| 564 } | |
| 565 '''); | |
| 566 helper.checkDynamic('h().x()', 'h()', 'x', isInvoke: true); | |
| 567 }); | |
| 568 | |
| 569 test('Call class defined at top level', () { | |
| 570 Helper helper = new Helper(''' | |
| 571 class A {} | |
| 572 | |
| 573 f() { | |
| 574 A(); | |
| 575 } | |
| 576 '''); | |
| 577 helper.checkTypeReference( | |
| 578 'A()', | |
| 579 'A', | |
| 580 AccessKind.TOPLEVEL_TYPE, | |
| 581 isInvoke: true); | |
| 582 }); | |
| 583 | |
| 584 test('Call class defined at top level via prefix', () { | |
| 585 Helper helper = new Helper(''' | |
| 586 import 'lib.dart' as l; | |
| 587 | |
| 588 f() { | |
| 589 l.A(); | |
| 590 } | |
| 591 '''); | |
| 592 helper.addFile('/lib.dart', ''' | |
| 593 library lib; | |
| 594 | |
| 595 class A {} | |
| 596 '''); | |
| 597 helper.checkTypeReference( | |
| 598 'l.A()', | |
| 599 'A', | |
| 600 AccessKind.TOPLEVEL_TYPE, | |
| 601 isInvoke: true); | |
| 602 }); | |
| 603 | |
| 604 test('Call dynamic type undefined at toplevel', () { | |
| 605 Helper helper = new Helper(''' | |
| 606 f() { | |
| 607 dynamic(); | |
| 608 } | |
| 609 '''); | |
| 610 // Since it is legal to define a toplevel function or a class member called | |
| 611 // dynamic, "dynamic()" must be treated as a dynamic access to a function | |
| 612 // called "dynamic". | |
| 613 helper.checkDynamic('dynamic()', null, 'dynamic', isInvoke: true); | |
| 614 }); | |
| 615 | |
| 616 test('Call function typedef defined at top level', () { | |
| 617 Helper helper = new Helper(''' | |
| 618 typedef F(); | |
| 619 | |
| 620 f() { | |
| 621 F(); | |
| 622 } | |
| 623 '''); | |
| 624 helper.checkTypeReference( | |
| 625 'F()', | |
| 626 'F', | |
| 627 AccessKind.TOPLEVEL_TYPE, | |
| 628 isInvoke: true); | |
| 629 }); | |
| 630 | |
| 631 test('Call function typedef defined at top level via prefix', () { | |
| 632 Helper helper = new Helper(''' | |
| 633 import 'lib.dart' as l; | |
| 634 | |
| 635 f() { | |
| 636 l.F(); | |
| 637 } | |
| 638 '''); | |
| 639 helper.addFile('/lib.dart', ''' | |
| 640 library lib; | |
| 641 | |
| 642 typedef F(); | |
| 643 '''); | |
| 644 helper.checkTypeReference( | |
| 645 'l.F()', | |
| 646 'F', | |
| 647 AccessKind.TOPLEVEL_TYPE, | |
| 648 isInvoke: true); | |
| 649 }); | |
| 650 | |
| 651 test('Call mixin application defined at top level', () { | |
| 652 Helper helper = new Helper(''' | |
| 653 class A {} | |
| 654 class B {} | |
| 655 class C = A with B; | |
| 656 | |
| 657 f() { | |
| 658 C(); | |
| 659 } | |
| 660 '''); | |
| 661 helper.checkTypeReference( | |
| 662 'C()', | |
| 663 'C', | |
| 664 AccessKind.TOPLEVEL_TYPE, | |
| 665 isInvoke: true); | |
| 666 }); | |
| 667 | |
| 668 test('Call mixin application defined at top level via prefix', () { | |
| 669 Helper helper = new Helper(''' | |
| 670 import 'lib.dart' as l; | |
| 671 | |
| 672 f() { | |
| 673 l.C(); | |
| 674 } | |
| 675 '''); | |
| 676 helper.addFile('/lib.dart', ''' | |
| 677 library lib; | |
| 678 | |
| 679 class A {} | |
| 680 class B {} | |
| 681 class C = A with B; | |
| 682 '''); | |
| 683 helper.checkTypeReference( | |
| 684 'l.C()', | |
| 685 'C', | |
| 686 AccessKind.TOPLEVEL_TYPE, | |
| 687 isInvoke: true); | |
| 688 }); | |
| 689 | |
| 690 test('Call type parameter of enclosing class', () { | |
| 691 Helper helper = new Helper(''' | |
| 692 class A<T, U> { | |
| 693 f() { | |
| 694 U(); | |
| 695 } | |
| 696 } | |
| 697 '''); | |
| 698 helper.checkTypeReference( | |
| 699 'U()', | |
| 700 'U', | |
| 701 AccessKind.TYPE_PARAMETER, | |
| 702 isInvoke: true); | |
| 703 }); | |
| 704 | |
| 705 test('Get function defined at top level', () { | |
| 706 Helper helper = new Helper(''' | |
| 707 g() {} | |
| 708 | |
| 709 f() { | |
| 710 return g; | |
| 711 } | |
| 712 '''); | |
| 713 helper.checkStaticMethod('g', null, 'g', true, isRead: true); | |
| 714 }); | |
| 715 | |
| 716 test('Get function defined at top level via prefix', () { | |
| 717 Helper helper = new Helper(''' | |
| 718 import 'lib.dart' as l; | |
| 719 | |
| 720 f() { | |
| 721 return l.g; | |
| 722 } | |
| 723 '''); | |
| 724 helper.addFile('/lib.dart', ''' | |
| 725 library lib; | |
| 726 | |
| 727 g() {} | |
| 728 '''); | |
| 729 helper.checkStaticMethod('l.g', null, 'g', true, isRead: true); | |
| 730 }); | |
| 731 | |
| 732 test('Get method defined statically in class from inside class', () { | |
| 733 Helper helper = new Helper(''' | |
| 734 class A { | |
| 735 static g() {} | |
| 736 | |
| 737 f() { | |
| 738 return g; | |
| 739 } | |
| 740 } | |
| 741 '''); | |
| 742 helper.checkStaticMethod('g', 'A', 'g', true, isRead: true); | |
| 743 }); | |
| 744 | |
| 745 test('Get method defined statically in class from outside class', () { | |
| 746 Helper helper = new Helper(''' | |
| 747 class A { | |
| 748 static g() {} | |
| 749 } | |
| 750 f() { | |
| 751 return A.g; | |
| 752 } | |
| 753 '''); | |
| 754 helper.checkStaticMethod('A.g', 'A', 'g', true, isRead: true); | |
| 755 }); | |
| 756 | |
| 757 test( | |
| 758 'Get method defined statically in class from outside class via prefix', | |
| 759 () { | |
| 760 Helper helper = new Helper(''' | |
| 761 import 'lib.dart' as l; | |
| 762 | |
| 763 f() { | |
| 764 return l.A.g; | |
| 765 } | |
| 766 '''); | |
| 767 helper.addFile('/lib.dart', ''' | |
| 768 library lib; | |
| 769 | |
| 770 class A { | |
| 771 static g() {} | |
| 772 } | |
| 773 '''); | |
| 774 helper.checkStaticMethod('l.A.g', 'A', 'g', true, isRead: true); | |
| 775 }); | |
| 776 | |
| 777 test('Get method defined dynamically in class from inside class', () { | |
| 778 Helper helper = new Helper(''' | |
| 779 class A { | |
| 780 g() {} | |
| 781 | |
| 782 f() { | |
| 783 return g; | |
| 784 } | |
| 785 } | |
| 786 '''); | |
| 787 helper.checkDynamic('g', null, 'g', isRead: true); | |
| 788 }); | |
| 789 | |
| 790 test( | |
| 791 'Get method defined dynamically in class from outside class via typed var'
, | |
| 792 () { | |
| 793 Helper helper = new Helper(''' | |
| 794 class A { | |
| 795 g() {} | |
| 796 } | |
| 797 f(A a) { | |
| 798 return a.g; | |
| 799 } | |
| 800 '''); | |
| 801 helper.checkDynamic('a.g', 'a', 'g', isRead: true); | |
| 802 }); | |
| 803 | |
| 804 test( | |
| 805 'Get method defined dynamically in class from outside class via typed expr
ession', | |
| 806 () { | |
| 807 Helper helper = new Helper(''' | |
| 808 class A { | |
| 809 g() {} | |
| 810 } | |
| 811 A h() => null; | |
| 812 f() { | |
| 813 return h().g; | |
| 814 } | |
| 815 '''); | |
| 816 helper.checkDynamic('h().g', 'h()', 'g', isRead: true); | |
| 817 }); | |
| 818 | |
| 819 test('Get method defined locally', () { | |
| 820 Helper helper = new Helper(''' | |
| 821 f() { | |
| 822 g() {} | |
| 823 return g; | |
| 824 } | |
| 825 '''); | |
| 826 helper.checkLocalFunction('g', 'g', isRead: true); | |
| 827 }); | |
| 828 | |
| 829 test('Get variable defined at top level', () { | |
| 830 Helper helper = new Helper(''' | |
| 831 var x; | |
| 832 | |
| 833 f() { | |
| 834 return x; | |
| 835 } | |
| 836 '''); | |
| 837 helper.checkStaticField('x', null, 'x', isRead: true); | |
| 838 }); | |
| 839 | |
| 840 test('Get variable defined at top level via prefix', () { | |
| 841 Helper helper = new Helper(''' | |
| 842 import 'lib.dart' as l; | |
| 843 | |
| 844 f() { | |
| 845 return l.x; | |
| 846 } | |
| 847 '''); | |
| 848 helper.addFile('/lib.dart', ''' | |
| 849 library lib; | |
| 850 | |
| 851 var x; | |
| 852 '''); | |
| 853 helper.checkStaticField('l.x', null, 'x', isRead: true); | |
| 854 }); | |
| 855 | |
| 856 test('Get field defined statically in class from inside class', () { | |
| 857 Helper helper = new Helper(''' | |
| 858 class A { | |
| 859 static var x; | |
| 860 | |
| 861 f() { | |
| 862 return x; | |
| 863 } | |
| 864 } | |
| 865 '''); | |
| 866 helper.checkStaticField('x', 'A', 'x', isRead: true); | |
| 867 }); | |
| 868 | |
| 869 test('Get field defined statically in class from outside class', () { | |
| 870 Helper helper = new Helper(''' | |
| 871 class A { | |
| 872 static var x; | |
| 873 } | |
| 874 | |
| 875 f() { | |
| 876 return A.x; | |
| 877 } | |
| 878 '''); | |
| 879 helper.checkStaticField('A.x', 'A', 'x', isRead: true); | |
| 880 }); | |
| 881 | |
| 882 test( | |
| 883 'Get field defined statically in class from outside class via prefix', | |
| 884 () { | |
| 885 Helper helper = new Helper(''' | |
| 886 import 'lib.dart' as l; | |
| 887 | |
| 888 f() { | |
| 889 return l.A.x; | |
| 890 } | |
| 891 '''); | |
| 892 helper.addFile('/lib.dart', ''' | |
| 893 library lib; | |
| 894 | |
| 895 class A { | |
| 896 static var x; | |
| 897 } | |
| 898 '''); | |
| 899 helper.checkStaticField('l.A.x', 'A', 'x', isRead: true); | |
| 900 }); | |
| 901 | |
| 902 test('Get field defined dynamically in class from inside class', () { | |
| 903 Helper helper = new Helper(''' | |
| 904 class A { | |
| 905 var x; | |
| 906 | |
| 907 f() { | |
| 908 return x; | |
| 909 } | |
| 910 } | |
| 911 '''); | |
| 912 helper.checkDynamic('x', null, 'x', isRead: true); | |
| 913 }); | |
| 914 | |
| 915 test( | |
| 916 'Get field defined dynamically in class from outside class via typed var', | |
| 917 () { | |
| 918 Helper helper = new Helper(''' | |
| 919 class A { | |
| 920 var x; | |
| 921 } | |
| 922 | |
| 923 f(A a) { | |
| 924 return a.x; | |
| 925 } | |
| 926 '''); | |
| 927 helper.checkDynamic('a.x', 'a', 'x', isRead: true); | |
| 928 }); | |
| 929 | |
| 930 test( | |
| 931 'Get field defined dynamically in class from outside class via typed expre
ssion', | |
| 932 () { | |
| 933 Helper helper = new Helper(''' | |
| 934 class A { | |
| 935 var x; | |
| 936 } | |
| 937 | |
| 938 A h() => null; | |
| 939 | |
| 940 f() { | |
| 941 return h().x; | |
| 942 } | |
| 943 '''); | |
| 944 helper.checkDynamic('h().x', 'h()', 'x', isRead: true); | |
| 945 }); | |
| 946 | |
| 947 test( | |
| 948 'Get field defined dynamically in class from outside class via dynamic var
', | |
| 949 () { | |
| 950 Helper helper = new Helper(''' | |
| 951 f(a) { | |
| 952 return a.x; | |
| 953 } | |
| 954 '''); | |
| 955 helper.checkDynamic('a.x', 'a', 'x', isRead: true); | |
| 956 }); | |
| 957 | |
| 958 test( | |
| 959 'Get field defined dynamically in class from outside class via dynamic exp
ression', | |
| 960 () { | |
| 961 Helper helper = new Helper(''' | |
| 962 h() => null; | |
| 963 | |
| 964 f() { | |
| 965 return h().x; | |
| 966 } | |
| 967 '''); | |
| 968 helper.checkDynamic('h().x', 'h()', 'x', isRead: true); | |
| 969 }); | |
| 970 | |
| 971 test('Get variable defined locally', () { | |
| 972 Helper helper = new Helper(''' | |
| 973 f() { | |
| 974 var x; | |
| 975 return x; | |
| 976 } | |
| 977 '''); | |
| 978 helper.checkLocalVariable('x', 'x', isRead: true); | |
| 979 }); | |
| 980 | |
| 981 test('Get variable defined in parameter', () { | |
| 982 Helper helper = new Helper(''' | |
| 983 f(x) { | |
| 984 return x; | |
| 985 } | |
| 986 '''); | |
| 987 helper.checkParameter('x', 'x', isRead: true); | |
| 988 }); | |
| 989 | |
| 990 test('Get accessor defined at top level', () { | |
| 991 Helper helper = new Helper(''' | |
| 992 get x => null; | |
| 993 | |
| 994 f() { | |
| 995 return x; | |
| 996 } | |
| 997 '''); | |
| 998 helper.checkStaticProperty('x', null, 'x', true, isRead: true); | |
| 999 }); | |
| 1000 | |
| 1001 test('Get accessor defined at top level via prefix', () { | |
| 1002 Helper helper = new Helper(''' | |
| 1003 import 'lib.dart' as l; | |
| 1004 | |
| 1005 f() { | |
| 1006 return l.x; | |
| 1007 } | |
| 1008 '''); | |
| 1009 helper.addFile('/lib.dart', ''' | |
| 1010 library lib; | |
| 1011 | |
| 1012 get x => null; | |
| 1013 '''); | |
| 1014 helper.checkStaticProperty('l.x', null, 'x', true, isRead: true); | |
| 1015 }); | |
| 1016 | |
| 1017 test('Get accessor defined statically in class from inside class', () { | |
| 1018 Helper helper = new Helper(''' | |
| 1019 class A { | |
| 1020 static get x => null; | |
| 1021 | |
| 1022 f() { | |
| 1023 return x; | |
| 1024 } | |
| 1025 } | |
| 1026 '''); | |
| 1027 helper.checkStaticProperty('x', 'A', 'x', true, isRead: true); | |
| 1028 }); | |
| 1029 | |
| 1030 test('Get accessor defined statically in class from outside class', () { | |
| 1031 Helper helper = new Helper(''' | |
| 1032 class A { | |
| 1033 static get x => null; | |
| 1034 } | |
| 1035 | |
| 1036 f() { | |
| 1037 return A.x; | |
| 1038 } | |
| 1039 '''); | |
| 1040 helper.checkStaticProperty('A.x', 'A', 'x', true, isRead: true); | |
| 1041 }); | |
| 1042 | |
| 1043 test( | |
| 1044 'Get accessor defined statically in class from outside class via prefix', | |
| 1045 () { | |
| 1046 Helper helper = new Helper(''' | |
| 1047 import 'lib.dart' as l; | |
| 1048 | |
| 1049 f() { | |
| 1050 return l.A.x; | |
| 1051 } | |
| 1052 '''); | |
| 1053 helper.addFile('/lib.dart', ''' | |
| 1054 library lib; | |
| 1055 | |
| 1056 class A { | |
| 1057 static get x => null; | |
| 1058 } | |
| 1059 '''); | |
| 1060 helper.checkStaticProperty('l.A.x', 'A', 'x', true, isRead: true); | |
| 1061 }); | |
| 1062 | |
| 1063 test('Get accessor defined dynamically in class from inside class', () { | |
| 1064 Helper helper = new Helper(''' | |
| 1065 class A { | |
| 1066 get x => null; | |
| 1067 | |
| 1068 f() { | |
| 1069 return x; | |
| 1070 } | |
| 1071 } | |
| 1072 '''); | |
| 1073 helper.checkDynamic('x', null, 'x', isRead: true); | |
| 1074 }); | |
| 1075 | |
| 1076 test( | |
| 1077 'Get accessor defined dynamically in class from outside class via typed va
r', | |
| 1078 () { | |
| 1079 Helper helper = new Helper(''' | |
| 1080 class A { | |
| 1081 get x => null; | |
| 1082 } | |
| 1083 | |
| 1084 f(A a) { | |
| 1085 return a.x; | |
| 1086 } | |
| 1087 '''); | |
| 1088 helper.checkDynamic('a.x', 'a', 'x', isRead: true); | |
| 1089 }); | |
| 1090 | |
| 1091 test( | |
| 1092 'Get accessor defined dynamically in class from outside class via typed ex
pression', | |
| 1093 () { | |
| 1094 Helper helper = new Helper(''' | |
| 1095 class A { | |
| 1096 get x => null; | |
| 1097 } | |
| 1098 | |
| 1099 A h() => null; | |
| 1100 | |
| 1101 f() { | |
| 1102 return h().x; | |
| 1103 } | |
| 1104 '''); | |
| 1105 helper.checkDynamic('h().x', 'h()', 'x', isRead: true); | |
| 1106 }); | |
| 1107 | |
| 1108 test( | |
| 1109 'Get accessor defined dynamically in class from outside class via dynamic
var', | |
| 1110 () { | |
| 1111 Helper helper = new Helper(''' | |
| 1112 f(a) { | |
| 1113 return a.x; | |
| 1114 } | |
| 1115 '''); | |
| 1116 helper.checkDynamic('a.x', 'a', 'x', isRead: true); | |
| 1117 }); | |
| 1118 | |
| 1119 test( | |
| 1120 'Get accessor defined dynamically in class from outside class via dynamic
expression', | |
| 1121 () { | |
| 1122 Helper helper = new Helper(''' | |
| 1123 h() => null; | |
| 1124 | |
| 1125 f() { | |
| 1126 return h().x; | |
| 1127 } | |
| 1128 '''); | |
| 1129 helper.checkDynamic('h().x', 'h()', 'x', isRead: true); | |
| 1130 }); | |
| 1131 | |
| 1132 test('Get accessor undefined at top level', () { | |
| 1133 Helper helper = new Helper(''' | |
| 1134 f() { | |
| 1135 return x; | |
| 1136 } | |
| 1137 '''); | |
| 1138 // Undefined top level property accesses are treated as dynamic. | |
| 1139 // TODO(paulberry): not sure if this is a good idea. In general, when such | |
| 1140 // an access appears inside an instance method, it is dynamic, because | |
| 1141 // "this" might be an instance of a derived class that implements x. | |
| 1142 // However, in this case, we are not inside an instance method, so we know | |
| 1143 // that the target is undefined. | |
| 1144 helper.checkDynamic('x', null, 'x', isRead: true); | |
| 1145 }); | |
| 1146 | |
| 1147 test('Get accessor undefined at top level via prefix', () { | |
| 1148 Helper helper = new Helper(''' | |
| 1149 import 'lib.dart' as l; | |
| 1150 | |
| 1151 f() { | |
| 1152 return l.x; | |
| 1153 } | |
| 1154 '''); | |
| 1155 helper.addFile('/lib.dart', ''' | |
| 1156 library lib; | |
| 1157 '''); | |
| 1158 // Undefined top level property accesses are treated as dynamic. | |
| 1159 // TODO(paulberry): not sure if this is a good idea, for similar reasons to | |
| 1160 // the case above. | |
| 1161 helper.checkDynamic('l.x', null, 'x', isRead: true); | |
| 1162 }); | |
| 1163 | |
| 1164 test('Get accessor undefined statically in class from outside class', () { | |
| 1165 Helper helper = new Helper(''' | |
| 1166 class A {} | |
| 1167 | |
| 1168 f() { | |
| 1169 return A.x; | |
| 1170 } | |
| 1171 '''); | |
| 1172 helper.checkStaticProperty('A.x', 'A', 'x', false, isRead: true); | |
| 1173 }); | |
| 1174 | |
| 1175 test( | |
| 1176 'Get accessor undefined statically in class from outside class via prefix'
, | |
| 1177 () { | |
| 1178 Helper helper = new Helper(''' | |
| 1179 import 'lib.dart' as l; | |
| 1180 | |
| 1181 f() { | |
| 1182 return l.A.x; | |
| 1183 } | |
| 1184 '''); | |
| 1185 helper.addFile('/lib.dart', ''' | |
| 1186 library lib; | |
| 1187 | |
| 1188 class A {} | |
| 1189 '''); | |
| 1190 helper.checkStaticProperty('l.A.x', 'A', 'x', false, isRead: true); | |
| 1191 }); | |
| 1192 | |
| 1193 test('Get accessor undefined dynamically in class from inside class', () { | |
| 1194 Helper helper = new Helper(''' | |
| 1195 class A { | |
| 1196 f() { | |
| 1197 return x; | |
| 1198 } | |
| 1199 } | |
| 1200 '''); | |
| 1201 helper.checkDynamic('x', null, 'x', isRead: true); | |
| 1202 }); | |
| 1203 | |
| 1204 test( | |
| 1205 'Get accessor undefined dynamically in class from outside class via typed
var', | |
| 1206 () { | |
| 1207 Helper helper = new Helper(''' | |
| 1208 class A {} | |
| 1209 | |
| 1210 f(A a) { | |
| 1211 return a.x; | |
| 1212 } | |
| 1213 '''); | |
| 1214 helper.checkDynamic('a.x', 'a', 'x', isRead: true); | |
| 1215 }); | |
| 1216 | |
| 1217 test( | |
| 1218 'Get accessor undefined dynamically in class from outside class via typed
expression', | |
| 1219 () { | |
| 1220 Helper helper = new Helper(''' | |
| 1221 class A {} | |
| 1222 | |
| 1223 A h() => null; | |
| 1224 | |
| 1225 f() { | |
| 1226 return h().x; | |
| 1227 } | |
| 1228 '''); | |
| 1229 helper.checkDynamic('h().x', 'h()', 'x', isRead: true); | |
| 1230 }); | |
| 1231 | |
| 1232 test('Get class defined at top level', () { | |
| 1233 Helper helper = new Helper(''' | |
| 1234 class A {} | |
| 1235 var t = A; | |
| 1236 '''); | |
| 1237 helper.checkTypeReference('A', 'A', AccessKind.TOPLEVEL_TYPE, isRead: true); | |
| 1238 }); | |
| 1239 | |
| 1240 test('Get class defined at top level via prefix', () { | |
| 1241 Helper helper = new Helper(''' | |
| 1242 import 'lib.dart' as l; | |
| 1243 | |
| 1244 var t = l.A; | |
| 1245 '''); | |
| 1246 helper.addFile('/lib.dart', ''' | |
| 1247 library lib; | |
| 1248 | |
| 1249 class A {} | |
| 1250 '''); | |
| 1251 helper.checkTypeReference( | |
| 1252 'l.A', | |
| 1253 'A', | |
| 1254 AccessKind.TOPLEVEL_TYPE, | |
| 1255 isRead: true); | |
| 1256 }); | |
| 1257 | |
| 1258 test('Get dynamic type', () { | |
| 1259 Helper helper = new Helper(''' | |
| 1260 var t = dynamic; | |
| 1261 '''); | |
| 1262 helper.checkTypeReference( | |
| 1263 'dynamic', | |
| 1264 'dynamic', | |
| 1265 AccessKind.TOPLEVEL_TYPE, | |
| 1266 isRead: true); | |
| 1267 }); | |
| 1268 | |
| 1269 test('Get function typedef defined at top level', () { | |
| 1270 Helper helper = new Helper(''' | |
| 1271 typedef F(); | |
| 1272 var t = F; | |
| 1273 '''); | |
| 1274 helper.checkTypeReference('F', 'F', AccessKind.TOPLEVEL_TYPE, isRead: true); | |
| 1275 }); | |
| 1276 | |
| 1277 test('Get function typedef defined at top level via prefix', () { | |
| 1278 Helper helper = new Helper(''' | |
| 1279 import 'lib.dart' as l; | |
| 1280 | |
| 1281 var t = l.F; | |
| 1282 '''); | |
| 1283 helper.addFile('/lib.dart', ''' | |
| 1284 library lib; | |
| 1285 | |
| 1286 typedef F(); | |
| 1287 '''); | |
| 1288 helper.checkTypeReference( | |
| 1289 'l.F', | |
| 1290 'F', | |
| 1291 AccessKind.TOPLEVEL_TYPE, | |
| 1292 isRead: true); | |
| 1293 }); | |
| 1294 | |
| 1295 test('Get mixin application defined at top level', () { | |
| 1296 Helper helper = new Helper(''' | |
| 1297 class A {} | |
| 1298 class B {} | |
| 1299 class C = A with B; | |
| 1300 var t = C; | |
| 1301 '''); | |
| 1302 helper.checkTypeReference('C', 'C', AccessKind.TOPLEVEL_TYPE, isRead: true); | |
| 1303 }); | |
| 1304 | |
| 1305 test('Get mixin application defined at top level via prefix', () { | |
| 1306 Helper helper = new Helper(''' | |
| 1307 import 'lib.dart' as l; | |
| 1308 | |
| 1309 var t = l.C; | |
| 1310 '''); | |
| 1311 helper.addFile('/lib.dart', ''' | |
| 1312 library lib; | |
| 1313 | |
| 1314 class A {} | |
| 1315 class B {} | |
| 1316 class C = A with B; | |
| 1317 '''); | |
| 1318 helper.checkTypeReference( | |
| 1319 'l.C', | |
| 1320 'C', | |
| 1321 AccessKind.TOPLEVEL_TYPE, | |
| 1322 isRead: true); | |
| 1323 }); | |
| 1324 | |
| 1325 test('Get type parameter of enclosing class', () { | |
| 1326 Helper helper = new Helper(''' | |
| 1327 class A<T, U> { | |
| 1328 f() { | |
| 1329 var t = U; | |
| 1330 } | |
| 1331 } | |
| 1332 '''); | |
| 1333 helper.checkTypeReference( | |
| 1334 'U', | |
| 1335 'U', | |
| 1336 AccessKind.TYPE_PARAMETER, | |
| 1337 isRead: true); | |
| 1338 }); | |
| 1339 | |
| 1340 test('Set variable defined at top level', () { | |
| 1341 Helper helper = new Helper(''' | |
| 1342 var x; | |
| 1343 | |
| 1344 f() { | |
| 1345 x = 1; | |
| 1346 } | |
| 1347 '''); | |
| 1348 helper.checkStaticField('x', null, 'x', isWrite: true); | |
| 1349 }); | |
| 1350 | |
| 1351 test('Set variable defined at top level in foreach loop', () { | |
| 1352 Helper helper = new Helper(''' | |
| 1353 var x; | |
| 1354 | |
| 1355 f() { | |
| 1356 for (x in []) {} | |
| 1357 } | |
| 1358 '''); | |
| 1359 helper.checkStaticField('x', null, 'x', isWrite: true); | |
| 1360 }); | |
| 1361 | |
| 1362 test('Set variable defined at top level via prefix', () { | |
| 1363 Helper helper = new Helper(''' | |
| 1364 import 'lib.dart' as l; | |
| 1365 | |
| 1366 f() { | |
| 1367 l.x = 1; | |
| 1368 } | |
| 1369 '''); | |
| 1370 helper.addFile('/lib.dart', ''' | |
| 1371 library lib; | |
| 1372 | |
| 1373 var x; | |
| 1374 '''); | |
| 1375 helper.checkStaticField('l.x', null, 'x', isWrite: true); | |
| 1376 }); | |
| 1377 | |
| 1378 test('Set field defined statically in class from inside class', () { | |
| 1379 Helper helper = new Helper(''' | |
| 1380 class A { | |
| 1381 static var x; | |
| 1382 | |
| 1383 f() { | |
| 1384 x = 1; | |
| 1385 } | |
| 1386 } | |
| 1387 '''); | |
| 1388 helper.checkStaticField('x', 'A', 'x', isWrite: true); | |
| 1389 }); | |
| 1390 | |
| 1391 test( | |
| 1392 'Set field defined statically in class from inside class in foreach' + ' l
oop', | |
| 1393 () { | |
| 1394 Helper helper = new Helper(''' | |
| 1395 class A { | |
| 1396 static var x; | |
| 1397 | |
| 1398 f() { | |
| 1399 for (x in []) {} | |
| 1400 } | |
| 1401 } | |
| 1402 '''); | |
| 1403 helper.checkStaticField('x', 'A', 'x', isWrite: true); | |
| 1404 }); | |
| 1405 | |
| 1406 test('Set field defined statically in class from outside class', () { | |
| 1407 Helper helper = new Helper(''' | |
| 1408 class A { | |
| 1409 static var x; | |
| 1410 } | |
| 1411 | |
| 1412 f() { | |
| 1413 A.x = 1; | |
| 1414 } | |
| 1415 '''); | |
| 1416 helper.checkStaticField('A.x', 'A', 'x', isWrite: true); | |
| 1417 }); | |
| 1418 | |
| 1419 test( | |
| 1420 'Set field defined statically in class from outside class via prefix', | |
| 1421 () { | |
| 1422 Helper helper = new Helper(''' | |
| 1423 import 'lib.dart' as l; | |
| 1424 | |
| 1425 f() { | |
| 1426 l.A.x = 1; | |
| 1427 } | |
| 1428 '''); | |
| 1429 helper.addFile('/lib.dart', ''' | |
| 1430 library lib; | |
| 1431 | |
| 1432 class A { | |
| 1433 static var x; | |
| 1434 } | |
| 1435 '''); | |
| 1436 helper.checkStaticField('l.A.x', 'A', 'x', isWrite: true); | |
| 1437 }); | |
| 1438 | |
| 1439 test('Set field defined dynamically in class from inside class', () { | |
| 1440 Helper helper = new Helper(''' | |
| 1441 class A { | |
| 1442 var x; | |
| 1443 | |
| 1444 f() { | |
| 1445 x = 1; | |
| 1446 } | |
| 1447 } | |
| 1448 '''); | |
| 1449 helper.checkDynamic('x', null, 'x', isWrite: true); | |
| 1450 }); | |
| 1451 | |
| 1452 test( | |
| 1453 'Set field defined dynamically in class from inside class in foreach' + '
loop', | |
| 1454 () { | |
| 1455 Helper helper = new Helper(''' | |
| 1456 class A { | |
| 1457 var x; | |
| 1458 | |
| 1459 f() { | |
| 1460 for (x in []) {} | |
| 1461 } | |
| 1462 } | |
| 1463 '''); | |
| 1464 helper.checkDynamic('x', null, 'x', isWrite: true); | |
| 1465 }); | |
| 1466 | |
| 1467 test( | |
| 1468 'Set field defined dynamically in class from outside class via typed var', | |
| 1469 () { | |
| 1470 Helper helper = new Helper(''' | |
| 1471 class A { | |
| 1472 var x; | |
| 1473 } | |
| 1474 | |
| 1475 f(A a) { | |
| 1476 a.x = 1; | |
| 1477 } | |
| 1478 '''); | |
| 1479 helper.checkDynamic('a.x', 'a', 'x', isWrite: true); | |
| 1480 }); | |
| 1481 | |
| 1482 test( | |
| 1483 'Set field defined dynamically in class from outside class via typed expre
ssion', | |
| 1484 () { | |
| 1485 Helper helper = new Helper(''' | |
| 1486 class A { | |
| 1487 var x; | |
| 1488 } | |
| 1489 | |
| 1490 A h() => null; | |
| 1491 | |
| 1492 f() { | |
| 1493 h().x = 1; | |
| 1494 } | |
| 1495 '''); | |
| 1496 helper.checkDynamic('h().x', 'h()', 'x', isWrite: true); | |
| 1497 }); | |
| 1498 | |
| 1499 test('Set variable defined locally', () { | |
| 1500 Helper helper = new Helper(''' | |
| 1501 f() { | |
| 1502 var x; | |
| 1503 x = 1; | |
| 1504 } | |
| 1505 '''); | |
| 1506 helper.checkLocalVariable('x', 'x', isWrite: true); | |
| 1507 }); | |
| 1508 | |
| 1509 test('Set variable defined locally in foreach loop', () { | |
| 1510 Helper helper = new Helper(''' | |
| 1511 f() { | |
| 1512 var x; | |
| 1513 for (x in []) {} | |
| 1514 } | |
| 1515 '''); | |
| 1516 helper.checkLocalVariable('x', 'x', isWrite: true); | |
| 1517 }); | |
| 1518 | |
| 1519 test('Set variable defined in parameter', () { | |
| 1520 Helper helper = new Helper(''' | |
| 1521 f(x) { | |
| 1522 x = 1; | |
| 1523 } | |
| 1524 '''); | |
| 1525 helper.checkParameter('x', 'x', isWrite: true); | |
| 1526 }); | |
| 1527 | |
| 1528 test('Set variable defined in parameter in foreach loop', () { | |
| 1529 Helper helper = new Helper(''' | |
| 1530 f(x) { | |
| 1531 for (x in []) {} | |
| 1532 } | |
| 1533 '''); | |
| 1534 helper.checkParameter('x', 'x', isWrite: true); | |
| 1535 }); | |
| 1536 | |
| 1537 test('Set accessor defined at top level', () { | |
| 1538 Helper helper = new Helper(''' | |
| 1539 set x(value) {}; | |
| 1540 | |
| 1541 f() { | |
| 1542 x = 1; | |
| 1543 } | |
| 1544 '''); | |
| 1545 helper.checkStaticProperty('x', null, 'x', true, isWrite: true); | |
| 1546 }); | |
| 1547 | |
| 1548 test('Set accessor defined at top level in foreach loop', () { | |
| 1549 Helper helper = new Helper(''' | |
| 1550 set x(value) {}; | |
| 1551 | |
| 1552 f() { | |
| 1553 for (x in []) {} | |
| 1554 } | |
| 1555 '''); | |
| 1556 helper.checkStaticProperty('x', null, 'x', true, isWrite: true); | |
| 1557 }); | |
| 1558 | |
| 1559 test('Set accessor defined at top level via prefix', () { | |
| 1560 Helper helper = new Helper(''' | |
| 1561 import 'lib.dart' as l; | |
| 1562 | |
| 1563 f() { | |
| 1564 l.x = 1; | |
| 1565 } | |
| 1566 '''); | |
| 1567 helper.addFile('/lib.dart', ''' | |
| 1568 library lib; | |
| 1569 | |
| 1570 set x(value) {}; | |
| 1571 '''); | |
| 1572 helper.checkStaticProperty('l.x', null, 'x', true, isWrite: true); | |
| 1573 }); | |
| 1574 | |
| 1575 test('Set accessor defined statically in class from inside class', () { | |
| 1576 Helper helper = new Helper(''' | |
| 1577 class A { | |
| 1578 static set x(value) {} | |
| 1579 | |
| 1580 f() { | |
| 1581 x = 1; | |
| 1582 } | |
| 1583 } | |
| 1584 '''); | |
| 1585 helper.checkStaticProperty('x', 'A', 'x', true, isWrite: true); | |
| 1586 }); | |
| 1587 | |
| 1588 test( | |
| 1589 'Set accessor defined statically in class from inside class in' + | |
| 1590 ' foreach loop', | |
| 1591 () { | |
| 1592 Helper helper = new Helper(''' | |
| 1593 class A { | |
| 1594 static set x(value) {} | |
| 1595 | |
| 1596 f() { | |
| 1597 for (x in []) {} | |
| 1598 } | |
| 1599 } | |
| 1600 '''); | |
| 1601 helper.checkStaticProperty('x', 'A', 'x', true, isWrite: true); | |
| 1602 }); | |
| 1603 | |
| 1604 test('Set accessor defined statically in class from outside class', () { | |
| 1605 Helper helper = new Helper(''' | |
| 1606 class A { | |
| 1607 static set x(value) {} | |
| 1608 } | |
| 1609 | |
| 1610 f() { | |
| 1611 A.x = 1; | |
| 1612 } | |
| 1613 '''); | |
| 1614 helper.checkStaticProperty('A.x', 'A', 'x', true, isWrite: true); | |
| 1615 }); | |
| 1616 | |
| 1617 test( | |
| 1618 'Set accessor defined statically in class from outside class via prefix', | |
| 1619 () { | |
| 1620 Helper helper = new Helper(''' | |
| 1621 import 'lib.dart' as l; | |
| 1622 | |
| 1623 f() { | |
| 1624 l.A.x = 1; | |
| 1625 } | |
| 1626 '''); | |
| 1627 helper.addFile('/lib.dart', ''' | |
| 1628 library lib; | |
| 1629 | |
| 1630 class A { | |
| 1631 static set x(value) {} | |
| 1632 } | |
| 1633 '''); | |
| 1634 helper.checkStaticProperty('l.A.x', 'A', 'x', true, isWrite: true); | |
| 1635 }); | |
| 1636 | |
| 1637 test('Set accessor defined dynamically in class from inside class', () { | |
| 1638 Helper helper = new Helper(''' | |
| 1639 class A { | |
| 1640 set x(value) {} | |
| 1641 | |
| 1642 f() { | |
| 1643 x = 1; | |
| 1644 } | |
| 1645 } | |
| 1646 '''); | |
| 1647 helper.checkDynamic('x', null, 'x', isWrite: true); | |
| 1648 }); | |
| 1649 | |
| 1650 test( | |
| 1651 'Set accessor defined dynamically in class from inside class in' + | |
| 1652 ' foreach loop', | |
| 1653 () { | |
| 1654 Helper helper = new Helper(''' | |
| 1655 class A { | |
| 1656 set x(value) {} | |
| 1657 | |
| 1658 f() { | |
| 1659 for (x in []) {} | |
| 1660 } | |
| 1661 } | |
| 1662 '''); | |
| 1663 helper.checkDynamic('x', null, 'x', isWrite: true); | |
| 1664 }); | |
| 1665 | |
| 1666 test( | |
| 1667 'Set accessor defined dynamically in class from outside class via typed va
r', | |
| 1668 () { | |
| 1669 Helper helper = new Helper(''' | |
| 1670 class A { | |
| 1671 set x(value) {} | |
| 1672 } | |
| 1673 | |
| 1674 f(A a) { | |
| 1675 a.x = 1; | |
| 1676 } | |
| 1677 '''); | |
| 1678 helper.checkDynamic('a.x', 'a', 'x', isWrite: true); | |
| 1679 }); | |
| 1680 | |
| 1681 test( | |
| 1682 'Set accessor defined dynamically in class from outside class via typed ex
pression', | |
| 1683 () { | |
| 1684 Helper helper = new Helper(''' | |
| 1685 class A { | |
| 1686 set x(value) {} | |
| 1687 } | |
| 1688 | |
| 1689 A h() => null; | |
| 1690 | |
| 1691 f() { | |
| 1692 h().x = 1; | |
| 1693 } | |
| 1694 '''); | |
| 1695 helper.checkDynamic('h().x', 'h()', 'x', isWrite: true); | |
| 1696 }); | |
| 1697 | |
| 1698 test( | |
| 1699 'Set accessor defined dynamically in class from outside class via dynamic
var', | |
| 1700 () { | |
| 1701 Helper helper = new Helper(''' | |
| 1702 f(a) { | |
| 1703 a.x = 1; | |
| 1704 } | |
| 1705 '''); | |
| 1706 helper.checkDynamic('a.x', 'a', 'x', isWrite: true); | |
| 1707 }); | |
| 1708 | |
| 1709 test( | |
| 1710 'Set accessor defined dynamically in class from outside class via dynamic
expression', | |
| 1711 () { | |
| 1712 Helper helper = new Helper(''' | |
| 1713 h() => null; | |
| 1714 | |
| 1715 f() { | |
| 1716 h().x = 1; | |
| 1717 } | |
| 1718 '''); | |
| 1719 helper.checkDynamic('h().x', 'h()', 'x', isWrite: true); | |
| 1720 }); | |
| 1721 | |
| 1722 test('Set accessor undefined at top level', () { | |
| 1723 Helper helper = new Helper(''' | |
| 1724 f() { | |
| 1725 x = 1; | |
| 1726 } | |
| 1727 '''); | |
| 1728 helper.checkDynamic('x', null, 'x', isWrite: true); | |
| 1729 }); | |
| 1730 | |
| 1731 test('Set accessor undefined at top level in foreach loop', () { | |
| 1732 Helper helper = new Helper(''' | |
| 1733 f() { | |
| 1734 for (x in []) {} | |
| 1735 } | |
| 1736 '''); | |
| 1737 helper.checkDynamic('x', null, 'x', isWrite: true); | |
| 1738 }); | |
| 1739 | |
| 1740 test('Set accessor undefined at top level via prefix', () { | |
| 1741 Helper helper = new Helper(''' | |
| 1742 import 'lib.dart' as l; | |
| 1743 | |
| 1744 f() { | |
| 1745 l.x = 1; | |
| 1746 } | |
| 1747 '''); | |
| 1748 helper.addFile('/lib.dart', ''' | |
| 1749 library lib; | |
| 1750 '''); | |
| 1751 helper.checkDynamic('l.x', null, 'x', isWrite: true); | |
| 1752 }); | |
| 1753 | |
| 1754 test('Set accessor undefined statically in class from outside class', () { | |
| 1755 Helper helper = new Helper(''' | |
| 1756 class A {} | |
| 1757 | |
| 1758 f() { | |
| 1759 A.x = 1; | |
| 1760 } | |
| 1761 '''); | |
| 1762 helper.checkStaticProperty('A.x', 'A', 'x', false, isWrite: true); | |
| 1763 }); | |
| 1764 | |
| 1765 test( | |
| 1766 'Set accessor undefined statically in class from outside class via prefix'
, | |
| 1767 () { | |
| 1768 Helper helper = new Helper(''' | |
| 1769 import 'lib.dart' as l; | |
| 1770 | |
| 1771 f() { | |
| 1772 l.A.x = 1; | |
| 1773 } | |
| 1774 '''); | |
| 1775 helper.addFile('/lib.dart', ''' | |
| 1776 library lib; | |
| 1777 | |
| 1778 class A {} | |
| 1779 '''); | |
| 1780 helper.checkStaticProperty('l.A.x', 'A', 'x', false, isWrite: true); | |
| 1781 }); | |
| 1782 | |
| 1783 test('Set accessor undefined dynamically in class from inside class', () { | |
| 1784 Helper helper = new Helper(''' | |
| 1785 class A { | |
| 1786 f() { | |
| 1787 x = 1; | |
| 1788 } | |
| 1789 } | |
| 1790 '''); | |
| 1791 helper.checkDynamic('x', null, 'x', isWrite: true); | |
| 1792 }); | |
| 1793 | |
| 1794 test( | |
| 1795 'Set accessor undefined dynamically in class from inside class in' + | |
| 1796 ' foreach loop', | |
| 1797 () { | |
| 1798 Helper helper = new Helper(''' | |
| 1799 class A { | |
| 1800 f() { | |
| 1801 for (x in []) {} | |
| 1802 } | |
| 1803 } | |
| 1804 '''); | |
| 1805 helper.checkDynamic('x', null, 'x', isWrite: true); | |
| 1806 }); | |
| 1807 | |
| 1808 test( | |
| 1809 'Set accessor undefined dynamically in class from outside class via typed
var', | |
| 1810 () { | |
| 1811 Helper helper = new Helper(''' | |
| 1812 class A {} | |
| 1813 | |
| 1814 f(A a) { | |
| 1815 a.x = 1; | |
| 1816 } | |
| 1817 '''); | |
| 1818 helper.checkDynamic('a.x', 'a', 'x', isWrite: true); | |
| 1819 }); | |
| 1820 | |
| 1821 test( | |
| 1822 'Set accessor undefined dynamically in class from outside class via typed
expression', | |
| 1823 () { | |
| 1824 Helper helper = new Helper(''' | |
| 1825 class A {} | |
| 1826 | |
| 1827 A h() => null; | |
| 1828 | |
| 1829 f() { | |
| 1830 h().x = 1; | |
| 1831 } | |
| 1832 '''); | |
| 1833 helper.checkDynamic('h().x', 'h()', 'x', isWrite: true); | |
| 1834 }); | |
| 1835 | |
| 1836 test('RMW variable defined at top level', () { | |
| 1837 Helper helper = new Helper(''' | |
| 1838 var x; | |
| 1839 | |
| 1840 f() { | |
| 1841 x += 1; | |
| 1842 } | |
| 1843 '''); | |
| 1844 helper.checkStaticField('x', null, 'x', isRead: true, isWrite: true); | |
| 1845 }); | |
| 1846 | |
| 1847 test('RMW variable defined at top level via prefix', () { | |
| 1848 Helper helper = new Helper(''' | |
| 1849 import 'lib.dart' as l; | |
| 1850 | |
| 1851 f() { | |
| 1852 l.x += 1; | |
| 1853 } | |
| 1854 '''); | |
| 1855 helper.addFile('/lib.dart', ''' | |
| 1856 library lib; | |
| 1857 | |
| 1858 var x; | |
| 1859 '''); | |
| 1860 helper.checkStaticField('l.x', null, 'x', isRead: true, isWrite: true); | |
| 1861 }); | |
| 1862 | |
| 1863 test('RMW field defined statically in class from inside class', () { | |
| 1864 Helper helper = new Helper(''' | |
| 1865 class A { | |
| 1866 static var x; | |
| 1867 | |
| 1868 f() { | |
| 1869 x += 1; | |
| 1870 } | |
| 1871 } | |
| 1872 '''); | |
| 1873 helper.checkStaticField('x', 'A', 'x', isRead: true, isWrite: true); | |
| 1874 }); | |
| 1875 | |
| 1876 test('RMW field defined statically in class from outside class', () { | |
| 1877 Helper helper = new Helper(''' | |
| 1878 class A { | |
| 1879 static var x; | |
| 1880 } | |
| 1881 | |
| 1882 f() { | |
| 1883 A.x += 1; | |
| 1884 } | |
| 1885 '''); | |
| 1886 helper.checkStaticField('A.x', 'A', 'x', isRead: true, isWrite: true); | |
| 1887 }); | |
| 1888 | |
| 1889 test( | |
| 1890 'RMW field defined statically in class from outside class via prefix', | |
| 1891 () { | |
| 1892 Helper helper = new Helper(''' | |
| 1893 import 'lib.dart' as l; | |
| 1894 | |
| 1895 f() { | |
| 1896 l.A.x += 1; | |
| 1897 } | |
| 1898 '''); | |
| 1899 helper.addFile('/lib.dart', ''' | |
| 1900 library lib; | |
| 1901 | |
| 1902 class A { | |
| 1903 static var x; | |
| 1904 } | |
| 1905 '''); | |
| 1906 helper.checkStaticField('l.A.x', 'A', 'x', isRead: true, isWrite: true); | |
| 1907 }); | |
| 1908 | |
| 1909 test('RMW field defined dynamically in class from inside class', () { | |
| 1910 Helper helper = new Helper(''' | |
| 1911 class A { | |
| 1912 var x; | |
| 1913 | |
| 1914 f() { | |
| 1915 x += 1; | |
| 1916 } | |
| 1917 } | |
| 1918 '''); | |
| 1919 helper.checkDynamic('x', null, 'x', isRead: true, isWrite: true); | |
| 1920 }); | |
| 1921 | |
| 1922 test( | |
| 1923 'RMW field defined dynamically in class from outside class via typed var', | |
| 1924 () { | |
| 1925 Helper helper = new Helper(''' | |
| 1926 class A { | |
| 1927 var x; | |
| 1928 } | |
| 1929 | |
| 1930 f(A a) { | |
| 1931 a.x += 1; | |
| 1932 } | |
| 1933 '''); | |
| 1934 helper.checkDynamic('a.x', 'a', 'x', isRead: true, isWrite: true); | |
| 1935 }); | |
| 1936 | |
| 1937 test( | |
| 1938 'RMW field defined dynamically in class from outside class via typed expre
ssion', | |
| 1939 () { | |
| 1940 Helper helper = new Helper(''' | |
| 1941 class A { | |
| 1942 var x; | |
| 1943 } | |
| 1944 | |
| 1945 A h() => null; | |
| 1946 | |
| 1947 f() { | |
| 1948 h().x += 1; | |
| 1949 } | |
| 1950 '''); | |
| 1951 helper.checkDynamic('h().x', 'h()', 'x', isRead: true, isWrite: true); | |
| 1952 }); | |
| 1953 | |
| 1954 test('RMW variable defined locally', () { | |
| 1955 Helper helper = new Helper(''' | |
| 1956 f() { | |
| 1957 var x; | |
| 1958 x += 1; | |
| 1959 } | |
| 1960 '''); | |
| 1961 helper.checkLocalVariable('x', 'x', isRead: true, isWrite: true); | |
| 1962 }); | |
| 1963 | |
| 1964 test('RMW variable defined in parameter', () { | |
| 1965 Helper helper = new Helper(''' | |
| 1966 f(x) { | |
| 1967 x += 1; | |
| 1968 } | |
| 1969 '''); | |
| 1970 helper.checkParameter('x', 'x', isRead: true, isWrite: true); | |
| 1971 }); | |
| 1972 | |
| 1973 test('RMW accessor defined at top level', () { | |
| 1974 Helper helper = new Helper(''' | |
| 1975 set x(value) {}; | |
| 1976 | |
| 1977 f() { | |
| 1978 x += 1; | |
| 1979 } | |
| 1980 '''); | |
| 1981 helper.checkStaticProperty( | |
| 1982 'x', | |
| 1983 null, | |
| 1984 'x', | |
| 1985 true, | |
| 1986 isRead: true, | |
| 1987 isWrite: true); | |
| 1988 }); | |
| 1989 | |
| 1990 test('RMW accessor defined at top level via prefix', () { | |
| 1991 Helper helper = new Helper(''' | |
| 1992 import 'lib.dart' as l; | |
| 1993 | |
| 1994 f() { | |
| 1995 l.x += 1; | |
| 1996 } | |
| 1997 '''); | |
| 1998 helper.addFile('/lib.dart', ''' | |
| 1999 library lib; | |
| 2000 | |
| 2001 set x(value) {}; | |
| 2002 '''); | |
| 2003 helper.checkStaticProperty( | |
| 2004 'l.x', | |
| 2005 null, | |
| 2006 'x', | |
| 2007 true, | |
| 2008 isRead: true, | |
| 2009 isWrite: true); | |
| 2010 }); | |
| 2011 | |
| 2012 test('RMW accessor defined statically in class from inside class', () { | |
| 2013 Helper helper = new Helper(''' | |
| 2014 class A { | |
| 2015 static set x(value) {} | |
| 2016 | |
| 2017 f() { | |
| 2018 x += 1; | |
| 2019 } | |
| 2020 } | |
| 2021 '''); | |
| 2022 helper.checkStaticProperty( | |
| 2023 'x', | |
| 2024 'A', | |
| 2025 'x', | |
| 2026 true, | |
| 2027 isRead: true, | |
| 2028 isWrite: true); | |
| 2029 }); | |
| 2030 | |
| 2031 test('RMW accessor defined statically in class from outside class', () { | |
| 2032 Helper helper = new Helper(''' | |
| 2033 class A { | |
| 2034 static set x(value) {} | |
| 2035 } | |
| 2036 | |
| 2037 f() { | |
| 2038 A.x += 1; | |
| 2039 } | |
| 2040 '''); | |
| 2041 helper.checkStaticProperty( | |
| 2042 'A.x', | |
| 2043 'A', | |
| 2044 'x', | |
| 2045 true, | |
| 2046 isRead: true, | |
| 2047 isWrite: true); | |
| 2048 }); | |
| 2049 | |
| 2050 test( | |
| 2051 'RMW accessor defined statically in class from outside class via prefix', | |
| 2052 () { | |
| 2053 Helper helper = new Helper(''' | |
| 2054 import 'lib.dart' as l; | |
| 2055 | |
| 2056 f() { | |
| 2057 l.A.x += 1; | |
| 2058 } | |
| 2059 '''); | |
| 2060 helper.addFile('/lib.dart', ''' | |
| 2061 library lib; | |
| 2062 | |
| 2063 class A { | |
| 2064 static set x(value) {} | |
| 2065 } | |
| 2066 '''); | |
| 2067 helper.checkStaticProperty( | |
| 2068 'l.A.x', | |
| 2069 'A', | |
| 2070 'x', | |
| 2071 true, | |
| 2072 isRead: true, | |
| 2073 isWrite: true); | |
| 2074 }); | |
| 2075 | |
| 2076 test('RMW accessor defined dynamically in class from inside class', () { | |
| 2077 Helper helper = new Helper(''' | |
| 2078 class A { | |
| 2079 set x(value) {} | |
| 2080 | |
| 2081 f() { | |
| 2082 x += 1; | |
| 2083 } | |
| 2084 } | |
| 2085 '''); | |
| 2086 helper.checkDynamic('x', null, 'x', isRead: true, isWrite: true); | |
| 2087 }); | |
| 2088 | |
| 2089 test( | |
| 2090 'RMW accessor defined dynamically in class from outside class via typed va
r', | |
| 2091 () { | |
| 2092 Helper helper = new Helper(''' | |
| 2093 class A { | |
| 2094 set x(value) {} | |
| 2095 } | |
| 2096 | |
| 2097 f(A a) { | |
| 2098 a.x += 1; | |
| 2099 } | |
| 2100 '''); | |
| 2101 helper.checkDynamic('a.x', 'a', 'x', isRead: true, isWrite: true); | |
| 2102 }); | |
| 2103 | |
| 2104 test( | |
| 2105 'RMW accessor defined dynamically in class from outside class via typed ex
pression', | |
| 2106 () { | |
| 2107 Helper helper = new Helper(''' | |
| 2108 class A { | |
| 2109 set x(value) {} | |
| 2110 } | |
| 2111 | |
| 2112 A h() => null; | |
| 2113 | |
| 2114 f() { | |
| 2115 h().x += 1; | |
| 2116 } | |
| 2117 '''); | |
| 2118 helper.checkDynamic('h().x', 'h()', 'x', isRead: true, isWrite: true); | |
| 2119 }); | |
| 2120 | |
| 2121 test( | |
| 2122 'RMW accessor defined dynamically in class from outside class via dynamic
var', | |
| 2123 () { | |
| 2124 Helper helper = new Helper(''' | |
| 2125 f(a) { | |
| 2126 a.x += 1; | |
| 2127 } | |
| 2128 '''); | |
| 2129 helper.checkDynamic('a.x', 'a', 'x', isRead: true, isWrite: true); | |
| 2130 }); | |
| 2131 | |
| 2132 test( | |
| 2133 'RMW accessor defined dynamically in class from outside class via dynamic
expression', | |
| 2134 () { | |
| 2135 Helper helper = new Helper(''' | |
| 2136 h() => null; | |
| 2137 | |
| 2138 f() { | |
| 2139 h().x += 1; | |
| 2140 } | |
| 2141 '''); | |
| 2142 helper.checkDynamic('h().x', 'h()', 'x', isRead: true, isWrite: true); | |
| 2143 }); | |
| 2144 | |
| 2145 test('RMW accessor undefined at top level', () { | |
| 2146 Helper helper = new Helper(''' | |
| 2147 f() { | |
| 2148 x += 1; | |
| 2149 } | |
| 2150 '''); | |
| 2151 helper.checkDynamic('x', null, 'x', isRead: true, isWrite: true); | |
| 2152 }); | |
| 2153 | |
| 2154 test('RMW accessor undefined at top level via prefix', () { | |
| 2155 Helper helper = new Helper(''' | |
| 2156 import 'lib.dart' as l; | |
| 2157 | |
| 2158 f() { | |
| 2159 l.x += 1; | |
| 2160 } | |
| 2161 '''); | |
| 2162 helper.addFile('/lib.dart', ''' | |
| 2163 library lib; | |
| 2164 '''); | |
| 2165 helper.checkDynamic('l.x', null, 'x', isRead: true, isWrite: true); | |
| 2166 }); | |
| 2167 | |
| 2168 test('RMW accessor undefined statically in class from outside class', () { | |
| 2169 Helper helper = new Helper(''' | |
| 2170 class A {} | |
| 2171 | |
| 2172 f() { | |
| 2173 A.x += 1; | |
| 2174 } | |
| 2175 '''); | |
| 2176 helper.checkStaticProperty( | |
| 2177 'A.x', | |
| 2178 'A', | |
| 2179 'x', | |
| 2180 false, | |
| 2181 isRead: true, | |
| 2182 isWrite: true); | |
| 2183 }); | |
| 2184 | |
| 2185 test( | |
| 2186 'RMW accessor undefined statically in class from outside class via prefix'
, | |
| 2187 () { | |
| 2188 Helper helper = new Helper(''' | |
| 2189 import 'lib.dart' as l; | |
| 2190 | |
| 2191 f() { | |
| 2192 l.A.x += 1; | |
| 2193 } | |
| 2194 '''); | |
| 2195 helper.addFile('/lib.dart', ''' | |
| 2196 library lib; | |
| 2197 | |
| 2198 class A {} | |
| 2199 '''); | |
| 2200 helper.checkStaticProperty( | |
| 2201 'l.A.x', | |
| 2202 'A', | |
| 2203 'x', | |
| 2204 false, | |
| 2205 isRead: true, | |
| 2206 isWrite: true); | |
| 2207 }); | |
| 2208 | |
| 2209 test('RMW accessor undefined dynamically in class from inside class', () { | |
| 2210 Helper helper = new Helper(''' | |
| 2211 class A { | |
| 2212 f() { | |
| 2213 x += 1; | |
| 2214 } | |
| 2215 } | |
| 2216 '''); | |
| 2217 helper.checkDynamic('x', null, 'x', isRead: true, isWrite: true); | |
| 2218 }); | |
| 2219 | |
| 2220 test( | |
| 2221 'RMW accessor undefined dynamically in class from outside class via typed
var', | |
| 2222 () { | |
| 2223 Helper helper = new Helper(''' | |
| 2224 class A {} | |
| 2225 | |
| 2226 f(A a) { | |
| 2227 a.x += 1; | |
| 2228 } | |
| 2229 '''); | |
| 2230 helper.checkDynamic('a.x', 'a', 'x', isRead: true, isWrite: true); | |
| 2231 }); | |
| 2232 | |
| 2233 test( | |
| 2234 'RMW accessor undefined dynamically in class from outside class via typed
expression', | |
| 2235 () { | |
| 2236 Helper helper = new Helper(''' | |
| 2237 class A {} | |
| 2238 | |
| 2239 A h() => null; | |
| 2240 | |
| 2241 f() { | |
| 2242 h().x += 1; | |
| 2243 } | |
| 2244 '''); | |
| 2245 helper.checkDynamic('h().x', 'h()', 'x', isRead: true, isWrite: true); | |
| 2246 }); | |
| 2247 } | |
| 2248 | |
| 2249 typedef void AccessHandler(Expression node, AccessSemantics semantics); | |
| 2250 | |
| 2251 class Helper { | |
| 2252 final MemoryResourceProvider provider = new MemoryResourceProvider(); | |
| 2253 Source rootSource; | |
| 2254 AnalysisContext context; | |
| 2255 | |
| 2256 Helper(String rootContents) { | |
| 2257 DartSdk sdk = new MockSdk(); | |
| 2258 String rootFile = '/root.dart'; | |
| 2259 File file = provider.newFile(rootFile, rootContents); | |
| 2260 rootSource = file.createSource(); | |
| 2261 context = AnalysisEngine.instance.createAnalysisContext(); | |
| 2262 // Set up the source factory. | |
| 2263 List<UriResolver> uriResolvers = [ | |
| 2264 new ResourceUriResolver(provider), | |
| 2265 new DartUriResolver(sdk)]; | |
| 2266 context.sourceFactory = new SourceFactory(uriResolvers); | |
| 2267 // add the Source | |
| 2268 ChangeSet changeSet = new ChangeSet(); | |
| 2269 changeSet.addedSource(rootSource); | |
| 2270 context.applyChanges(changeSet); | |
| 2271 } | |
| 2272 | |
| 2273 LibraryElement get libraryElement { | |
| 2274 return context.computeLibraryElement(rootSource); | |
| 2275 } | |
| 2276 | |
| 2277 void addFile(String path, String contents) { | |
| 2278 provider.newFile(path, contents); | |
| 2279 } | |
| 2280 | |
| 2281 /** | |
| 2282 * Verify that the node represented by [expectedSource] is classified as | |
| 2283 * a dynamic method invocation. | |
| 2284 */ | |
| 2285 void checkDynamic(String expectedSource, String expectedTarget, | |
| 2286 String expectedName, {bool isRead: false, bool isWrite: false, bool isInvo
ke: | |
| 2287 false}) { | |
| 2288 TestVisitor visitor = new TestVisitor(); | |
| 2289 int count = 0; | |
| 2290 visitor.onAccess = (AstNode node, AccessSemantics semantics) { | |
| 2291 count++; | |
| 2292 expect(node.toSource(), equals(expectedSource)); | |
| 2293 expect(semantics.kind, equals(AccessKind.DYNAMIC)); | |
| 2294 if (expectedTarget == null) { | |
| 2295 expect(semantics.target, isNull); | |
| 2296 } else { | |
| 2297 expect(semantics.target.toSource(), equals(expectedTarget)); | |
| 2298 } | |
| 2299 expect(semantics.identifier.name, equals(expectedName)); | |
| 2300 expect(semantics.element, isNull); | |
| 2301 expect(semantics.classElement, isNull); | |
| 2302 expect(semantics.isRead, equals(isRead)); | |
| 2303 expect(semantics.isWrite, equals(isWrite)); | |
| 2304 expect(semantics.isInvoke, equals(isInvoke)); | |
| 2305 }; | |
| 2306 libraryElement.unit.accept(visitor); | |
| 2307 expect(count, equals(1)); | |
| 2308 } | |
| 2309 | |
| 2310 /** | |
| 2311 * Verify that the node represented by [expectedSource] is classified as | |
| 2312 * a local function invocation. | |
| 2313 */ | |
| 2314 void checkLocalFunction(String expectedSource, String expectedName, | |
| 2315 {bool isRead: false, bool isWrite: false, bool isInvoke: false}) { | |
| 2316 TestVisitor visitor = new TestVisitor(); | |
| 2317 int count = 0; | |
| 2318 visitor.onAccess = (AstNode node, AccessSemantics semantics) { | |
| 2319 count++; | |
| 2320 expect(node.toSource(), equals(expectedSource)); | |
| 2321 expect(semantics.kind, equals(AccessKind.LOCAL_FUNCTION)); | |
| 2322 expect(semantics.identifier.name, equals(expectedName)); | |
| 2323 expect(semantics.element.displayName, equals(expectedName)); | |
| 2324 expect(semantics.classElement, isNull); | |
| 2325 expect(semantics.target, isNull); | |
| 2326 expect(semantics.isRead, equals(isRead)); | |
| 2327 expect(semantics.isWrite, equals(isWrite)); | |
| 2328 expect(semantics.isInvoke, equals(isInvoke)); | |
| 2329 }; | |
| 2330 libraryElement.unit.accept(visitor); | |
| 2331 expect(count, equals(1)); | |
| 2332 } | |
| 2333 | |
| 2334 /** | |
| 2335 * Verify that the node represented by [expectedSource] is classified as | |
| 2336 * a local variable access. | |
| 2337 */ | |
| 2338 void checkLocalVariable(String expectedSource, String expectedName, | |
| 2339 {bool isRead: false, bool isWrite: false, bool isInvoke: false}) { | |
| 2340 TestVisitor visitor = new TestVisitor(); | |
| 2341 int count = 0; | |
| 2342 visitor.onAccess = (AstNode node, AccessSemantics semantics) { | |
| 2343 count++; | |
| 2344 expect(node.toSource(), equals(expectedSource)); | |
| 2345 expect(semantics.kind, equals(AccessKind.LOCAL_VARIABLE)); | |
| 2346 expect(semantics.element.name, equals(expectedName)); | |
| 2347 expect(semantics.classElement, isNull); | |
| 2348 expect(semantics.target, isNull); | |
| 2349 expect(semantics.isRead, equals(isRead)); | |
| 2350 expect(semantics.isWrite, equals(isWrite)); | |
| 2351 expect(semantics.isInvoke, equals(isInvoke)); | |
| 2352 }; | |
| 2353 libraryElement.unit.accept(visitor); | |
| 2354 expect(count, equals(1)); | |
| 2355 } | |
| 2356 | |
| 2357 /** | |
| 2358 * Verify that the node represented by [expectedSource] is classified as a | |
| 2359 * parameter access. | |
| 2360 */ | |
| 2361 void checkParameter(String expectedSource, String expectedName, {bool isRead: | |
| 2362 false, bool isWrite: false, bool isInvoke: false}) { | |
| 2363 TestVisitor visitor = new TestVisitor(); | |
| 2364 int count = 0; | |
| 2365 visitor.onAccess = (AstNode node, AccessSemantics semantics) { | |
| 2366 count++; | |
| 2367 expect(node.toSource(), equals(expectedSource)); | |
| 2368 expect(semantics.kind, equals(AccessKind.PARAMETER)); | |
| 2369 expect(semantics.element.name, equals(expectedName)); | |
| 2370 expect(semantics.classElement, isNull); | |
| 2371 expect(semantics.target, isNull); | |
| 2372 expect(semantics.isRead, equals(isRead)); | |
| 2373 expect(semantics.isWrite, equals(isWrite)); | |
| 2374 expect(semantics.isInvoke, equals(isInvoke)); | |
| 2375 }; | |
| 2376 libraryElement.unit.accept(visitor); | |
| 2377 expect(count, equals(1)); | |
| 2378 } | |
| 2379 | |
| 2380 /** | |
| 2381 * Verify that the node represented by [expectedSource] is classified as | |
| 2382 * a static field element reference. | |
| 2383 */ | |
| 2384 void checkStaticField(String expectedSource, String expectedClass, | |
| 2385 String expectedName, {bool isRead: false, bool isWrite: false, bool isInvo
ke: | |
| 2386 false}) { | |
| 2387 TestVisitor visitor = new TestVisitor(); | |
| 2388 int count = 0; | |
| 2389 visitor.onAccess = (Expression node, AccessSemantics semantics) { | |
| 2390 count++; | |
| 2391 expect(node.toSource(), equals(expectedSource)); | |
| 2392 expect(semantics.kind, equals(AccessKind.STATIC_FIELD)); | |
| 2393 expect(semantics.identifier.name, equals(expectedName)); | |
| 2394 expect(semantics.element.displayName, equals(expectedName)); | |
| 2395 if (expectedClass == null) { | |
| 2396 expect(semantics.classElement, isNull); | |
| 2397 } else { | |
| 2398 expect(semantics.classElement, isNotNull); | |
| 2399 expect(semantics.classElement.displayName, equals(expectedClass)); | |
| 2400 } | |
| 2401 expect(semantics.target, isNull); | |
| 2402 expect(semantics.isRead, equals(isRead)); | |
| 2403 expect(semantics.isWrite, equals(isWrite)); | |
| 2404 expect(semantics.isInvoke, equals(isInvoke)); | |
| 2405 }; | |
| 2406 libraryElement.unit.accept(visitor); | |
| 2407 expect(count, equals(1)); | |
| 2408 } | |
| 2409 | |
| 2410 /** | |
| 2411 * Verify that the node represented by [expectedSource] is classified as | |
| 2412 * a static method. | |
| 2413 */ | |
| 2414 void checkStaticMethod(String expectedSource, String expectedClass, | |
| 2415 String expectedName, bool defined, {bool isRead: false, bool isWrite: fals
e, | |
| 2416 bool isInvoke: false}) { | |
| 2417 TestVisitor visitor = new TestVisitor(); | |
| 2418 int count = 0; | |
| 2419 visitor.onAccess = (AstNode node, AccessSemantics semantics) { | |
| 2420 count++; | |
| 2421 expect(node.toSource(), equals(expectedSource)); | |
| 2422 expect(semantics.kind, equals(AccessKind.STATIC_METHOD)); | |
| 2423 expect(semantics.identifier.name, equals(expectedName)); | |
| 2424 if (expectedClass == null) { | |
| 2425 expect(semantics.classElement, isNull); | |
| 2426 if (defined) { | |
| 2427 expect(semantics.element, new isInstanceOf<FunctionElement>()); | |
| 2428 } | |
| 2429 } else { | |
| 2430 expect(semantics.classElement, isNotNull); | |
| 2431 expect(semantics.classElement.displayName, equals(expectedClass)); | |
| 2432 if (defined) { | |
| 2433 expect(semantics.element, new isInstanceOf<MethodElement>()); | |
| 2434 } | |
| 2435 } | |
| 2436 if (defined) { | |
| 2437 expect(semantics.element.displayName, equals(expectedName)); | |
| 2438 } else { | |
| 2439 expect(semantics.element, isNull); | |
| 2440 } | |
| 2441 expect(semantics.target, isNull); | |
| 2442 expect(semantics.isRead, equals(isRead)); | |
| 2443 expect(semantics.isWrite, equals(isWrite)); | |
| 2444 expect(semantics.isInvoke, equals(isInvoke)); | |
| 2445 }; | |
| 2446 libraryElement.unit.accept(visitor); | |
| 2447 expect(count, equals(1)); | |
| 2448 } | |
| 2449 | |
| 2450 /** | |
| 2451 * Verify that the node represented by [expectedSource] is classified as | |
| 2452 * a static property access. | |
| 2453 */ | |
| 2454 void checkStaticProperty(String expectedSource, String expectedClass, | |
| 2455 String expectedName, bool defined, {bool isRead: false, bool isWrite: fals
e, | |
| 2456 bool isInvoke: false}) { | |
| 2457 TestVisitor visitor = new TestVisitor(); | |
| 2458 int count = 0; | |
| 2459 visitor.onAccess = (Expression node, AccessSemantics semantics) { | |
| 2460 count++; | |
| 2461 expect(node.toSource(), equals(expectedSource)); | |
| 2462 expect(semantics.kind, equals(AccessKind.STATIC_PROPERTY)); | |
| 2463 expect(semantics.identifier.name, equals(expectedName)); | |
| 2464 if (expectedClass == null) { | |
| 2465 expect(semantics.classElement, isNull); | |
| 2466 } else { | |
| 2467 expect(semantics.classElement, isNotNull); | |
| 2468 expect(semantics.classElement.displayName, equals(expectedClass)); | |
| 2469 } | |
| 2470 if (defined) { | |
| 2471 expect(semantics.element.displayName, equals(expectedName)); | |
| 2472 } else { | |
| 2473 expect(semantics.element, isNull); | |
| 2474 } | |
| 2475 expect(semantics.target, isNull); | |
| 2476 expect(semantics.isRead, equals(isRead)); | |
| 2477 expect(semantics.isWrite, equals(isWrite)); | |
| 2478 expect(semantics.isInvoke, equals(isInvoke)); | |
| 2479 }; | |
| 2480 libraryElement.unit.accept(visitor); | |
| 2481 expect(count, equals(1)); | |
| 2482 } | |
| 2483 | |
| 2484 /** | |
| 2485 * Verify that the node represented by [expectedSource] is classified as a | |
| 2486 * reference to a toplevel class or a type parameter. | |
| 2487 */ | |
| 2488 void checkTypeReference(String expectedSource, String expectedName, | |
| 2489 AccessKind expectedKind, {bool isRead: false, bool isInvoke: false}) { | |
| 2490 TestVisitor visitor = new TestVisitor(); | |
| 2491 int count = 0; | |
| 2492 visitor.onAccess = (AstNode node, AccessSemantics semantics) { | |
| 2493 count++; | |
| 2494 expect(node.toSource(), equals(expectedSource)); | |
| 2495 expect(semantics.kind, equals(expectedKind)); | |
| 2496 expect(semantics.element.name, equals(expectedName)); | |
| 2497 expect(semantics.classElement, isNull); | |
| 2498 expect(semantics.target, isNull); | |
| 2499 expect(semantics.isRead, equals(isRead)); | |
| 2500 expect(semantics.isWrite, isFalse); | |
| 2501 expect(semantics.isInvoke, equals(isInvoke)); | |
| 2502 }; | |
| 2503 libraryElement.unit.accept(visitor); | |
| 2504 expect(count, equals(1)); | |
| 2505 } | |
| 2506 } | |
| 2507 | |
| 2508 /** | |
| 2509 * Visitor class used to run the tests. | |
| 2510 */ | |
| 2511 class TestVisitor extends RecursiveAstVisitor { | |
| 2512 AccessHandler onAccess; | |
| 2513 | |
| 2514 @override | |
| 2515 visitMethodInvocation(MethodInvocation node) { | |
| 2516 onAccess(node, node.accept(ACCESS_SEMANTICS_VISITOR)); | |
| 2517 } | |
| 2518 | |
| 2519 @override | |
| 2520 visitPrefixedIdentifier(PrefixedIdentifier node) { | |
| 2521 onAccess(node, node.accept(ACCESS_SEMANTICS_VISITOR)); | |
| 2522 } | |
| 2523 | |
| 2524 @override | |
| 2525 visitPropertyAccess(PropertyAccess node) { | |
| 2526 onAccess(node, node.accept(ACCESS_SEMANTICS_VISITOR)); | |
| 2527 } | |
| 2528 | |
| 2529 @override | |
| 2530 visitSimpleIdentifier(SimpleIdentifier node) { | |
| 2531 AccessSemantics semantics = node.accept(ACCESS_SEMANTICS_VISITOR); | |
| 2532 if (semantics != null) { | |
| 2533 onAccess(node, semantics); | |
| 2534 } | |
| 2535 } | |
| 2536 } | |
| OLD | NEW |