| 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 library test.services.src.index.dart_index_contributor; | |
| 6 | |
| 7 import 'package:analysis_services/index/index.dart'; | |
| 8 import 'package:analysis_services/index/index_store.dart'; | |
| 9 import 'package:analysis_services/src/index/index_contributor.dart'; | |
| 10 import 'package:analysis_testing/abstract_single_unit.dart'; | |
| 11 import 'package:analysis_testing/reflective_tests.dart'; | |
| 12 import 'package:analyzer/src/generated/ast.dart'; | |
| 13 import 'package:analyzer/src/generated/element.dart'; | |
| 14 import 'package:analyzer/src/generated/source.dart'; | |
| 15 import 'package:typed_mock/typed_mock.dart'; | |
| 16 import 'package:unittest/unittest.dart'; | |
| 17 | |
| 18 | |
| 19 main() { | |
| 20 groupSep = ' | '; | |
| 21 runReflectiveTests(DartUnitContributorTest); | |
| 22 } | |
| 23 | |
| 24 | |
| 25 /** | |
| 26 * Returns `true` if the [actual] location the same properties as [expected]. | |
| 27 */ | |
| 28 bool _equalsLocation(Location actual, ExpectedLocation expected) { | |
| 29 return _equalsLocationProperties( | |
| 30 actual, | |
| 31 expected.element, | |
| 32 expected.offset, | |
| 33 expected.length, | |
| 34 expected.isQualified, | |
| 35 expected.isResolved); | |
| 36 } | |
| 37 | |
| 38 | |
| 39 /** | |
| 40 * Returns `true` if the [actual] location the expected properties. | |
| 41 */ | |
| 42 bool _equalsLocationProperties(Location actual, Element expectedElement, | |
| 43 int expectedOffset, int expectedLength, bool isQualified, bool isResolved) { | |
| 44 return expectedElement == actual.element && | |
| 45 expectedOffset == actual.offset && | |
| 46 expectedLength == actual.length && | |
| 47 isQualified == actual.isQualified && | |
| 48 isResolved == actual.isResolved; | |
| 49 } | |
| 50 | |
| 51 | |
| 52 bool _equalsRecordedRelation(RecordedRelation recordedRelation, | |
| 53 Element expectedElement, Relationship expectedRelationship, | |
| 54 ExpectedLocation expectedLocation) { | |
| 55 return expectedElement == recordedRelation.element && | |
| 56 expectedRelationship == recordedRelation.relationship && | |
| 57 (expectedLocation == null || | |
| 58 _equalsLocation(recordedRelation.location, expectedLocation)); | |
| 59 } | |
| 60 | |
| 61 | |
| 62 @ReflectiveTestCase() | |
| 63 class DartUnitContributorTest extends AbstractSingleUnitTest { | |
| 64 IndexStore store = new MockIndexStore(); | |
| 65 List<RecordedRelation> recordedRelations = <RecordedRelation>[]; | |
| 66 | |
| 67 CompilationUnitElement importedUnit({int index: 0}) { | |
| 68 List<ImportElement> imports = testLibraryElement.imports; | |
| 69 return imports[index].importedLibrary.definingCompilationUnit; | |
| 70 } | |
| 71 | |
| 72 void setUp() { | |
| 73 super.setUp(); | |
| 74 when(store.aboutToIndexDart(context, anyObject)).thenReturn(true); | |
| 75 when( | |
| 76 store.recordRelationship( | |
| 77 anyObject, | |
| 78 anyObject, | |
| 79 anyObject)).thenInvoke( | |
| 80 (Element element, Relationship relationship, Location location)
{ | |
| 81 recordedRelations.add( | |
| 82 new RecordedRelation(element, relationship, location)); | |
| 83 }); | |
| 84 } | |
| 85 | |
| 86 void test_NameElement_field() { | |
| 87 _indexTestUnit(''' | |
| 88 class A { | |
| 89 int field; | |
| 90 } | |
| 91 main(A a, p) { | |
| 92 print(a.field); // r | |
| 93 print(p.field); // ur | |
| 94 { | |
| 95 var field = 42; | |
| 96 print(field); // not a member | |
| 97 } | |
| 98 } | |
| 99 '''); | |
| 100 // prepare elements | |
| 101 Element mainElement = findElement('main'); | |
| 102 FieldElement fieldElement = findElement('field'); | |
| 103 Element nameElement = new NameElement('field'); | |
| 104 // verify | |
| 105 _assertRecordedRelation( | |
| 106 nameElement, | |
| 107 IndexConstants.NAME_IS_DEFINED_BY, | |
| 108 _expectedLocation(fieldElement, 'field;')); | |
| 109 _assertRecordedRelation( | |
| 110 nameElement, | |
| 111 IndexConstants.IS_READ_BY, | |
| 112 _expectedLocationQ(mainElement, 'field); // r')); | |
| 113 _assertRecordedRelation( | |
| 114 nameElement, | |
| 115 IndexConstants.IS_READ_BY, | |
| 116 _expectedLocationQU(mainElement, 'field); // ur')); | |
| 117 _assertNoRecordedRelation( | |
| 118 nameElement, | |
| 119 IndexConstants.IS_READ_BY, | |
| 120 _expectedLocation(mainElement, 'field); // not a member')); | |
| 121 } | |
| 122 | |
| 123 void test_NameElement_isDefinedBy_localVariable_inForEach() { | |
| 124 _indexTestUnit(''' | |
| 125 class A { | |
| 126 main() { | |
| 127 for (int test in []) { | |
| 128 } | |
| 129 } | |
| 130 } | |
| 131 '''); | |
| 132 // prepare elements | |
| 133 Element mainElement = findElement('main'); | |
| 134 LocalVariableElement testElement = findElement('test'); | |
| 135 Element nameElement = new NameElement('test'); | |
| 136 // verify | |
| 137 _assertRecordedRelation( | |
| 138 nameElement, | |
| 139 IndexConstants.NAME_IS_DEFINED_BY, | |
| 140 _expectedLocation(testElement, 'test in []')); | |
| 141 } | |
| 142 | |
| 143 void test_NameElement_method() { | |
| 144 _indexTestUnit(''' | |
| 145 class A { | |
| 146 method() {} | |
| 147 } | |
| 148 main(A a, p) { | |
| 149 a.method(); // r | |
| 150 p.method(); // ur | |
| 151 } | |
| 152 '''); | |
| 153 // prepare elements | |
| 154 Element mainElement = findElement('main'); | |
| 155 MethodElement methodElement = findElement('method'); | |
| 156 Element nameElement = new NameElement('method'); | |
| 157 // verify | |
| 158 _assertRecordedRelation( | |
| 159 nameElement, | |
| 160 IndexConstants.NAME_IS_DEFINED_BY, | |
| 161 _expectedLocation(methodElement, 'method() {}')); | |
| 162 _assertRecordedRelation( | |
| 163 nameElement, | |
| 164 IndexConstants.IS_INVOKED_BY, | |
| 165 _expectedLocationQ(mainElement, 'method(); // r')); | |
| 166 _assertRecordedRelation( | |
| 167 nameElement, | |
| 168 IndexConstants.IS_INVOKED_BY, | |
| 169 _expectedLocationQU(mainElement, 'method(); // ur')); | |
| 170 } | |
| 171 | |
| 172 void test_NameElement_operator_resolved() { | |
| 173 _indexTestUnit(''' | |
| 174 class A { | |
| 175 operator +(o) {} | |
| 176 operator -(o) {} | |
| 177 operator ~() {} | |
| 178 operator ==(o) {} | |
| 179 } | |
| 180 main(A a) { | |
| 181 a + 5; | |
| 182 a += 5; | |
| 183 a == 5; | |
| 184 ++a; | |
| 185 --a; | |
| 186 ~a; | |
| 187 a++; | |
| 188 a--; | |
| 189 } | |
| 190 '''); | |
| 191 // prepare elements | |
| 192 Element mainElement = findElement('main'); | |
| 193 // binary | |
| 194 _assertRecordedRelation( | |
| 195 new NameElement('+'), | |
| 196 IndexConstants.IS_INVOKED_BY, | |
| 197 _expectedLocationQ(mainElement, '+ 5', length: 1)); | |
| 198 _assertRecordedRelation( | |
| 199 new NameElement('+'), | |
| 200 IndexConstants.IS_INVOKED_BY, | |
| 201 _expectedLocationQ(mainElement, '+= 5', length: 2)); | |
| 202 _assertRecordedRelation( | |
| 203 new NameElement('=='), | |
| 204 IndexConstants.IS_INVOKED_BY, | |
| 205 _expectedLocationQ(mainElement, '== 5', length: 2)); | |
| 206 // prefix | |
| 207 _assertRecordedRelation( | |
| 208 new NameElement('+'), | |
| 209 IndexConstants.IS_INVOKED_BY, | |
| 210 _expectedLocationQ(mainElement, '++a', length: 2)); | |
| 211 _assertRecordedRelation( | |
| 212 new NameElement('-'), | |
| 213 IndexConstants.IS_INVOKED_BY, | |
| 214 _expectedLocationQ(mainElement, '--a', length: 2)); | |
| 215 _assertRecordedRelation( | |
| 216 new NameElement('~'), | |
| 217 IndexConstants.IS_INVOKED_BY, | |
| 218 _expectedLocationQ(mainElement, '~a', length: 1)); | |
| 219 // postfix | |
| 220 _assertRecordedRelation( | |
| 221 new NameElement('+'), | |
| 222 IndexConstants.IS_INVOKED_BY, | |
| 223 _expectedLocationQ(mainElement, '++;', length: 2)); | |
| 224 _assertRecordedRelation( | |
| 225 new NameElement('-'), | |
| 226 IndexConstants.IS_INVOKED_BY, | |
| 227 _expectedLocationQ(mainElement, '--;', length: 2)); | |
| 228 } | |
| 229 | |
| 230 | |
| 231 void test_NameElement_operator_unresolved() { | |
| 232 _indexTestUnit(''' | |
| 233 class A { | |
| 234 operator +(o) {} | |
| 235 operator -(o) {} | |
| 236 operator ~() {} | |
| 237 operator ==(o) {} | |
| 238 } | |
| 239 main(a) { | |
| 240 a + 5; | |
| 241 a += 5; | |
| 242 a == 5; | |
| 243 ++a; | |
| 244 --a; | |
| 245 ~a; | |
| 246 a++; | |
| 247 a--; | |
| 248 } | |
| 249 '''); | |
| 250 // prepare elements | |
| 251 Element mainElement = findElement('main'); | |
| 252 // binary | |
| 253 _assertRecordedRelation( | |
| 254 new NameElement('+'), | |
| 255 IndexConstants.IS_INVOKED_BY, | |
| 256 _expectedLocationQU(mainElement, '+ 5', length: 1)); | |
| 257 _assertRecordedRelation( | |
| 258 new NameElement('+'), | |
| 259 IndexConstants.IS_INVOKED_BY, | |
| 260 _expectedLocationQU(mainElement, '+= 5', length: 2)); | |
| 261 _assertRecordedRelation( | |
| 262 new NameElement('=='), | |
| 263 IndexConstants.IS_INVOKED_BY, | |
| 264 _expectedLocationQU(mainElement, '== 5', length: 2)); | |
| 265 // prefix | |
| 266 _assertRecordedRelation( | |
| 267 new NameElement('+'), | |
| 268 IndexConstants.IS_INVOKED_BY, | |
| 269 _expectedLocationQU(mainElement, '++a', length: 2)); | |
| 270 _assertRecordedRelation( | |
| 271 new NameElement('-'), | |
| 272 IndexConstants.IS_INVOKED_BY, | |
| 273 _expectedLocationQU(mainElement, '--a', length: 2)); | |
| 274 _assertRecordedRelation( | |
| 275 new NameElement('~'), | |
| 276 IndexConstants.IS_INVOKED_BY, | |
| 277 _expectedLocationQU(mainElement, '~a', length: 1)); | |
| 278 // postfix | |
| 279 _assertRecordedRelation( | |
| 280 new NameElement('+'), | |
| 281 IndexConstants.IS_INVOKED_BY, | |
| 282 _expectedLocationQU(mainElement, '++;', length: 2)); | |
| 283 _assertRecordedRelation( | |
| 284 new NameElement('-'), | |
| 285 IndexConstants.IS_INVOKED_BY, | |
| 286 _expectedLocationQU(mainElement, '--;', length: 2)); | |
| 287 } | |
| 288 | |
| 289 void test_definesClass() { | |
| 290 _indexTestUnit('class A {}'); | |
| 291 // prepare elements | |
| 292 ClassElement classElement = findElement("A"); | |
| 293 // verify | |
| 294 _assertDefinesTopLevelElement( | |
| 295 IndexConstants.DEFINES, | |
| 296 _expectedLocation(classElement, 'A {}')); | |
| 297 } | |
| 298 | |
| 299 void test_definesClassAlias() { | |
| 300 _indexTestUnit(''' | |
| 301 class Mix {} | |
| 302 class MyClass = Object with Mix;'''); | |
| 303 // prepare elements | |
| 304 Element classElement = findElement("MyClass"); | |
| 305 // verify | |
| 306 _assertDefinesTopLevelElement( | |
| 307 IndexConstants.DEFINES, | |
| 308 _expectedLocation(classElement, 'MyClass =')); | |
| 309 } | |
| 310 | |
| 311 void test_definesFunction() { | |
| 312 _indexTestUnit('myFunction() {}'); | |
| 313 // prepare elements | |
| 314 FunctionElement functionElement = findElement("myFunction"); | |
| 315 // verify | |
| 316 _assertDefinesTopLevelElement( | |
| 317 IndexConstants.DEFINES, | |
| 318 _expectedLocation(functionElement, 'myFunction() {}')); | |
| 319 } | |
| 320 | |
| 321 | |
| 322 void test_definesFunctionType() { | |
| 323 _indexTestUnit('typedef MyFunction(int p);'); | |
| 324 // prepare elements | |
| 325 FunctionTypeAliasElement typeAliasElement = findElement("MyFunction"); | |
| 326 // verify | |
| 327 _assertDefinesTopLevelElement( | |
| 328 IndexConstants.DEFINES, | |
| 329 _expectedLocation(typeAliasElement, 'MyFunction(int p);')); | |
| 330 } | |
| 331 | |
| 332 void test_definesVariable() { | |
| 333 _indexTestUnit('var myVar = 42;'); | |
| 334 // prepare elements | |
| 335 VariableElement varElement = findElement("myVar"); | |
| 336 // verify | |
| 337 _assertDefinesTopLevelElement( | |
| 338 IndexConstants.DEFINES, | |
| 339 _expectedLocation(varElement, 'myVar = 42;')); | |
| 340 } | |
| 341 | |
| 342 void test_forIn() { | |
| 343 _indexTestUnit(''' | |
| 344 main() { | |
| 345 for (var v in []) { | |
| 346 } | |
| 347 }'''); | |
| 348 // prepare elements | |
| 349 Element mainElement = findElement("main"); | |
| 350 VariableElement variableElement = findElement("v"); | |
| 351 // verify | |
| 352 _assertNoRecordedRelation( | |
| 353 variableElement, | |
| 354 IndexConstants.IS_READ_BY, | |
| 355 _expectedLocation(mainElement, 'v in []')); | |
| 356 } | |
| 357 | |
| 358 void test_isDefinedBy_ConstructorElement() { | |
| 359 _indexTestUnit(''' | |
| 360 class A { | |
| 361 A() {} | |
| 362 A.foo() {} | |
| 363 }'''); | |
| 364 // prepare elements | |
| 365 ClassElement classA = findElement("A"); | |
| 366 ConstructorElement consA = | |
| 367 findNodeElementAtString("A()", (node) => node is ConstructorDeclaration)
; | |
| 368 ConstructorElement consA_foo = | |
| 369 findNodeElementAtString("A.foo()", (node) => node is ConstructorDeclarat
ion); | |
| 370 // verify | |
| 371 _assertRecordedRelation( | |
| 372 consA, | |
| 373 IndexConstants.NAME_IS_DEFINED_BY, | |
| 374 _expectedLocation(classA, '() {}')); | |
| 375 _assertRecordedRelation( | |
| 376 consA_foo, | |
| 377 IndexConstants.NAME_IS_DEFINED_BY, | |
| 378 _expectedLocation(classA, '.foo() {}', length: 4)); | |
| 379 } | |
| 380 | |
| 381 void test_isDefinedBy_NameElement_method() { | |
| 382 _indexTestUnit(''' | |
| 383 class A { | |
| 384 m() {} | |
| 385 }'''); | |
| 386 // prepare elements | |
| 387 Element methodElement = findElement("m"); | |
| 388 Element nameElement = new NameElement("m"); | |
| 389 // verify | |
| 390 _assertRecordedRelation( | |
| 391 nameElement, | |
| 392 IndexConstants.NAME_IS_DEFINED_BY, | |
| 393 _expectedLocation(methodElement, 'm() {}')); | |
| 394 } | |
| 395 | |
| 396 void test_isDefinedBy_NameElement_operator() { | |
| 397 _indexTestUnit(''' | |
| 398 class A { | |
| 399 operator +(o) {} | |
| 400 }'''); | |
| 401 // prepare elements | |
| 402 Element methodElement = findElement("+"); | |
| 403 Element nameElement = new NameElement("+"); | |
| 404 // verify | |
| 405 _assertRecordedRelation( | |
| 406 nameElement, | |
| 407 IndexConstants.NAME_IS_DEFINED_BY, | |
| 408 _expectedLocation(methodElement, '+(o) {}', length: 1)); | |
| 409 } | |
| 410 | |
| 411 | |
| 412 void test_isExtendedBy_ClassDeclaration() { | |
| 413 _indexTestUnit(''' | |
| 414 class A {} // 1 | |
| 415 class B extends A {} // 2 | |
| 416 '''); | |
| 417 // prepare elements | |
| 418 ClassElement classElementA = findElement("A"); | |
| 419 ClassElement classElementB = findElement("B"); | |
| 420 // verify | |
| 421 _assertRecordedRelation( | |
| 422 classElementA, | |
| 423 IndexConstants.IS_EXTENDED_BY, | |
| 424 _expectedLocation(classElementB, 'A {} // 2')); | |
| 425 } | |
| 426 | |
| 427 void test_isExtendedBy_ClassDeclaration_Object() { | |
| 428 _indexTestUnit(''' | |
| 429 class A {} // 1 | |
| 430 '''); | |
| 431 // prepare elements | |
| 432 ClassElement classElementA = findElement("A"); | |
| 433 ClassElement classElementObject = classElementA.supertype.element; | |
| 434 // verify | |
| 435 _assertRecordedRelation( | |
| 436 classElementObject, | |
| 437 IndexConstants.IS_EXTENDED_BY, | |
| 438 _expectedLocation(classElementA, 'A {}', length: 0)); | |
| 439 } | |
| 440 | |
| 441 | |
| 442 void test_isExtendedBy_ClassTypeAlias() { | |
| 443 _indexTestUnit(''' | |
| 444 class A {} // 1 | |
| 445 class B {} // 2 | |
| 446 class C = A with B; // 3 | |
| 447 '''); | |
| 448 // prepare elements | |
| 449 ClassElement classElementA = findElement("A"); | |
| 450 ClassElement classElementC = findElement("C"); | |
| 451 // verify | |
| 452 _assertRecordedRelation( | |
| 453 classElementA, | |
| 454 IndexConstants.IS_EXTENDED_BY, | |
| 455 _expectedLocation(classElementC, 'A with')); | |
| 456 } | |
| 457 | |
| 458 void test_isImplementedBy_ClassDeclaration() { | |
| 459 _indexTestUnit(''' | |
| 460 class A {} // 1 | |
| 461 class B implements A {} // 2 | |
| 462 '''); | |
| 463 // prepare elements | |
| 464 ClassElement classElementA = findElement("A"); | |
| 465 ClassElement classElementB = findElement("B"); | |
| 466 // verify | |
| 467 _assertRecordedRelation( | |
| 468 classElementA, | |
| 469 IndexConstants.IS_IMPLEMENTED_BY, | |
| 470 _expectedLocation(classElementB, 'A {} // 2')); | |
| 471 } | |
| 472 | |
| 473 void test_isImplementedBy_ClassTypeAlias() { | |
| 474 _indexTestUnit(''' | |
| 475 class A {} // 1 | |
| 476 class B {} // 2 | |
| 477 class C = Object with A implements B; // 3 | |
| 478 '''); | |
| 479 // prepare elements | |
| 480 ClassElement classElementB = findElement("B"); | |
| 481 ClassElement classElementC = findElement("C"); | |
| 482 // verify | |
| 483 _assertRecordedRelation( | |
| 484 classElementB, | |
| 485 IndexConstants.IS_IMPLEMENTED_BY, | |
| 486 _expectedLocation(classElementC, 'B; // 3')); | |
| 487 } | |
| 488 | |
| 489 void test_isInvokedBy_FieldElement() { | |
| 490 _indexTestUnit(''' | |
| 491 class A { | |
| 492 var field; | |
| 493 main() { | |
| 494 this.field(); // q | |
| 495 field(); // nq | |
| 496 } | |
| 497 }'''); | |
| 498 // prepare elements | |
| 499 Element mainElement = findElement("main"); | |
| 500 FieldElement fieldElement = findElement("field"); | |
| 501 PropertyAccessorElement getterElement = fieldElement.getter; | |
| 502 // verify | |
| 503 _assertRecordedRelation( | |
| 504 getterElement, | |
| 505 IndexConstants.IS_INVOKED_BY, | |
| 506 _expectedLocationQ(mainElement, 'field(); // q')); | |
| 507 _assertRecordedRelation( | |
| 508 getterElement, | |
| 509 IndexConstants.IS_INVOKED_BY, | |
| 510 _expectedLocation(mainElement, 'field(); // nq')); | |
| 511 } | |
| 512 | |
| 513 void test_isInvokedBy_FunctionElement() { | |
| 514 addSource('/lib.dart', ''' | |
| 515 library lib; | |
| 516 foo() {} | |
| 517 '''); | |
| 518 _indexTestUnit(''' | |
| 519 import 'lib.dart'; | |
| 520 import 'lib.dart' as pref; | |
| 521 main() { | |
| 522 pref.foo(); // q | |
| 523 foo(); // nq | |
| 524 }'''); | |
| 525 // prepare elements | |
| 526 Element mainElement = findElement("main"); | |
| 527 FunctionElement functionElement = importedUnit().functions[0]; | |
| 528 // verify | |
| 529 _assertRecordedRelation( | |
| 530 functionElement, | |
| 531 IndexConstants.IS_INVOKED_BY, | |
| 532 _expectedLocation(mainElement, 'foo(); // q')); | |
| 533 _assertRecordedRelation( | |
| 534 functionElement, | |
| 535 IndexConstants.IS_INVOKED_BY, | |
| 536 _expectedLocation(mainElement, 'foo(); // nq')); | |
| 537 } | |
| 538 | |
| 539 void test_isInvokedBy_LocalVariableElement() { | |
| 540 _indexTestUnit(''' | |
| 541 main() { | |
| 542 var v; | |
| 543 v(); | |
| 544 }'''); | |
| 545 // prepare elements | |
| 546 Element mainElement = findElement("main"); | |
| 547 Element element = findElement("v"); | |
| 548 // verify | |
| 549 _assertRecordedRelation( | |
| 550 element, | |
| 551 IndexConstants.IS_INVOKED_BY, | |
| 552 _expectedLocation(mainElement, 'v();')); | |
| 553 } | |
| 554 | |
| 555 void test_isInvokedBy_MethodElement() { | |
| 556 _indexTestUnit(''' | |
| 557 class A { | |
| 558 foo() {} | |
| 559 main() { | |
| 560 this.foo(); // q | |
| 561 foo(); // nq | |
| 562 } | |
| 563 }'''); | |
| 564 // prepare elements | |
| 565 Element mainElement = findElement("main"); | |
| 566 Element methodElement = findElement("foo"); | |
| 567 // verify | |
| 568 _assertRecordedRelation( | |
| 569 methodElement, | |
| 570 IndexConstants.IS_INVOKED_BY, | |
| 571 _expectedLocationQ(mainElement, 'foo(); // q')); | |
| 572 _assertRecordedRelation( | |
| 573 methodElement, | |
| 574 IndexConstants.IS_INVOKED_BY, | |
| 575 _expectedLocation(mainElement, 'foo(); // nq')); | |
| 576 } | |
| 577 | |
| 578 void test_isInvokedBy_MethodElement_propagatedType() { | |
| 579 _indexTestUnit(''' | |
| 580 class A { | |
| 581 foo() {} | |
| 582 } | |
| 583 main() { | |
| 584 var a = new A(); | |
| 585 a.foo(); | |
| 586 } | |
| 587 '''); | |
| 588 // prepare elements | |
| 589 Element mainElement = findElement("main"); | |
| 590 Element methodElement = findElement("foo"); | |
| 591 // verify | |
| 592 _assertRecordedRelation( | |
| 593 methodElement, | |
| 594 IndexConstants.IS_INVOKED_BY, | |
| 595 _expectedLocationQ(mainElement, 'foo();')); | |
| 596 } | |
| 597 | |
| 598 void test_isInvokedBy_ParameterElement() { | |
| 599 _indexTestUnit(''' | |
| 600 main(p()) { | |
| 601 p(); | |
| 602 }'''); | |
| 603 // prepare elements | |
| 604 Element mainElement = findElement("main"); | |
| 605 Element element = findElement("p"); | |
| 606 // verify | |
| 607 _assertRecordedRelation( | |
| 608 element, | |
| 609 IndexConstants.IS_INVOKED_BY, | |
| 610 _expectedLocation(mainElement, 'p();')); | |
| 611 } | |
| 612 | |
| 613 void test_isInvokedBy_operator_binary() { | |
| 614 _indexTestUnit(''' | |
| 615 class A { | |
| 616 operator +(other) => this; | |
| 617 } | |
| 618 main(A a) { | |
| 619 print(a + 1); | |
| 620 a += 2; | |
| 621 ++a; | |
| 622 a++; | |
| 623 } | |
| 624 '''); | |
| 625 // prepare elements | |
| 626 MethodElement element = findElement('+'); | |
| 627 Element mainElement = findElement('main'); | |
| 628 // verify | |
| 629 _assertRecordedRelation( | |
| 630 element, | |
| 631 IndexConstants.IS_INVOKED_BY, | |
| 632 _expectedLocationQ(mainElement, '+ 1', length: 1)); | |
| 633 _assertRecordedRelation( | |
| 634 element, | |
| 635 IndexConstants.IS_INVOKED_BY, | |
| 636 _expectedLocationQ(mainElement, '+= 2', length: 2)); | |
| 637 _assertRecordedRelation( | |
| 638 element, | |
| 639 IndexConstants.IS_INVOKED_BY, | |
| 640 _expectedLocationQ(mainElement, '++a;', length: 2)); | |
| 641 _assertRecordedRelation( | |
| 642 element, | |
| 643 IndexConstants.IS_INVOKED_BY, | |
| 644 _expectedLocationQ(mainElement, '++;', length: 2)); | |
| 645 } | |
| 646 | |
| 647 void test_isInvokedBy_operator_index() { | |
| 648 _indexTestUnit(''' | |
| 649 class A { | |
| 650 operator [](i) => null; | |
| 651 operator []=(i, v) {} | |
| 652 } | |
| 653 main(A a) { | |
| 654 print(a[0]); | |
| 655 a[1] = 42; | |
| 656 } | |
| 657 '''); | |
| 658 // prepare elements | |
| 659 MethodElement readElement = findElement("[]"); | |
| 660 MethodElement writeElement = findElement("[]="); | |
| 661 Element mainElement = findElement('main'); | |
| 662 // verify | |
| 663 _assertRecordedRelation( | |
| 664 readElement, | |
| 665 IndexConstants.IS_INVOKED_BY, | |
| 666 _expectedLocationQ(mainElement, '[0]', length: 1)); | |
| 667 _assertRecordedRelation( | |
| 668 writeElement, | |
| 669 IndexConstants.IS_INVOKED_BY, | |
| 670 _expectedLocationQ(mainElement, '[1] =', length: 1)); | |
| 671 } | |
| 672 | |
| 673 void test_isInvokedBy_operator_prefix() { | |
| 674 _indexTestUnit(''' | |
| 675 class A { | |
| 676 A operator ~() => this; | |
| 677 } | |
| 678 main(A a) { | |
| 679 print(~a); | |
| 680 } | |
| 681 '''); | |
| 682 // prepare elements | |
| 683 MethodElement element = findElement("~"); | |
| 684 Element mainElement = findElement('main'); | |
| 685 // verify | |
| 686 _assertRecordedRelation( | |
| 687 element, | |
| 688 IndexConstants.IS_INVOKED_BY, | |
| 689 _expectedLocationQ(mainElement, '~a', length: 1)); | |
| 690 } | |
| 691 | |
| 692 void test_isMixedInBy_ClassDeclaration() { | |
| 693 _indexTestUnit(''' | |
| 694 class A {} // 1 | |
| 695 class B extends Object with A {} // 2 | |
| 696 '''); | |
| 697 // prepare elements | |
| 698 ClassElement classElementA = findElement("A"); | |
| 699 ClassElement classElementB = findElement("B"); | |
| 700 // verify | |
| 701 _assertRecordedRelation( | |
| 702 classElementA, | |
| 703 IndexConstants.IS_MIXED_IN_BY, | |
| 704 _expectedLocation(classElementB, 'A {} // 2')); | |
| 705 } | |
| 706 | |
| 707 void test_isMixedInBy_ClassTypeAlias() { | |
| 708 _indexTestUnit(''' | |
| 709 class A {} // 1 | |
| 710 class B = Object with A; // 2 | |
| 711 '''); | |
| 712 // prepare elements | |
| 713 ClassElement classElementA = findElement("A"); | |
| 714 ClassElement classElementB = findElement("B"); | |
| 715 // verify | |
| 716 _assertRecordedRelation( | |
| 717 classElementA, | |
| 718 IndexConstants.IS_MIXED_IN_BY, | |
| 719 _expectedLocation(classElementB, 'A; // 2')); | |
| 720 } | |
| 721 | |
| 722 void test_isReadBy_ParameterElement() { | |
| 723 _indexTestUnit(''' | |
| 724 main(var p) { | |
| 725 print(p); | |
| 726 } | |
| 727 '''); | |
| 728 // prepare elements | |
| 729 Element mainElement = findElement("main"); | |
| 730 Element parameterElement = findElement("p"); | |
| 731 // verify | |
| 732 _assertRecordedRelation( | |
| 733 parameterElement, | |
| 734 IndexConstants.IS_READ_BY, | |
| 735 _expectedLocation(mainElement, 'p);')); | |
| 736 } | |
| 737 | |
| 738 void test_isReadBy_VariableElement() { | |
| 739 _indexTestUnit(''' | |
| 740 main() { | |
| 741 var v = 0; | |
| 742 print(v); | |
| 743 } | |
| 744 '''); | |
| 745 // prepare elements | |
| 746 Element mainElement = findElement("main"); | |
| 747 Element variableElement = findElement("v"); | |
| 748 // verify | |
| 749 _assertRecordedRelation( | |
| 750 variableElement, | |
| 751 IndexConstants.IS_READ_BY, | |
| 752 _expectedLocation(mainElement, 'v);')); | |
| 753 } | |
| 754 | |
| 755 void test_isReadWrittenBy_ParameterElement() { | |
| 756 _indexTestUnit(''' | |
| 757 main(int p) { | |
| 758 p += 1; | |
| 759 } | |
| 760 '''); | |
| 761 // prepare elements | |
| 762 Element mainElement = findElement("main"); | |
| 763 Element parameterElement = findElement("p"); | |
| 764 // verify | |
| 765 _assertRecordedRelation( | |
| 766 parameterElement, | |
| 767 IndexConstants.IS_READ_WRITTEN_BY, | |
| 768 _expectedLocation(mainElement, 'p += 1')); | |
| 769 } | |
| 770 | |
| 771 void test_isReadWrittenBy_VariableElement() { | |
| 772 _indexTestUnit(''' | |
| 773 main() { | |
| 774 var v = 0; | |
| 775 v += 1; | |
| 776 } | |
| 777 '''); | |
| 778 // prepare elements | |
| 779 Element mainElement = findElement("main"); | |
| 780 Element variableElement = findElement("v"); | |
| 781 // verify | |
| 782 _assertRecordedRelation( | |
| 783 variableElement, | |
| 784 IndexConstants.IS_READ_WRITTEN_BY, | |
| 785 _expectedLocation(mainElement, 'v += 1')); | |
| 786 } | |
| 787 | |
| 788 void test_isReferencedBy_ClassElement() { | |
| 789 _indexTestUnit(''' | |
| 790 class A { | |
| 791 static var field; | |
| 792 } | |
| 793 main(A p) { | |
| 794 A v; | |
| 795 new A(); // 2 | |
| 796 A.field = 1; | |
| 797 print(A.field); // 3 | |
| 798 } | |
| 799 '''); | |
| 800 // prepare elements | |
| 801 ClassElement aElement = findElement("A"); | |
| 802 Element mainElement = findElement("main"); | |
| 803 ParameterElement pElement = findElement("p"); | |
| 804 VariableElement vElement = findElement("v"); | |
| 805 // verify | |
| 806 _assertRecordedRelation( | |
| 807 aElement, | |
| 808 IndexConstants.IS_REFERENCED_BY, | |
| 809 _expectedLocation(pElement, 'A p) {')); | |
| 810 _assertRecordedRelation( | |
| 811 aElement, | |
| 812 IndexConstants.IS_REFERENCED_BY, | |
| 813 _expectedLocation(vElement, 'A v;')); | |
| 814 _assertRecordedRelation( | |
| 815 aElement, | |
| 816 IndexConstants.IS_REFERENCED_BY, | |
| 817 _expectedLocation(mainElement, 'A(); // 2')); | |
| 818 _assertRecordedRelation( | |
| 819 aElement, | |
| 820 IndexConstants.IS_REFERENCED_BY, | |
| 821 _expectedLocation(mainElement, 'A.field = 1;')); | |
| 822 _assertRecordedRelation( | |
| 823 aElement, | |
| 824 IndexConstants.IS_REFERENCED_BY, | |
| 825 _expectedLocation(mainElement, 'A.field); // 3')); | |
| 826 } | |
| 827 | |
| 828 void test_isReferencedBy_ClassTypeAlias() { | |
| 829 _indexTestUnit(''' | |
| 830 class A {} | |
| 831 class B = Object with A; | |
| 832 main(B p) { | |
| 833 B v; | |
| 834 } | |
| 835 '''); | |
| 836 // prepare elements | |
| 837 ClassElement bElement = findElement("B"); | |
| 838 ParameterElement pElement = findElement("p"); | |
| 839 VariableElement vElement = findElement("v"); | |
| 840 // verify | |
| 841 _assertRecordedRelation( | |
| 842 bElement, | |
| 843 IndexConstants.IS_REFERENCED_BY, | |
| 844 _expectedLocation(pElement, 'B p) {')); | |
| 845 _assertRecordedRelation( | |
| 846 bElement, | |
| 847 IndexConstants.IS_REFERENCED_BY, | |
| 848 _expectedLocation(vElement, 'B v;')); | |
| 849 } | |
| 850 | |
| 851 void test_isReferencedBy_CompilationUnitElement_export() { | |
| 852 addSource('/lib.dart', ''' | |
| 853 library lib; | |
| 854 '''); | |
| 855 _indexTestUnit(''' | |
| 856 export 'lib.dart'; | |
| 857 '''); | |
| 858 // prepare elements | |
| 859 LibraryElement libElement = testLibraryElement.exportedLibraries[0]; | |
| 860 CompilationUnitElement libUnitElement = libElement.definingCompilationUnit; | |
| 861 // verify | |
| 862 _assertRecordedRelation( | |
| 863 libUnitElement, | |
| 864 IndexConstants.IS_REFERENCED_BY, | |
| 865 _expectedLocation(testUnitElement, "'lib.dart'", length: 10)); | |
| 866 } | |
| 867 | |
| 868 void test_isReferencedBy_CompilationUnitElement_import() { | |
| 869 addSource('/lib.dart', ''' | |
| 870 library lib; | |
| 871 '''); | |
| 872 _indexTestUnit(''' | |
| 873 import 'lib.dart'; | |
| 874 '''); | |
| 875 // prepare elements | |
| 876 LibraryElement libElement = testLibraryElement.imports[0].importedLibrary; | |
| 877 CompilationUnitElement libUnitElement = libElement.definingCompilationUnit; | |
| 878 // verify | |
| 879 _assertRecordedRelation( | |
| 880 libUnitElement, | |
| 881 IndexConstants.IS_REFERENCED_BY, | |
| 882 _expectedLocation(testUnitElement, "'lib.dart'", length: 10)); | |
| 883 } | |
| 884 | |
| 885 void test_isReferencedBy_CompilationUnitElement_part() { | |
| 886 addSource('/my_unit.dart', 'part of my_lib;'); | |
| 887 _indexTestUnit(''' | |
| 888 library my_lib; | |
| 889 part 'my_unit.dart'; | |
| 890 '''); | |
| 891 // prepare elements | |
| 892 CompilationUnitElement myUnitElement = testLibraryElement.parts[0]; | |
| 893 // verify | |
| 894 _assertRecordedRelation( | |
| 895 myUnitElement, | |
| 896 IndexConstants.IS_REFERENCED_BY, | |
| 897 _expectedLocation(testUnitElement, "'my_unit.dart';", length: 14)); | |
| 898 } | |
| 899 | |
| 900 void test_isReferencedBy_ConstructorElement() { | |
| 901 _indexTestUnit(''' | |
| 902 class A implements B { | |
| 903 A() {} | |
| 904 A.foo() {} | |
| 905 } | |
| 906 class B extends A { | |
| 907 B() : super(); // marker-1 | |
| 908 B.foo() : super.foo(); // marker-2 | |
| 909 factory B.bar() = A.foo; // marker-3 | |
| 910 } | |
| 911 main() { | |
| 912 new A(); // marker-main-1 | |
| 913 new A.foo(); // marker-main-2 | |
| 914 } | |
| 915 '''); | |
| 916 // prepare elements | |
| 917 Element mainElement = findElement('main'); | |
| 918 var isConstructor = (node) => node is ConstructorDeclaration; | |
| 919 ConstructorElement consA = findNodeElementAtString("A()", isConstructor); | |
| 920 ConstructorElement consA_foo = | |
| 921 findNodeElementAtString("A.foo()", isConstructor); | |
| 922 ConstructorElement consB = findNodeElementAtString("B()", isConstructor); | |
| 923 ConstructorElement consB_foo = | |
| 924 findNodeElementAtString("B.foo()", isConstructor); | |
| 925 ConstructorElement consB_bar = | |
| 926 findNodeElementAtString("B.bar()", isConstructor); | |
| 927 // A() | |
| 928 _assertRecordedRelation( | |
| 929 consA, | |
| 930 IndexConstants.IS_REFERENCED_BY, | |
| 931 _expectedLocation(consB, '(); // marker-1', length: 0)); | |
| 932 _assertRecordedRelation( | |
| 933 consA, | |
| 934 IndexConstants.IS_REFERENCED_BY, | |
| 935 _expectedLocation(mainElement, '(); // marker-main-1', length: 0)); | |
| 936 // A.foo() | |
| 937 _assertRecordedRelation( | |
| 938 consA_foo, | |
| 939 IndexConstants.IS_REFERENCED_BY, | |
| 940 _expectedLocation(consB_foo, '.foo(); // marker-2', length: 4)); | |
| 941 _assertRecordedRelation( | |
| 942 consA_foo, | |
| 943 IndexConstants.IS_REFERENCED_BY, | |
| 944 _expectedLocation(consB_bar, '.foo; // marker-3', length: 4)); | |
| 945 _assertRecordedRelation( | |
| 946 consA_foo, | |
| 947 IndexConstants.IS_REFERENCED_BY, | |
| 948 _expectedLocation(mainElement, '.foo(); // marker-main-2', length: 4)); | |
| 949 } | |
| 950 | |
| 951 void test_isReferencedBy_ConstructorElement_classTypeAlias() { | |
| 952 _indexTestUnit(''' | |
| 953 class M {} | |
| 954 class A implements B { | |
| 955 A() {} | |
| 956 A.named() {} | |
| 957 } | |
| 958 class B = A with M; | |
| 959 main() { | |
| 960 new B(); // marker-main-1 | |
| 961 new B.named(); // marker-main-2 | |
| 962 } | |
| 963 '''); | |
| 964 // prepare elements | |
| 965 Element mainElement = findElement('main'); | |
| 966 var isConstructor = (node) => node is ConstructorDeclaration; | |
| 967 ConstructorElement consA = findNodeElementAtString("A()", isConstructor); | |
| 968 ConstructorElement consA_named = | |
| 969 findNodeElementAtString("A.named()", isConstructor); | |
| 970 // verify | |
| 971 _assertRecordedRelation( | |
| 972 consA, | |
| 973 IndexConstants.IS_REFERENCED_BY, | |
| 974 _expectedLocation(mainElement, '(); // marker-main-1', length: 0)); | |
| 975 _assertRecordedRelation( | |
| 976 consA_named, | |
| 977 IndexConstants.IS_REFERENCED_BY, | |
| 978 _expectedLocation(mainElement, '.named(); // marker-main-2', length: 6))
; | |
| 979 } | |
| 980 | |
| 981 void test_isReferencedBy_ConstructorFieldInitializer() { | |
| 982 _indexTestUnit(''' | |
| 983 class A { | |
| 984 int field; | |
| 985 A() : field = 5; | |
| 986 } | |
| 987 '''); | |
| 988 // prepare elements | |
| 989 ConstructorElement constructorElement = | |
| 990 findNodeElementAtString("A()", (node) => node is ConstructorDeclaration)
; | |
| 991 FieldElement fieldElement = findElement("field"); | |
| 992 // verify | |
| 993 _assertRecordedRelation( | |
| 994 fieldElement, | |
| 995 IndexConstants.IS_REFERENCED_BY, | |
| 996 _expectedLocation(constructorElement, 'field = 5')); | |
| 997 } | |
| 998 | |
| 999 void test_isReferencedBy_FieldElement() { | |
| 1000 _indexTestUnit(''' | |
| 1001 class A { | |
| 1002 var field; | |
| 1003 main() { | |
| 1004 this.field = 5; // q | |
| 1005 print(this.field); // q | |
| 1006 field = 5; // nq | |
| 1007 print(field); // nq | |
| 1008 } | |
| 1009 } | |
| 1010 '''); | |
| 1011 // prepare elements | |
| 1012 Element mainElement = findElement("main"); | |
| 1013 FieldElement fieldElement = findElement("field"); | |
| 1014 PropertyAccessorElement getter = fieldElement.getter; | |
| 1015 PropertyAccessorElement setter = fieldElement.setter; | |
| 1016 // verify | |
| 1017 _assertRecordedRelation( | |
| 1018 setter, | |
| 1019 IndexConstants.IS_REFERENCED_BY, | |
| 1020 _expectedLocationQ(mainElement, 'field = 5; // q')); | |
| 1021 _assertRecordedRelation( | |
| 1022 getter, | |
| 1023 IndexConstants.IS_REFERENCED_BY, | |
| 1024 _expectedLocationQ(mainElement, 'field); // q')); | |
| 1025 _assertRecordedRelation( | |
| 1026 setter, | |
| 1027 IndexConstants.IS_REFERENCED_BY, | |
| 1028 _expectedLocation(mainElement, 'field = 5; // nq')); | |
| 1029 _assertRecordedRelation( | |
| 1030 getter, | |
| 1031 IndexConstants.IS_REFERENCED_BY, | |
| 1032 _expectedLocation(mainElement, 'field); // nq')); | |
| 1033 } | |
| 1034 | |
| 1035 void test_isReferencedBy_FieldFormalParameterElement() { | |
| 1036 _indexTestUnit(''' | |
| 1037 class A { | |
| 1038 int field; | |
| 1039 A(this.field); | |
| 1040 } | |
| 1041 '''); | |
| 1042 // prepare elements | |
| 1043 FieldElement fieldElement = findElement("field"); | |
| 1044 Element fieldParameterElement = findNodeElementAtString("field);"); | |
| 1045 // verify | |
| 1046 _assertRecordedRelation( | |
| 1047 fieldElement, | |
| 1048 IndexConstants.IS_REFERENCED_BY, | |
| 1049 _expectedLocation(fieldParameterElement, 'field);')); | |
| 1050 } | |
| 1051 | |
| 1052 void test_isReferencedBy_FunctionElement() { | |
| 1053 _indexTestUnit(''' | |
| 1054 foo() {} | |
| 1055 main() { | |
| 1056 print(foo); | |
| 1057 print(foo()); | |
| 1058 } | |
| 1059 '''); | |
| 1060 // prepare elements | |
| 1061 FunctionElement element = findElement("foo"); | |
| 1062 Element mainElement = findElement("main"); | |
| 1063 // "referenced" here | |
| 1064 _assertRecordedRelation( | |
| 1065 element, | |
| 1066 IndexConstants.IS_REFERENCED_BY, | |
| 1067 _expectedLocation(mainElement, 'foo);')); | |
| 1068 // only "invoked", but not "referenced" | |
| 1069 { | |
| 1070 _assertRecordedRelation( | |
| 1071 element, | |
| 1072 IndexConstants.IS_INVOKED_BY, | |
| 1073 _expectedLocation(mainElement, 'foo());')); | |
| 1074 _assertNoRecordedRelation( | |
| 1075 element, | |
| 1076 IndexConstants.IS_REFERENCED_BY, | |
| 1077 _expectedLocation(mainElement, 'foo());')); | |
| 1078 } | |
| 1079 } | |
| 1080 | |
| 1081 void test_isReferencedBy_FunctionTypeAliasElement() { | |
| 1082 _indexTestUnit(''' | |
| 1083 typedef A(); | |
| 1084 main(A p) { | |
| 1085 } | |
| 1086 '''); | |
| 1087 // prepare elements | |
| 1088 Element aElement = findElement('A'); | |
| 1089 Element pElement = findElement('p'); | |
| 1090 // verify | |
| 1091 _assertRecordedRelation( | |
| 1092 aElement, | |
| 1093 IndexConstants.IS_REFERENCED_BY, | |
| 1094 _expectedLocation(pElement, 'A p) {')); | |
| 1095 } | |
| 1096 | |
| 1097 void test_isReferencedBy_ImportElement_noPrefix() { | |
| 1098 addSource('/lib.dart', ''' | |
| 1099 library lib; | |
| 1100 var myVar; | |
| 1101 myFunction() {} | |
| 1102 myToHide() {} | |
| 1103 '''); | |
| 1104 _indexTestUnit(''' | |
| 1105 import 'lib.dart' show myVar, myFunction hide myToHide; | |
| 1106 main() { | |
| 1107 myVar = 1; | |
| 1108 myFunction(); | |
| 1109 print(0); | |
| 1110 } | |
| 1111 '''); | |
| 1112 // prepare elements | |
| 1113 ImportElement importElement = testLibraryElement.imports[0]; | |
| 1114 Element mainElement = findElement('main'); | |
| 1115 // verify | |
| 1116 _assertRecordedRelation( | |
| 1117 importElement, | |
| 1118 IndexConstants.IS_REFERENCED_BY, | |
| 1119 _expectedLocation(mainElement, 'myVar = 1;', length: 0)); | |
| 1120 _assertRecordedRelation( | |
| 1121 importElement, | |
| 1122 IndexConstants.IS_REFERENCED_BY, | |
| 1123 _expectedLocation(mainElement, 'myFunction();', length: 0)); | |
| 1124 _assertNoRecordedRelation( | |
| 1125 importElement, | |
| 1126 IndexConstants.IS_REFERENCED_BY, | |
| 1127 _expectedLocation(mainElement, 'print(0);', length: 0)); | |
| 1128 // no references from import combinators | |
| 1129 _assertNoRecordedRelation( | |
| 1130 importElement, | |
| 1131 IndexConstants.IS_REFERENCED_BY, | |
| 1132 _expectedLocation(testUnitElement, 'myVar, ', length: 0)); | |
| 1133 _assertNoRecordedRelation( | |
| 1134 importElement, | |
| 1135 IndexConstants.IS_REFERENCED_BY, | |
| 1136 _expectedLocation(testUnitElement, 'myFunction hide', length: 0)); | |
| 1137 _assertNoRecordedRelation( | |
| 1138 importElement, | |
| 1139 IndexConstants.IS_REFERENCED_BY, | |
| 1140 _expectedLocation(testUnitElement, 'myToHide;', length: 0)); | |
| 1141 } | |
| 1142 | |
| 1143 void test_isReferencedBy_ImportElement_withPrefix() { | |
| 1144 addSource('/libA.dart', ''' | |
| 1145 library libA; | |
| 1146 var myVar; | |
| 1147 '''); | |
| 1148 addSource('/libB.dart', ''' | |
| 1149 library libB; | |
| 1150 class MyClass {} | |
| 1151 '''); | |
| 1152 _indexTestUnit(''' | |
| 1153 import 'libA.dart' as pref; | |
| 1154 import 'libB.dart' as pref; | |
| 1155 main() { | |
| 1156 pref.myVar = 1; | |
| 1157 new pref.MyClass(); | |
| 1158 } | |
| 1159 '''); | |
| 1160 // prepare elements | |
| 1161 ImportElement importElementA = testLibraryElement.imports[0]; | |
| 1162 ImportElement importElementB = testLibraryElement.imports[1]; | |
| 1163 Element mainElement = findElement('main'); | |
| 1164 // verify | |
| 1165 _assertRecordedRelation( | |
| 1166 importElementA, | |
| 1167 IndexConstants.IS_REFERENCED_BY, | |
| 1168 _expectedLocation(mainElement, 'pref.myVar = 1;', length: 5)); | |
| 1169 _assertRecordedRelation( | |
| 1170 importElementB, | |
| 1171 IndexConstants.IS_REFERENCED_BY, | |
| 1172 _expectedLocation(mainElement, 'pref.MyClass();', length: 5)); | |
| 1173 } | |
| 1174 | |
| 1175 void test_isReferencedBy_ImportElement_withPrefix_combinators() { | |
| 1176 addSource('/lib.dart', ''' | |
| 1177 library lib; | |
| 1178 class A {} | |
| 1179 class B {} | |
| 1180 '''); | |
| 1181 _indexTestUnit(''' | |
| 1182 import 'lib.dart' as pref show A; | |
| 1183 import 'lib.dart' as pref show B; | |
| 1184 import 'lib.dart'; | |
| 1185 import 'lib.dart' as otherPrefix; | |
| 1186 main() { | |
| 1187 new pref.A(); | |
| 1188 new pref.B(); | |
| 1189 } | |
| 1190 '''); | |
| 1191 // prepare elements | |
| 1192 ImportElement importElementA = testLibraryElement.imports[0]; | |
| 1193 ImportElement importElementB = testLibraryElement.imports[1]; | |
| 1194 Element mainElement = findElement('main'); | |
| 1195 // verify | |
| 1196 _assertRecordedRelation( | |
| 1197 importElementA, | |
| 1198 IndexConstants.IS_REFERENCED_BY, | |
| 1199 _expectedLocation(mainElement, 'pref.A();', length: 5)); | |
| 1200 _assertRecordedRelation( | |
| 1201 importElementB, | |
| 1202 IndexConstants.IS_REFERENCED_BY, | |
| 1203 _expectedLocation(mainElement, 'pref.B();', length: 5)); | |
| 1204 } | |
| 1205 | |
| 1206 void test_isReferencedBy_ImportElement_withPrefix_invocation() { | |
| 1207 addSource('/lib.dart', ''' | |
| 1208 library lib; | |
| 1209 myFunc() {} | |
| 1210 '''); | |
| 1211 _indexTestUnit(''' | |
| 1212 import 'lib.dart' as pref; | |
| 1213 main() { | |
| 1214 pref.myFunc(); | |
| 1215 } | |
| 1216 '''); | |
| 1217 // prepare elements | |
| 1218 ImportElement importElement = testLibraryElement.imports[0]; | |
| 1219 Element mainElement = findElement('main'); | |
| 1220 // verify | |
| 1221 _assertRecordedRelation( | |
| 1222 importElement, | |
| 1223 IndexConstants.IS_REFERENCED_BY, | |
| 1224 _expectedLocation(mainElement, 'pref.myFunc();', length: 5)); | |
| 1225 } | |
| 1226 | |
| 1227 void test_isReferencedBy_ImportElement_withPrefix_oneCandidate() { | |
| 1228 addSource('/lib.dart', ''' | |
| 1229 library lib; | |
| 1230 class A {} | |
| 1231 class B {} | |
| 1232 '''); | |
| 1233 _indexTestUnit(''' | |
| 1234 import 'lib.dart' as pref show A; | |
| 1235 main() { | |
| 1236 new pref.A(); | |
| 1237 } | |
| 1238 '''); | |
| 1239 // prepare elements | |
| 1240 ImportElement importElement = testLibraryElement.imports[0]; | |
| 1241 Element mainElement = findElement('main'); | |
| 1242 // verify | |
| 1243 _assertRecordedRelation( | |
| 1244 importElement, | |
| 1245 IndexConstants.IS_REFERENCED_BY, | |
| 1246 _expectedLocation(mainElement, 'pref.A();', length: 5)); | |
| 1247 } | |
| 1248 | |
| 1249 void test_isReferencedBy_ImportElement_withPrefix_unresolvedElement() { | |
| 1250 verifyNoTestUnitErrors = false; | |
| 1251 addSource('/lib.dart', ''' | |
| 1252 library lib; | |
| 1253 '''); | |
| 1254 _indexTestUnit(''' | |
| 1255 import 'lib.dart' as pref; | |
| 1256 main() { | |
| 1257 pref.myVar = 1; | |
| 1258 } | |
| 1259 '''); | |
| 1260 } | |
| 1261 | |
| 1262 void test_isReferencedBy_ImportElement_withPrefix_wrongInvocation() { | |
| 1263 verifyNoTestUnitErrors = false; | |
| 1264 _indexTestUnit(''' | |
| 1265 import 'dart:math' as m; | |
| 1266 main() { | |
| 1267 m(); | |
| 1268 }'''); | |
| 1269 } | |
| 1270 | |
| 1271 void test_isReferencedBy_ImportElement_withPrefix_wrongPrefixedIdentifier() { | |
| 1272 verifyNoTestUnitErrors = false; | |
| 1273 _indexTestUnit(''' | |
| 1274 import 'dart:math' as m; | |
| 1275 main() { | |
| 1276 x.m; | |
| 1277 } | |
| 1278 '''); | |
| 1279 } | |
| 1280 | |
| 1281 void test_isReferencedBy_LabelElement() { | |
| 1282 _indexTestUnit(''' | |
| 1283 main() { | |
| 1284 L: while (true) { | |
| 1285 break L; | |
| 1286 } | |
| 1287 } | |
| 1288 '''); | |
| 1289 // prepare elements | |
| 1290 Element mainElement = findElement('main'); | |
| 1291 Element element = findElement('L'); | |
| 1292 // verify | |
| 1293 _assertRecordedRelation( | |
| 1294 element, | |
| 1295 IndexConstants.IS_REFERENCED_BY, | |
| 1296 _expectedLocation(mainElement, 'L;')); | |
| 1297 } | |
| 1298 | |
| 1299 void test_isReferencedBy_MethodElement() { | |
| 1300 _indexTestUnit(''' | |
| 1301 class A { | |
| 1302 method() {} | |
| 1303 main() { | |
| 1304 print(this.method); // q | |
| 1305 print(method); // nq | |
| 1306 } | |
| 1307 }'''); | |
| 1308 // prepare elements | |
| 1309 Element mainElement = findElement("main"); | |
| 1310 MethodElement methodElement = findElement("method"); | |
| 1311 // verify | |
| 1312 _assertRecordedRelation( | |
| 1313 methodElement, | |
| 1314 IndexConstants.IS_REFERENCED_BY, | |
| 1315 _expectedLocationQ(mainElement, 'method); // q')); | |
| 1316 _assertRecordedRelation( | |
| 1317 methodElement, | |
| 1318 IndexConstants.IS_REFERENCED_BY, | |
| 1319 _expectedLocation(mainElement, 'method); // nq')); | |
| 1320 } | |
| 1321 | |
| 1322 void test_isReferencedBy_ParameterElement() { | |
| 1323 _indexTestUnit(''' | |
| 1324 foo({var p}) {} | |
| 1325 main() { | |
| 1326 foo(p: 1); | |
| 1327 } | |
| 1328 '''); | |
| 1329 // prepare elements | |
| 1330 Element mainElement = findElement('main'); | |
| 1331 Element element = findElement('p'); | |
| 1332 // verify | |
| 1333 _assertRecordedRelation( | |
| 1334 element, | |
| 1335 IndexConstants.IS_REFERENCED_BY, | |
| 1336 _expectedLocation(mainElement, 'p: 1')); | |
| 1337 } | |
| 1338 | |
| 1339 void test_isReferencedBy_TopLevelVariableElement() { | |
| 1340 addSource('/lib.dart', ''' | |
| 1341 library lib; | |
| 1342 var V; | |
| 1343 '''); | |
| 1344 _indexTestUnit(''' | |
| 1345 import 'lib.dart' show V; // imp | |
| 1346 import 'lib.dart' as pref; | |
| 1347 main() { | |
| 1348 pref.V = 5; // q | |
| 1349 print(pref.V); // q | |
| 1350 V = 5; // nq | |
| 1351 print(V); // nq | |
| 1352 }'''); | |
| 1353 // prepare elements | |
| 1354 TopLevelVariableElement variable = importedUnit().topLevelVariables[0]; | |
| 1355 Element mainElement = findElement("main"); | |
| 1356 // verify | |
| 1357 _assertRecordedRelation( | |
| 1358 variable, | |
| 1359 IndexConstants.IS_REFERENCED_BY, | |
| 1360 _expectedLocation(testUnitElement, 'V; // imp')); | |
| 1361 _assertRecordedRelation( | |
| 1362 variable.setter, | |
| 1363 IndexConstants.IS_REFERENCED_BY, | |
| 1364 _expectedLocation(mainElement, 'V = 5; // q')); | |
| 1365 _assertRecordedRelation( | |
| 1366 variable.getter, | |
| 1367 IndexConstants.IS_REFERENCED_BY, | |
| 1368 _expectedLocation(mainElement, 'V); // q')); | |
| 1369 _assertRecordedRelation( | |
| 1370 variable.setter, | |
| 1371 IndexConstants.IS_REFERENCED_BY, | |
| 1372 _expectedLocation(mainElement, 'V = 5; // nq')); | |
| 1373 _assertRecordedRelation( | |
| 1374 variable.getter, | |
| 1375 IndexConstants.IS_REFERENCED_BY, | |
| 1376 _expectedLocation(mainElement, 'V); // nq')); | |
| 1377 } | |
| 1378 | |
| 1379 void test_isReferencedBy_TypeParameterElement() { | |
| 1380 _indexTestUnit(''' | |
| 1381 class A<T> { | |
| 1382 T f; | |
| 1383 foo(T p) { | |
| 1384 T v; | |
| 1385 } | |
| 1386 } | |
| 1387 '''); | |
| 1388 // prepare elements | |
| 1389 Element typeParameterElement = findElement('T'); | |
| 1390 Element fieldElement = findElement('f'); | |
| 1391 Element parameterElement = findElement('p'); | |
| 1392 Element variableElement = findElement('v'); | |
| 1393 // verify | |
| 1394 _assertRecordedRelation( | |
| 1395 typeParameterElement, | |
| 1396 IndexConstants.IS_REFERENCED_BY, | |
| 1397 _expectedLocation(fieldElement, 'T f')); | |
| 1398 _assertRecordedRelation( | |
| 1399 typeParameterElement, | |
| 1400 IndexConstants.IS_REFERENCED_BY, | |
| 1401 _expectedLocation(parameterElement, 'T p')); | |
| 1402 _assertRecordedRelation( | |
| 1403 typeParameterElement, | |
| 1404 IndexConstants.IS_REFERENCED_BY, | |
| 1405 _expectedLocation(variableElement, 'T v')); | |
| 1406 } | |
| 1407 | |
| 1408 /** | |
| 1409 * There was a bug in the AST structure, when single [Comment] was cloned and | |
| 1410 * assigned to both [FieldDeclaration] and [VariableDeclaration]. | |
| 1411 * | |
| 1412 * This caused duplicate indexing. | |
| 1413 * Here we test that the problem is fixed one way or another. | |
| 1414 */ | |
| 1415 void test_isReferencedBy_identifierInComment() { | |
| 1416 _indexTestUnit(''' | |
| 1417 class A {} | |
| 1418 /// [A] text | |
| 1419 var myVariable = null; | |
| 1420 '''); | |
| 1421 // prepare elements | |
| 1422 Element aElement = findElement('A'); | |
| 1423 Element variableElement = findElement('myVariable'); | |
| 1424 // verify | |
| 1425 _assertRecordedRelation( | |
| 1426 aElement, | |
| 1427 IndexConstants.IS_REFERENCED_BY, | |
| 1428 _expectedLocation(testUnitElement, 'A] text')); | |
| 1429 _assertNoRecordedRelation( | |
| 1430 aElement, | |
| 1431 IndexConstants.IS_REFERENCED_BY, | |
| 1432 _expectedLocation(variableElement, 'A] text')); | |
| 1433 } | |
| 1434 | |
| 1435 void test_isReferencedBy_libraryName() { | |
| 1436 Source libSource = addSource('/lib.dart', ''' | |
| 1437 library lib; | |
| 1438 part 'test.dart'; | |
| 1439 '''); | |
| 1440 testCode = 'part of lib;'; | |
| 1441 testSource = addSource('/test.dart', testCode); | |
| 1442 testUnit = resolveDartUnit(testSource, libSource); | |
| 1443 testUnitElement = testUnit.element; | |
| 1444 testLibraryElement = testUnitElement.library; | |
| 1445 indexDartUnit(store, context, testUnit); | |
| 1446 // verify | |
| 1447 _assertRecordedRelation( | |
| 1448 testLibraryElement, | |
| 1449 IndexConstants.IS_REFERENCED_BY, | |
| 1450 _expectedLocation(testUnitElement, "lib;")); | |
| 1451 } | |
| 1452 | |
| 1453 void test_isReferencedBy_typeInVariableList() { | |
| 1454 _indexTestUnit(''' | |
| 1455 class A {} | |
| 1456 A myVariable = null; | |
| 1457 '''); | |
| 1458 // prepare elements | |
| 1459 Element classElementA = findElement('A'); | |
| 1460 Element variableElement = findElement('myVariable'); | |
| 1461 // verify | |
| 1462 _assertRecordedRelation( | |
| 1463 classElementA, | |
| 1464 IndexConstants.IS_REFERENCED_BY, | |
| 1465 _expectedLocation(variableElement, 'A myVariable')); | |
| 1466 } | |
| 1467 | |
| 1468 void test_isWrittenBy_ParameterElement() { | |
| 1469 _indexTestUnit(''' | |
| 1470 main(var p) { | |
| 1471 p = 1; | |
| 1472 }'''); | |
| 1473 // prepare elements | |
| 1474 Element mainElement = findElement("main"); | |
| 1475 ParameterElement pElement = findElement("p"); | |
| 1476 // verify | |
| 1477 _assertRecordedRelation( | |
| 1478 pElement, | |
| 1479 IndexConstants.IS_WRITTEN_BY, | |
| 1480 _expectedLocation(mainElement, 'p = 1')); | |
| 1481 } | |
| 1482 | |
| 1483 void test_isWrittenBy_VariableElement() { | |
| 1484 _indexTestUnit(''' | |
| 1485 main() { | |
| 1486 var v = 0; | |
| 1487 v = 1; | |
| 1488 }'''); | |
| 1489 // prepare elements | |
| 1490 Element mainElement = findElement("main"); | |
| 1491 LocalVariableElement vElement = findElement("v"); | |
| 1492 // verify | |
| 1493 _assertRecordedRelation( | |
| 1494 vElement, | |
| 1495 IndexConstants.IS_WRITTEN_BY, | |
| 1496 _expectedLocation(mainElement, 'v = 1')); | |
| 1497 } | |
| 1498 | |
| 1499 void test_nameIsInvokedBy() { | |
| 1500 _indexTestUnit(''' | |
| 1501 class A { | |
| 1502 test(x) {} | |
| 1503 } | |
| 1504 main(A a, p) { | |
| 1505 a.test(1); | |
| 1506 p.test(2); | |
| 1507 }'''); | |
| 1508 // prepare elements | |
| 1509 Element mainElement = findElement("main"); | |
| 1510 Element nameElement = new NameElement('test'); | |
| 1511 // verify | |
| 1512 _assertRecordedRelation( | |
| 1513 nameElement, | |
| 1514 IndexConstants.IS_INVOKED_BY, | |
| 1515 _expectedLocationQ(mainElement, 'test(1)')); | |
| 1516 _assertRecordedRelation( | |
| 1517 nameElement, | |
| 1518 IndexConstants.IS_INVOKED_BY, | |
| 1519 _expectedLocationQU(mainElement, 'test(2)')); | |
| 1520 _assertNoRecordedRelation( | |
| 1521 nameElement, | |
| 1522 IndexConstants.IS_READ_BY, | |
| 1523 _expectedLocationQU(mainElement, 'test(2)')); | |
| 1524 } | |
| 1525 | |
| 1526 void test_nameIsReadBy() { | |
| 1527 _indexTestUnit(''' | |
| 1528 class A { | |
| 1529 var test; | |
| 1530 } | |
| 1531 main(A a, p) { | |
| 1532 print(a.test); // a | |
| 1533 print(p.test); // p | |
| 1534 }'''); | |
| 1535 // prepare elements | |
| 1536 Element mainElement = findElement("main"); | |
| 1537 Element nameElement = new NameElement('test'); | |
| 1538 // verify | |
| 1539 _assertRecordedRelation( | |
| 1540 nameElement, | |
| 1541 IndexConstants.IS_READ_BY, | |
| 1542 _expectedLocationQ(mainElement, 'test); // a')); | |
| 1543 _assertRecordedRelation( | |
| 1544 nameElement, | |
| 1545 IndexConstants.IS_READ_BY, | |
| 1546 _expectedLocationQU(mainElement, 'test); // p')); | |
| 1547 } | |
| 1548 | |
| 1549 void test_nameIsReadWrittenBy() { | |
| 1550 _indexTestUnit(''' | |
| 1551 class A { | |
| 1552 var test; | |
| 1553 } | |
| 1554 main(A a, p) { | |
| 1555 a.test += 1; | |
| 1556 p.test += 2; | |
| 1557 }'''); | |
| 1558 // prepare elements | |
| 1559 Element mainElement = findElement("main"); | |
| 1560 Element nameElement = new NameElement('test'); | |
| 1561 // verify | |
| 1562 _assertRecordedRelation( | |
| 1563 nameElement, | |
| 1564 IndexConstants.IS_READ_WRITTEN_BY, | |
| 1565 _expectedLocationQ(mainElement, 'test += 1')); | |
| 1566 _assertRecordedRelation( | |
| 1567 nameElement, | |
| 1568 IndexConstants.IS_READ_WRITTEN_BY, | |
| 1569 _expectedLocationQU(mainElement, 'test += 2')); | |
| 1570 } | |
| 1571 | |
| 1572 void test_nameIsWrittenBy() { | |
| 1573 _indexTestUnit(''' | |
| 1574 class A { | |
| 1575 var test; | |
| 1576 } | |
| 1577 main(A a, p) { | |
| 1578 a.test = 1; | |
| 1579 p.test = 2; | |
| 1580 }'''); | |
| 1581 // prepare elements | |
| 1582 Element mainElement = findElement("main"); | |
| 1583 Element nameElement = new NameElement('test'); | |
| 1584 // verify | |
| 1585 _assertRecordedRelation( | |
| 1586 nameElement, | |
| 1587 IndexConstants.IS_WRITTEN_BY, | |
| 1588 _expectedLocationQ(mainElement, 'test = 1')); | |
| 1589 _assertRecordedRelation( | |
| 1590 nameElement, | |
| 1591 IndexConstants.IS_WRITTEN_BY, | |
| 1592 _expectedLocationQU(mainElement, 'test = 2')); | |
| 1593 } | |
| 1594 | |
| 1595 void test_nullUnit() { | |
| 1596 indexDartUnit(store, context, null); | |
| 1597 } | |
| 1598 | |
| 1599 void test_nullUnitElement() { | |
| 1600 CompilationUnit unit = new CompilationUnit(null, null, [], [], null); | |
| 1601 indexDartUnit(store, context, unit); | |
| 1602 } | |
| 1603 | |
| 1604 void _assertDefinesTopLevelElement(Relationship relationship, | |
| 1605 ExpectedLocation expectedLocation) { | |
| 1606 _assertRecordedRelation(testLibraryElement, relationship, expectedLocation); | |
| 1607 _assertRecordedRelation( | |
| 1608 UniverseElement.INSTANCE, | |
| 1609 relationship, | |
| 1610 expectedLocation); | |
| 1611 } | |
| 1612 | |
| 1613 /** | |
| 1614 * Asserts that [recordedRelations] has no item with the specified properties. | |
| 1615 */ | |
| 1616 void _assertNoRecordedRelation(Element element, Relationship relationship, | |
| 1617 ExpectedLocation location) { | |
| 1618 for (RecordedRelation recordedRelation in recordedRelations) { | |
| 1619 if (_equalsRecordedRelation( | |
| 1620 recordedRelation, | |
| 1621 element, | |
| 1622 relationship, | |
| 1623 location)) { | |
| 1624 fail( | |
| 1625 'not expected: ${recordedRelation} in\n' + recordedRelations.join('\
n')); | |
| 1626 } | |
| 1627 } | |
| 1628 } | |
| 1629 | |
| 1630 /** | |
| 1631 * Asserts that [recordedRelations] has an item with the expected properties. | |
| 1632 */ | |
| 1633 Location _assertRecordedRelation(Element expectedElement, | |
| 1634 Relationship expectedRelationship, ExpectedLocation expectedLocation) { | |
| 1635 for (RecordedRelation recordedRelation in recordedRelations) { | |
| 1636 if (_equalsRecordedRelation( | |
| 1637 recordedRelation, | |
| 1638 expectedElement, | |
| 1639 expectedRelationship, | |
| 1640 expectedLocation)) { | |
| 1641 return recordedRelation.location; | |
| 1642 } | |
| 1643 } | |
| 1644 fail( | |
| 1645 "not found\n$expectedElement $expectedRelationship " "in $expectedLocati
on in\n" | |
| 1646 + | |
| 1647 recordedRelations.join('\n')); | |
| 1648 return null; | |
| 1649 } | |
| 1650 | |
| 1651 ExpectedLocation _expectedLocation(Element element, String search, | |
| 1652 {int length: -1, bool isQualified: false, bool isResolved: true}) { | |
| 1653 int offset = findOffset(search); | |
| 1654 if (length == -1) { | |
| 1655 length = getLeadingIdentifierLength(search); | |
| 1656 } | |
| 1657 return new ExpectedLocation( | |
| 1658 element, | |
| 1659 offset, | |
| 1660 length, | |
| 1661 isQualified, | |
| 1662 isResolved); | |
| 1663 } | |
| 1664 | |
| 1665 ExpectedLocation _expectedLocationQ(Element element, String search, | |
| 1666 {int length: -1}) { | |
| 1667 return _expectedLocation( | |
| 1668 element, | |
| 1669 search, | |
| 1670 length: length, | |
| 1671 isQualified: true); | |
| 1672 } | |
| 1673 | |
| 1674 ExpectedLocation _expectedLocationQU(Element element, String search, | |
| 1675 {int length: -1}) { | |
| 1676 return _expectedLocation( | |
| 1677 element, | |
| 1678 search, | |
| 1679 length: length, | |
| 1680 isQualified: true, | |
| 1681 isResolved: false); | |
| 1682 } | |
| 1683 | |
| 1684 void _indexTestUnit(String code) { | |
| 1685 resolveTestUnit(code); | |
| 1686 indexDartUnit(store, context, testUnit); | |
| 1687 } | |
| 1688 } | |
| 1689 | |
| 1690 class ExpectedLocation { | |
| 1691 Element element; | |
| 1692 int offset; | |
| 1693 int length; | |
| 1694 bool isQualified; | |
| 1695 bool isResolved; | |
| 1696 | |
| 1697 ExpectedLocation(this.element, this.offset, this.length, this.isQualified, | |
| 1698 this.isResolved); | |
| 1699 | |
| 1700 @override | |
| 1701 String toString() { | |
| 1702 return 'ExpectedLocation(element=$element; offset=$offset; length=$length;' | |
| 1703 ' isQualified=$isQualified isResolved=$isResolved)'; | |
| 1704 } | |
| 1705 } | |
| 1706 | |
| 1707 class MockIndexStore extends TypedMock implements IndexStore { | |
| 1708 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); | |
| 1709 } | |
| 1710 | |
| 1711 | |
| 1712 /** | |
| 1713 * Information about a relation recorded into {@link IndexStore}. | |
| 1714 */ | |
| 1715 class RecordedRelation { | |
| 1716 final Element element; | |
| 1717 final Relationship relationship; | |
| 1718 final Location location; | |
| 1719 | |
| 1720 RecordedRelation(this.element, this.relationship, this.location); | |
| 1721 | |
| 1722 @override | |
| 1723 String toString() { | |
| 1724 return 'RecordedRelation(element=$element; relationship=$relationship; ' | |
| 1725 'location=$location; flags=' '${location.isQualified ? "Q" : ""}' | |
| 1726 '${location.isResolved ? "R" : ""})'; | |
| 1727 } | |
| 1728 } | |
| OLD | NEW |