| 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.search.search_engine2; | |
| 6 | |
| 7 import 'dart:async'; | |
| 8 | |
| 9 import 'package:analysis_server/src/services/index2/index2.dart'; | |
| 10 import 'package:analysis_server/src/services/search/search_engine.dart'; | |
| 11 import 'package:analysis_server/src/services/search/search_engine_internal2.dart
'; | |
| 12 import 'package:analyzer/dart/element/element.dart'; | |
| 13 import 'package:analyzer/src/dart/element/element.dart'; | |
| 14 import 'package:analyzer/src/dart/element/member.dart'; | |
| 15 import 'package:analyzer/src/generated/source.dart'; | |
| 16 import 'package:test_reflective_loader/test_reflective_loader.dart'; | |
| 17 import 'package:unittest/unittest.dart'; | |
| 18 | |
| 19 import '../../abstract_single_unit.dart'; | |
| 20 import '../../utils.dart'; | |
| 21 | |
| 22 main() { | |
| 23 initializeTestEnvironment(); | |
| 24 defineReflectiveTests(SearchEngineImpl2Test); | |
| 25 } | |
| 26 | |
| 27 class ExpectedMatch { | |
| 28 final Element element; | |
| 29 final MatchKind kind; | |
| 30 SourceRange range; | |
| 31 final bool isResolved; | |
| 32 final bool isQualified; | |
| 33 | |
| 34 ExpectedMatch(this.element, this.kind, int offset, int length, | |
| 35 {this.isResolved: true, this.isQualified: false}) { | |
| 36 this.range = new SourceRange(offset, length); | |
| 37 } | |
| 38 | |
| 39 bool operator ==(SearchMatch match) { | |
| 40 return match.element == this.element && | |
| 41 match.kind == this.kind && | |
| 42 match.isResolved == this.isResolved && | |
| 43 match.isQualified == this.isQualified && | |
| 44 match.sourceRange == this.range; | |
| 45 } | |
| 46 | |
| 47 @override | |
| 48 String toString() { | |
| 49 StringBuffer buffer = new StringBuffer(); | |
| 50 buffer.write("ExpectedMatch(kind="); | |
| 51 buffer.write(kind); | |
| 52 buffer.write(", element="); | |
| 53 buffer.write(element != null ? element.displayName : 'null'); | |
| 54 buffer.write(", range="); | |
| 55 buffer.write(range); | |
| 56 buffer.write(", isResolved="); | |
| 57 buffer.write(isResolved); | |
| 58 buffer.write(", isQualified="); | |
| 59 buffer.write(isQualified); | |
| 60 buffer.write(")"); | |
| 61 return buffer.toString(); | |
| 62 } | |
| 63 } | |
| 64 | |
| 65 @reflectiveTest | |
| 66 class SearchEngineImpl2Test extends AbstractSingleUnitTest { | |
| 67 Index2 index; | |
| 68 SearchEngineImpl2 searchEngine; | |
| 69 | |
| 70 void setUp() { | |
| 71 super.setUp(); | |
| 72 index = createMemoryIndex2(); | |
| 73 searchEngine = new SearchEngineImpl2(index); | |
| 74 } | |
| 75 | |
| 76 test_searchAllSubtypes() async { | |
| 77 _indexTestUnit(''' | |
| 78 class T {} | |
| 79 class A extends T {} | |
| 80 class B extends A {} | |
| 81 class C implements B {} | |
| 82 '''); | |
| 83 ClassElement element = findElement('T'); | |
| 84 ClassElement elementA = findElement('A'); | |
| 85 ClassElement elementB = findElement('B'); | |
| 86 ClassElement elementC = findElement('C'); | |
| 87 var expected = [ | |
| 88 _expectId(elementA, MatchKind.DECLARATION, 'A extends T'), | |
| 89 _expectId(elementB, MatchKind.DECLARATION, 'B extends A'), | |
| 90 _expectId(elementC, MatchKind.DECLARATION, 'C implements B') | |
| 91 ]; | |
| 92 List<SearchMatch> matches = await searchEngine.searchAllSubtypes(element); | |
| 93 _assertMatches(matches, expected); | |
| 94 } | |
| 95 | |
| 96 test_searchMemberDeclarations() async { | |
| 97 _indexTestUnit(''' | |
| 98 class A { | |
| 99 test() {} | |
| 100 } | |
| 101 class B { | |
| 102 int test = 1; | |
| 103 main() { | |
| 104 int test = 2; | |
| 105 } | |
| 106 } | |
| 107 '''); | |
| 108 ClassElement elementA = findElement('A'); | |
| 109 ClassElement elementB = findElement('B'); | |
| 110 var expected = [ | |
| 111 _expectId(elementA.methods[0], MatchKind.DECLARATION, 'test() {}'), | |
| 112 _expectId(elementB.fields[0], MatchKind.DECLARATION, 'test = 1;') | |
| 113 ]; | |
| 114 List<SearchMatch> matches = | |
| 115 await searchEngine.searchMemberDeclarations('test'); | |
| 116 _assertMatches(matches, expected); | |
| 117 } | |
| 118 | |
| 119 test_searchMemberReferences_qualified_resolved() async { | |
| 120 _indexTestUnit(''' | |
| 121 class C { | |
| 122 var test; | |
| 123 } | |
| 124 main(C c) { | |
| 125 print(c.test); | |
| 126 c.test = 1; | |
| 127 c.test += 2; | |
| 128 c.test(); | |
| 129 } | |
| 130 '''); | |
| 131 List<SearchMatch> matches = | |
| 132 await searchEngine.searchMemberReferences('test'); | |
| 133 expect(matches, isEmpty); | |
| 134 } | |
| 135 | |
| 136 test_searchMemberReferences_qualified_unresolved() async { | |
| 137 _indexTestUnit(''' | |
| 138 main(p) { | |
| 139 print(p.test); | |
| 140 p.test = 1; | |
| 141 p.test += 2; | |
| 142 p.test(); | |
| 143 } | |
| 144 '''); | |
| 145 Element main = findElement('main'); | |
| 146 var expected = [ | |
| 147 _expectIdQU(main, MatchKind.READ, 'test);'), | |
| 148 _expectIdQU(main, MatchKind.WRITE, 'test = 1;'), | |
| 149 _expectIdQU(main, MatchKind.READ_WRITE, 'test += 2;'), | |
| 150 _expectIdQU(main, MatchKind.INVOCATION, 'test();'), | |
| 151 ]; | |
| 152 List<SearchMatch> matches = | |
| 153 await searchEngine.searchMemberReferences('test'); | |
| 154 _assertMatches(matches, expected); | |
| 155 } | |
| 156 | |
| 157 test_searchMemberReferences_unqualified_resolved() async { | |
| 158 _indexTestUnit(''' | |
| 159 class C { | |
| 160 var test; | |
| 161 main() { | |
| 162 print(test); | |
| 163 test = 1; | |
| 164 test += 2; | |
| 165 test(); | |
| 166 } | |
| 167 } | |
| 168 '''); | |
| 169 List<SearchMatch> matches = | |
| 170 await searchEngine.searchMemberReferences('test'); | |
| 171 expect(matches, isEmpty); | |
| 172 } | |
| 173 | |
| 174 test_searchMemberReferences_unqualified_unresolved() async { | |
| 175 verifyNoTestUnitErrors = false; | |
| 176 _indexTestUnit(''' | |
| 177 class C { | |
| 178 main() { | |
| 179 print(test); | |
| 180 test = 1; | |
| 181 test += 2; | |
| 182 test(); | |
| 183 } | |
| 184 } | |
| 185 '''); | |
| 186 Element main = findElement('main'); | |
| 187 var expected = [ | |
| 188 _expectIdU(main, MatchKind.READ, 'test);'), | |
| 189 _expectIdU(main, MatchKind.WRITE, 'test = 1;'), | |
| 190 _expectIdU(main, MatchKind.READ_WRITE, 'test += 2;'), | |
| 191 _expectIdU(main, MatchKind.INVOCATION, 'test();'), | |
| 192 ]; | |
| 193 List<SearchMatch> matches = | |
| 194 await searchEngine.searchMemberReferences('test'); | |
| 195 _assertMatches(matches, expected); | |
| 196 } | |
| 197 | |
| 198 test_searchReferences_ClassElement() async { | |
| 199 _indexTestUnit(''' | |
| 200 class A {} | |
| 201 main(A p) { | |
| 202 A v; | |
| 203 } | |
| 204 '''); | |
| 205 ClassElement element = findElement('A'); | |
| 206 Element pElement = findElement('p'); | |
| 207 Element vElement = findElement('v'); | |
| 208 var expected = [ | |
| 209 _expectId(pElement, MatchKind.REFERENCE, 'A p'), | |
| 210 _expectId(vElement, MatchKind.REFERENCE, 'A v') | |
| 211 ]; | |
| 212 await _verifyReferences(element, expected); | |
| 213 } | |
| 214 | |
| 215 test_searchReferences_CompilationUnitElement() async { | |
| 216 addSource( | |
| 217 '/my_part.dart', | |
| 218 ''' | |
| 219 part of lib; | |
| 220 '''); | |
| 221 _indexTestUnit(''' | |
| 222 library lib; | |
| 223 part 'my_part.dart'; | |
| 224 '''); | |
| 225 CompilationUnitElement element = testLibraryElement.parts[0]; | |
| 226 var expected = [ | |
| 227 _expectIdQ(testUnitElement, MatchKind.REFERENCE, "'my_part.dart'", | |
| 228 length: "'my_part.dart'".length) | |
| 229 ]; | |
| 230 await _verifyReferences(element, expected); | |
| 231 } | |
| 232 | |
| 233 test_searchReferences_ConstructorElement() async { | |
| 234 _indexTestUnit(''' | |
| 235 class A { | |
| 236 A.named() {} | |
| 237 } | |
| 238 main() { | |
| 239 new A.named(); | |
| 240 } | |
| 241 '''); | |
| 242 ConstructorElement element = findElement('named'); | |
| 243 Element mainElement = findElement('main'); | |
| 244 var expected = [ | |
| 245 _expectIdQ(mainElement, MatchKind.REFERENCE, '.named();', length: 6) | |
| 246 ]; | |
| 247 await _verifyReferences(element, expected); | |
| 248 } | |
| 249 | |
| 250 test_searchReferences_ConstructorElement_synthetic() async { | |
| 251 _indexTestUnit(''' | |
| 252 class A { | |
| 253 } | |
| 254 main() { | |
| 255 new A(); | |
| 256 } | |
| 257 '''); | |
| 258 ClassElement classElement = findElement('A'); | |
| 259 ConstructorElement element = classElement.unnamedConstructor; | |
| 260 Element mainElement = findElement('main'); | |
| 261 var expected = [ | |
| 262 _expectIdQ(mainElement, MatchKind.REFERENCE, '();', length: 0) | |
| 263 ]; | |
| 264 await _verifyReferences(element, expected); | |
| 265 } | |
| 266 | |
| 267 test_searchReferences_Element_unknown() async { | |
| 268 await _verifyReferences(DynamicElementImpl.instance, []); | |
| 269 } | |
| 270 | |
| 271 test_searchReferences_FieldElement() async { | |
| 272 _indexTestUnit(''' | |
| 273 class A { | |
| 274 var field; | |
| 275 A({this.field}); | |
| 276 main() { | |
| 277 new A(field: 1); | |
| 278 // getter | |
| 279 print(field); // ref-nq | |
| 280 print(this.field); // ref-q | |
| 281 field(); // inv-nq | |
| 282 this.field(); // inv-q | |
| 283 // setter | |
| 284 field = 2; // ref-nq; | |
| 285 this.field = 3; // ref-q; | |
| 286 } | |
| 287 } | |
| 288 '''); | |
| 289 FieldElement element = findElement('field'); | |
| 290 Element main = findElement('main'); | |
| 291 Element fieldParameter = findElement('field', ElementKind.PARAMETER); | |
| 292 var expected = [ | |
| 293 _expectIdQ(fieldParameter, MatchKind.WRITE, 'field}'), | |
| 294 _expectIdQ(main, MatchKind.REFERENCE, 'field: 1'), | |
| 295 _expectId(main, MatchKind.READ, 'field); // ref-nq'), | |
| 296 _expectIdQ(main, MatchKind.READ, 'field); // ref-q'), | |
| 297 _expectId(main, MatchKind.INVOCATION, 'field(); // inv-nq'), | |
| 298 _expectIdQ(main, MatchKind.INVOCATION, 'field(); // inv-q'), | |
| 299 _expectId(main, MatchKind.WRITE, 'field = 2; // ref-nq'), | |
| 300 _expectIdQ(main, MatchKind.WRITE, 'field = 3; // ref-q'), | |
| 301 ]; | |
| 302 await _verifyReferences(element, expected); | |
| 303 } | |
| 304 | |
| 305 test_searchReferences_FieldElement_ofEnum() async { | |
| 306 _indexTestUnit(''' | |
| 307 enum MyEnum { | |
| 308 A, B, C | |
| 309 } | |
| 310 main() { | |
| 311 print(MyEnum.A.index); | |
| 312 print(MyEnum.values); | |
| 313 print(MyEnum.A); | |
| 314 print(MyEnum.B); | |
| 315 } | |
| 316 '''); | |
| 317 ClassElement enumElement = findElement('MyEnum'); | |
| 318 Element mainElement = findElement('main'); | |
| 319 await _verifyReferences(enumElement.getField('index'), | |
| 320 [_expectIdQ(mainElement, MatchKind.READ, 'index);')]); | |
| 321 await _verifyReferences(enumElement.getField('values'), | |
| 322 [_expectIdQ(mainElement, MatchKind.READ, 'values);')]); | |
| 323 await _verifyReferences(enumElement.getField('A'), [ | |
| 324 _expectIdQ(mainElement, MatchKind.READ, 'A.index);'), | |
| 325 _expectIdQ(mainElement, MatchKind.READ, 'A);') | |
| 326 ]); | |
| 327 await _verifyReferences(enumElement.getField('B'), | |
| 328 [_expectIdQ(mainElement, MatchKind.READ, 'B);')]); | |
| 329 } | |
| 330 | |
| 331 test_searchReferences_FieldElement_synthetic() async { | |
| 332 _indexTestUnit(''' | |
| 333 class A { | |
| 334 get field => null; | |
| 335 set field(x) {} | |
| 336 main() { | |
| 337 // getter | |
| 338 print(field); // ref-nq | |
| 339 print(this.field); // ref-q | |
| 340 field(); // inv-nq | |
| 341 this.field(); // inv-q | |
| 342 // setter | |
| 343 field = 2; // ref-nq; | |
| 344 this.field = 3; // ref-q; | |
| 345 } | |
| 346 } | |
| 347 '''); | |
| 348 FieldElement element = findElement('field', ElementKind.FIELD); | |
| 349 Element main = findElement('main'); | |
| 350 var expected = [ | |
| 351 _expectId(main, MatchKind.READ, 'field); // ref-nq'), | |
| 352 _expectIdQ(main, MatchKind.READ, 'field); // ref-q'), | |
| 353 _expectId(main, MatchKind.INVOCATION, 'field(); // inv-nq'), | |
| 354 _expectIdQ(main, MatchKind.INVOCATION, 'field(); // inv-q'), | |
| 355 _expectId(main, MatchKind.WRITE, 'field = 2; // ref-nq'), | |
| 356 _expectIdQ(main, MatchKind.WRITE, 'field = 3; // ref-q'), | |
| 357 ]; | |
| 358 await _verifyReferences(element, expected); | |
| 359 } | |
| 360 | |
| 361 test_searchReferences_FunctionElement() async { | |
| 362 _indexTestUnit(''' | |
| 363 test() {} | |
| 364 main() { | |
| 365 test(); | |
| 366 print(test); | |
| 367 } | |
| 368 '''); | |
| 369 FunctionElement element = findElement('test'); | |
| 370 Element mainElement = findElement('main'); | |
| 371 var expected = [ | |
| 372 _expectId(mainElement, MatchKind.INVOCATION, 'test();'), | |
| 373 _expectId(mainElement, MatchKind.REFERENCE, 'test);') | |
| 374 ]; | |
| 375 await _verifyReferences(element, expected); | |
| 376 } | |
| 377 | |
| 378 test_searchReferences_FunctionElement_local() async { | |
| 379 _indexTestUnit(''' | |
| 380 main() { | |
| 381 test() {} | |
| 382 test(); | |
| 383 print(test); | |
| 384 } | |
| 385 '''); | |
| 386 FunctionElement element = findElement('test'); | |
| 387 Element mainElement = findElement('main'); | |
| 388 var expected = [ | |
| 389 _expectId(mainElement, MatchKind.INVOCATION, 'test();'), | |
| 390 _expectId(mainElement, MatchKind.REFERENCE, 'test);') | |
| 391 ]; | |
| 392 await _verifyReferences(element, expected); | |
| 393 } | |
| 394 | |
| 395 test_searchReferences_FunctionTypeAliasElement() async { | |
| 396 _indexTestUnit(''' | |
| 397 typedef Test(); | |
| 398 main() { | |
| 399 Test a; | |
| 400 Test b; | |
| 401 } | |
| 402 '''); | |
| 403 FunctionTypeAliasElement element = findElement('Test'); | |
| 404 Element aElement = findElement('a'); | |
| 405 Element bElement = findElement('b'); | |
| 406 var expected = [ | |
| 407 _expectId(aElement, MatchKind.REFERENCE, 'Test a;'), | |
| 408 _expectId(bElement, MatchKind.REFERENCE, 'Test b;') | |
| 409 ]; | |
| 410 await _verifyReferences(element, expected); | |
| 411 } | |
| 412 | |
| 413 test_searchReferences_ImportElement_noPrefix() async { | |
| 414 _indexTestUnit(''' | |
| 415 import 'dart:math' show max, PI, Random hide min; | |
| 416 export 'dart:math' show max, PI, Random hide min; | |
| 417 main() { | |
| 418 print(PI); | |
| 419 print(new Random()); | |
| 420 print(max(1, 2)); | |
| 421 } | |
| 422 Random bar() => null; | |
| 423 '''); | |
| 424 ImportElement element = testLibraryElement.imports[0]; | |
| 425 Element mainElement = findElement('main'); | |
| 426 Element barElement = findElement('bar'); | |
| 427 var kind = MatchKind.REFERENCE; | |
| 428 var expected = [ | |
| 429 _expectId(mainElement, kind, 'PI);', length: 0), | |
| 430 _expectId(mainElement, kind, 'Random()', length: 0), | |
| 431 _expectId(mainElement, kind, 'max(', length: 0), | |
| 432 _expectId(barElement, kind, 'Random bar()', length: 0), | |
| 433 ]; | |
| 434 await _verifyReferences(element, expected); | |
| 435 } | |
| 436 | |
| 437 test_searchReferences_ImportElement_withPrefix() async { | |
| 438 _indexTestUnit(''' | |
| 439 import 'dart:math' as math show max, PI, Random hide min; | |
| 440 export 'dart:math' show max, PI, Random hide min; | |
| 441 main() { | |
| 442 print(math.PI); | |
| 443 print(new math.Random()); | |
| 444 print(math.max(1, 2)); | |
| 445 } | |
| 446 math.Random bar() => null; | |
| 447 '''); | |
| 448 ImportElement element = testLibraryElement.imports[0]; | |
| 449 Element mainElement = findElement('main'); | |
| 450 Element barElement = findElement('bar'); | |
| 451 var kind = MatchKind.REFERENCE; | |
| 452 var length = 'math.'.length; | |
| 453 var expected = [ | |
| 454 _expectId(mainElement, kind, 'math.PI);', length: length), | |
| 455 _expectId(mainElement, kind, 'math.Random()', length: length), | |
| 456 _expectId(mainElement, kind, 'math.max(', length: length), | |
| 457 _expectId(barElement, kind, 'math.Random bar()', length: length), | |
| 458 ]; | |
| 459 await _verifyReferences(element, expected); | |
| 460 } | |
| 461 | |
| 462 test_searchReferences_LabelElement() async { | |
| 463 _indexTestUnit(''' | |
| 464 main() { | |
| 465 label: | |
| 466 while (true) { | |
| 467 if (true) { | |
| 468 break label; // 1 | |
| 469 } | |
| 470 break label; // 2 | |
| 471 } | |
| 472 } | |
| 473 '''); | |
| 474 LabelElement element = findElement('label'); | |
| 475 Element mainElement = findElement('main'); | |
| 476 var expected = [ | |
| 477 _expectId(mainElement, MatchKind.REFERENCE, 'label; // 1'), | |
| 478 _expectId(mainElement, MatchKind.REFERENCE, 'label; // 2') | |
| 479 ]; | |
| 480 await _verifyReferences(element, expected); | |
| 481 } | |
| 482 | |
| 483 test_searchReferences_LibraryElement() async { | |
| 484 var codeA = 'part of lib; // A'; | |
| 485 var codeB = 'part of lib; // B'; | |
| 486 addSource('/unitA.dart', codeA); | |
| 487 addSource('/unitB.dart', codeB); | |
| 488 _indexTestUnit(''' | |
| 489 library lib; | |
| 490 part 'unitA.dart'; | |
| 491 part 'unitB.dart'; | |
| 492 '''); | |
| 493 LibraryElement element = testLibraryElement; | |
| 494 CompilationUnitElement unitElementA = element.parts[0]; | |
| 495 CompilationUnitElement unitElementB = element.parts[1]; | |
| 496 index.indexUnit(unitElementA.computeNode()); | |
| 497 index.indexUnit(unitElementB.computeNode()); | |
| 498 var expected = [ | |
| 499 new ExpectedMatch(unitElementA, MatchKind.REFERENCE, | |
| 500 codeA.indexOf('lib; // A'), 'lib'.length), | |
| 501 new ExpectedMatch(unitElementB, MatchKind.REFERENCE, | |
| 502 codeB.indexOf('lib; // B'), 'lib'.length), | |
| 503 ]; | |
| 504 await _verifyReferences(element, expected); | |
| 505 } | |
| 506 | |
| 507 test_searchReferences_LocalVariableElement() async { | |
| 508 _indexTestUnit(''' | |
| 509 main() { | |
| 510 var v; | |
| 511 v = 1; | |
| 512 v += 2; | |
| 513 print(v); | |
| 514 v(); | |
| 515 } | |
| 516 '''); | |
| 517 LocalVariableElement element = findElement('v'); | |
| 518 Element mainElement = findElement('main'); | |
| 519 var expected = [ | |
| 520 _expectId(mainElement, MatchKind.WRITE, 'v = 1;'), | |
| 521 _expectId(mainElement, MatchKind.READ_WRITE, 'v += 2;'), | |
| 522 _expectId(mainElement, MatchKind.READ, 'v);'), | |
| 523 _expectId(mainElement, MatchKind.INVOCATION, 'v();') | |
| 524 ]; | |
| 525 await _verifyReferences(element, expected); | |
| 526 } | |
| 527 | |
| 528 test_searchReferences_MethodElement() async { | |
| 529 _indexTestUnit(''' | |
| 530 class A { | |
| 531 m() {} | |
| 532 main() { | |
| 533 m(); // 1 | |
| 534 this.m(); // 2 | |
| 535 print(m); // 3 | |
| 536 print(this.m); // 4 | |
| 537 } | |
| 538 } | |
| 539 '''); | |
| 540 MethodElement method = findElement('m'); | |
| 541 Element mainElement = findElement('main'); | |
| 542 var expected = [ | |
| 543 _expectId(mainElement, MatchKind.INVOCATION, 'm(); // 1'), | |
| 544 _expectIdQ(mainElement, MatchKind.INVOCATION, 'm(); // 2'), | |
| 545 _expectId(mainElement, MatchKind.REFERENCE, 'm); // 3'), | |
| 546 _expectIdQ(mainElement, MatchKind.REFERENCE, 'm); // 4') | |
| 547 ]; | |
| 548 await _verifyReferences(method, expected); | |
| 549 } | |
| 550 | |
| 551 test_searchReferences_MethodMember() async { | |
| 552 _indexTestUnit(''' | |
| 553 class A<T> { | |
| 554 T m() => null; | |
| 555 } | |
| 556 main(A<int> a) { | |
| 557 a.m(); // ref | |
| 558 } | |
| 559 '''); | |
| 560 MethodMember method = findNodeElementAtString('m(); // ref'); | |
| 561 Element mainElement = findElement('main'); | |
| 562 var expected = [ | |
| 563 _expectIdQ(mainElement, MatchKind.INVOCATION, 'm(); // ref') | |
| 564 ]; | |
| 565 await _verifyReferences(method, expected); | |
| 566 } | |
| 567 | |
| 568 test_searchReferences_ParameterElement_ofLocalFunction() async { | |
| 569 _indexTestUnit(''' | |
| 570 main() { | |
| 571 foo({p}) { | |
| 572 p = 1; | |
| 573 p += 2; | |
| 574 print(p); | |
| 575 p(); | |
| 576 } | |
| 577 foo(p: 42); | |
| 578 } | |
| 579 '''); | |
| 580 ParameterElement element = findElement('p'); | |
| 581 Element fooElement = findElement('foo'); | |
| 582 Element mainElement = findElement('main'); | |
| 583 var expected = [ | |
| 584 _expectId(fooElement, MatchKind.WRITE, 'p = 1;'), | |
| 585 _expectId(fooElement, MatchKind.READ_WRITE, 'p += 2;'), | |
| 586 _expectId(fooElement, MatchKind.READ, 'p);'), | |
| 587 _expectId(fooElement, MatchKind.INVOCATION, 'p();'), | |
| 588 _expectIdQ(mainElement, MatchKind.REFERENCE, 'p: 42') | |
| 589 ]; | |
| 590 await _verifyReferences(element, expected); | |
| 591 } | |
| 592 | |
| 593 test_searchReferences_ParameterElement_ofMethod() async { | |
| 594 _indexTestUnit(''' | |
| 595 class C { | |
| 596 foo({p}) { | |
| 597 p = 1; | |
| 598 p += 2; | |
| 599 print(p); | |
| 600 p(); | |
| 601 } | |
| 602 } | |
| 603 main(C c) { | |
| 604 c.foo(p: 42); | |
| 605 } | |
| 606 '''); | |
| 607 ParameterElement element = findElement('p'); | |
| 608 Element fooElement = findElement('foo'); | |
| 609 Element mainElement = findElement('main'); | |
| 610 var expected = [ | |
| 611 _expectId(fooElement, MatchKind.WRITE, 'p = 1;'), | |
| 612 _expectId(fooElement, MatchKind.READ_WRITE, 'p += 2;'), | |
| 613 _expectId(fooElement, MatchKind.READ, 'p);'), | |
| 614 _expectId(fooElement, MatchKind.INVOCATION, 'p();'), | |
| 615 _expectIdQ(mainElement, MatchKind.REFERENCE, 'p: 42') | |
| 616 ]; | |
| 617 await _verifyReferences(element, expected); | |
| 618 } | |
| 619 | |
| 620 test_searchReferences_ParameterElement_ofTopLevelFunction() async { | |
| 621 _indexTestUnit(''' | |
| 622 foo({p}) { | |
| 623 p = 1; | |
| 624 p += 2; | |
| 625 print(p); | |
| 626 p(); | |
| 627 } | |
| 628 main() { | |
| 629 foo(p: 42); | |
| 630 } | |
| 631 '''); | |
| 632 ParameterElement element = findElement('p'); | |
| 633 Element fooElement = findElement('foo'); | |
| 634 Element mainElement = findElement('main'); | |
| 635 var expected = [ | |
| 636 _expectId(fooElement, MatchKind.WRITE, 'p = 1;'), | |
| 637 _expectId(fooElement, MatchKind.READ_WRITE, 'p += 2;'), | |
| 638 _expectId(fooElement, MatchKind.READ, 'p);'), | |
| 639 _expectId(fooElement, MatchKind.INVOCATION, 'p();'), | |
| 640 _expectIdQ(mainElement, MatchKind.REFERENCE, 'p: 42') | |
| 641 ]; | |
| 642 await _verifyReferences(element, expected); | |
| 643 } | |
| 644 | |
| 645 test_searchReferences_PrefixElement() async { | |
| 646 _indexTestUnit(''' | |
| 647 import 'dart:async' as ppp; | |
| 648 main() { | |
| 649 ppp.Future a; | |
| 650 ppp.Stream b; | |
| 651 } | |
| 652 '''); | |
| 653 PrefixElement element = findNodeElementAtString('ppp;'); | |
| 654 Element elementA = findElement('a'); | |
| 655 Element elementB = findElement('b'); | |
| 656 var expected = [ | |
| 657 _expectId(elementA, MatchKind.REFERENCE, 'ppp.Future'), | |
| 658 _expectId(elementB, MatchKind.REFERENCE, 'ppp.Stream') | |
| 659 ]; | |
| 660 await _verifyReferences(element, expected); | |
| 661 } | |
| 662 | |
| 663 test_searchReferences_PropertyAccessorElement_getter() async { | |
| 664 _indexTestUnit(''' | |
| 665 class A { | |
| 666 get ggg => null; | |
| 667 main() { | |
| 668 print(ggg); // ref-nq | |
| 669 print(this.ggg); // ref-q | |
| 670 ggg(); // inv-nq | |
| 671 this.ggg(); // inv-q | |
| 672 } | |
| 673 } | |
| 674 '''); | |
| 675 PropertyAccessorElement element = findElement('ggg', ElementKind.GETTER); | |
| 676 Element main = findElement('main'); | |
| 677 var expected = [ | |
| 678 _expectId(main, MatchKind.REFERENCE, 'ggg); // ref-nq'), | |
| 679 _expectIdQ(main, MatchKind.REFERENCE, 'ggg); // ref-q'), | |
| 680 _expectId(main, MatchKind.INVOCATION, 'ggg(); // inv-nq'), | |
| 681 _expectIdQ(main, MatchKind.INVOCATION, 'ggg(); // inv-q'), | |
| 682 ]; | |
| 683 await _verifyReferences(element, expected); | |
| 684 } | |
| 685 | |
| 686 test_searchReferences_PropertyAccessorElement_setter() async { | |
| 687 _indexTestUnit(''' | |
| 688 class A { | |
| 689 set s(x) {} | |
| 690 main() { | |
| 691 s = 1; | |
| 692 this.s = 2; | |
| 693 } | |
| 694 } | |
| 695 '''); | |
| 696 PropertyAccessorElement element = findElement('s='); | |
| 697 Element mainElement = findElement('main'); | |
| 698 var expected = [ | |
| 699 _expectId(mainElement, MatchKind.REFERENCE, 's = 1'), | |
| 700 _expectIdQ(mainElement, MatchKind.REFERENCE, 's = 2') | |
| 701 ]; | |
| 702 await _verifyReferences(element, expected); | |
| 703 } | |
| 704 | |
| 705 test_searchReferences_TopLevelVariableElement() async { | |
| 706 addSource( | |
| 707 '/lib.dart', | |
| 708 ''' | |
| 709 library lib; | |
| 710 var V; | |
| 711 '''); | |
| 712 _indexTestUnit(''' | |
| 713 import 'lib.dart' show V; // imp | |
| 714 import 'lib.dart' as pref; | |
| 715 main() { | |
| 716 pref.V = 1; // q | |
| 717 print(pref.V); // q | |
| 718 pref.V(); // q | |
| 719 V = 1; // nq | |
| 720 print(V); // nq | |
| 721 V(); // nq | |
| 722 } | |
| 723 '''); | |
| 724 ImportElement importElement = testLibraryElement.imports[0]; | |
| 725 CompilationUnitElement impUnit = | |
| 726 importElement.importedLibrary.definingCompilationUnit; | |
| 727 TopLevelVariableElement variable = impUnit.topLevelVariables[0]; | |
| 728 Element main = findElement('main'); | |
| 729 var expected = [ | |
| 730 _expectIdQ(testUnitElement, MatchKind.REFERENCE, 'V; // imp'), | |
| 731 _expectIdQ(main, MatchKind.WRITE, 'V = 1; // q'), | |
| 732 _expectIdQ(main, MatchKind.READ, 'V); // q'), | |
| 733 _expectIdQ(main, MatchKind.INVOCATION, 'V(); // q'), | |
| 734 _expectId(main, MatchKind.WRITE, 'V = 1; // nq'), | |
| 735 _expectId(main, MatchKind.READ, 'V); // nq'), | |
| 736 _expectId(main, MatchKind.INVOCATION, 'V(); // nq'), | |
| 737 ]; | |
| 738 await _verifyReferences(variable, expected); | |
| 739 } | |
| 740 | |
| 741 test_searchReferences_TypeParameterElement() async { | |
| 742 _indexTestUnit(''' | |
| 743 class A<T> { | |
| 744 main(T a, T b) {} | |
| 745 } | |
| 746 '''); | |
| 747 TypeParameterElement element = findElement('T'); | |
| 748 Element aElement = findElement('a'); | |
| 749 Element bElement = findElement('b'); | |
| 750 var expected = [ | |
| 751 _expectId(aElement, MatchKind.REFERENCE, 'T a'), | |
| 752 _expectId(bElement, MatchKind.REFERENCE, 'T b') | |
| 753 ]; | |
| 754 await _verifyReferences(element, expected); | |
| 755 } | |
| 756 | |
| 757 test_searchSubtypes() async { | |
| 758 _indexTestUnit(''' | |
| 759 class T {} | |
| 760 class A extends T {} // A | |
| 761 class B = Object with T; // B | |
| 762 class C implements T {} // C | |
| 763 '''); | |
| 764 ClassElement element = findElement('T'); | |
| 765 ClassElement elementA = findElement('A'); | |
| 766 ClassElement elementB = findElement('B'); | |
| 767 ClassElement elementC = findElement('C'); | |
| 768 var expected = [ | |
| 769 _expectId(elementA, MatchKind.REFERENCE, 'T {} // A'), | |
| 770 _expectId(elementB, MatchKind.REFERENCE, 'T; // B'), | |
| 771 _expectId(elementC, MatchKind.REFERENCE, 'T {} // C') | |
| 772 ]; | |
| 773 List<SearchMatch> matches = await searchEngine.searchSubtypes(element); | |
| 774 _assertMatches(matches, expected); | |
| 775 } | |
| 776 | |
| 777 test_searchTopLevelDeclarations() async { | |
| 778 _indexTestUnit(''' | |
| 779 class A {} // A | |
| 780 class B = Object with A; | |
| 781 typedef C(); | |
| 782 D() {} | |
| 783 var E = null; | |
| 784 class NoMatchABCDE {} | |
| 785 '''); | |
| 786 Element topA = findElement('A'); | |
| 787 Element topB = findElement('B'); | |
| 788 Element topC = findElement('C'); | |
| 789 Element topD = findElement('D'); | |
| 790 Element topE = findElement('E'); | |
| 791 var expected = [ | |
| 792 _expectId(topA, MatchKind.DECLARATION, 'A {} // A'), | |
| 793 _expectId(topB, MatchKind.DECLARATION, 'B ='), | |
| 794 _expectId(topC, MatchKind.DECLARATION, 'C()'), | |
| 795 _expectId(topD, MatchKind.DECLARATION, 'D() {}'), | |
| 796 _expectId(topE, MatchKind.DECLARATION, 'E = null') | |
| 797 ]; | |
| 798 List<SearchMatch> matches = | |
| 799 await searchEngine.searchTopLevelDeclarations(r'^[A-E]$'); | |
| 800 _assertMatches(matches, expected); | |
| 801 } | |
| 802 | |
| 803 ExpectedMatch _expectId(Element element, MatchKind kind, String search, | |
| 804 {int length, bool isResolved: true, bool isQualified: false}) { | |
| 805 int offset = findOffset(search); | |
| 806 if (length == null) { | |
| 807 length = getLeadingIdentifierLength(search); | |
| 808 } | |
| 809 return new ExpectedMatch(element, kind, offset, length, | |
| 810 isResolved: isResolved, isQualified: isQualified); | |
| 811 } | |
| 812 | |
| 813 /** | |
| 814 * Create [ExpectedMatch] for a qualified and resolved match. | |
| 815 */ | |
| 816 ExpectedMatch _expectIdQ(Element element, MatchKind kind, String search, | |
| 817 {int length, bool isResolved: true}) { | |
| 818 return _expectId(element, kind, search, isQualified: true, length: length); | |
| 819 } | |
| 820 | |
| 821 /** | |
| 822 * Create [ExpectedMatch] for a qualified and unresolved match. | |
| 823 */ | |
| 824 ExpectedMatch _expectIdQU(Element element, MatchKind kind, String search, | |
| 825 {int length}) { | |
| 826 return _expectId(element, kind, search, | |
| 827 isQualified: true, isResolved: false, length: length); | |
| 828 } | |
| 829 | |
| 830 /** | |
| 831 * Create [ExpectedMatch] for a unqualified and unresolved match. | |
| 832 */ | |
| 833 ExpectedMatch _expectIdU(Element element, MatchKind kind, String search, | |
| 834 {int length}) { | |
| 835 return _expectId(element, kind, search, | |
| 836 isQualified: false, isResolved: false, length: length); | |
| 837 } | |
| 838 | |
| 839 void _indexTestUnit(String code) { | |
| 840 resolveTestUnit(code); | |
| 841 index.indexUnit(testUnit); | |
| 842 } | |
| 843 | |
| 844 Future _verifyReferences( | |
| 845 Element element, List<ExpectedMatch> expectedMatches) async { | |
| 846 List<SearchMatch> matches = await searchEngine.searchReferences(element); | |
| 847 _assertMatches(matches, expectedMatches); | |
| 848 expect(matches, hasLength(expectedMatches.length)); | |
| 849 } | |
| 850 | |
| 851 static void _assertMatches( | |
| 852 List<SearchMatch> matches, List<ExpectedMatch> expectedMatches) { | |
| 853 expect(matches, unorderedEquals(expectedMatches)); | |
| 854 } | |
| 855 } | |
| OLD | NEW |