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