| 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.search.element_references; |
| 6 |
| 7 import 'dart:async'; |
| 8 |
| 9 import 'package:analysis_server/src/computer/element.dart'; |
| 10 import 'package:analysis_server/src/constants.dart'; |
| 11 import 'package:analysis_server/src/protocol.dart'; |
| 12 import 'package:analysis_server/src/search/search_domain.dart'; |
| 13 import 'package:analysis_server/src/search/search_result.dart'; |
| 14 import 'package:analysis_services/index/index.dart' show Index; |
| 15 import 'package:analysis_services/index/local_memory_index.dart'; |
| 16 import 'package:analysis_testing/reflective_tests.dart'; |
| 17 import 'package:unittest/unittest.dart'; |
| 18 |
| 19 import '../analysis_abstract.dart'; |
| 20 |
| 21 |
| 22 main() { |
| 23 groupSep = ' | '; |
| 24 group('findElementReferences', () { |
| 25 runReflectiveTests(ElementReferencesTest); |
| 26 }); |
| 27 } |
| 28 |
| 29 |
| 30 @ReflectiveTestCase() |
| 31 class ElementReferencesTest extends AbstractAnalysisTest { |
| 32 String searchId; |
| 33 bool searchDone = false; |
| 34 List<SearchResult> results = <SearchResult>[]; |
| 35 SearchResult result; |
| 36 |
| 37 void assertHasResult(SearchResultKind kind, String search, [int length]) { |
| 38 int offset = findOffset(search); |
| 39 if (length == null) { |
| 40 length = findIdentifierLength(search); |
| 41 } |
| 42 findResult(kind, testFile, offset, length, true); |
| 43 } |
| 44 |
| 45 void assertNoResult(SearchResultKind kind, String search, [int length]) { |
| 46 int offset = findOffset(search); |
| 47 if (length == null) { |
| 48 length = findIdentifierLength(search); |
| 49 } |
| 50 findResult(kind, testFile, offset, length, false); |
| 51 } |
| 52 |
| 53 @override |
| 54 Index createIndex() { |
| 55 return createLocalMemoryIndex(); |
| 56 } |
| 57 |
| 58 fail_test_hierarchyMembers_field_explicit() { |
| 59 // TODO(scheglov) implement |
| 60 addTestFile(''' |
| 61 class A { |
| 62 int fff; // in A |
| 63 } |
| 64 class B extends A { |
| 65 int fff; // in B |
| 66 } |
| 67 class C extends B { |
| 68 int fff; // in C |
| 69 } |
| 70 main(A a, B b, C c) { |
| 71 a.fff = 10; |
| 72 b.fff = 20; |
| 73 c.fff = 30; |
| 74 } |
| 75 '''); |
| 76 return findElementReferences('fff; // in B', false).then((_) { |
| 77 assertHasResult(SearchResultKind.DECLARATION, 'fff; // in A'); |
| 78 assertHasResult(SearchResultKind.DECLARATION, 'fff; // in B'); |
| 79 assertHasResult(SearchResultKind.DECLARATION, 'fff; // in C'); |
| 80 assertHasResult(SearchResultKind.WRITE, 'fff = 10;'); |
| 81 assertHasResult(SearchResultKind.WRITE, 'fff = 20;'); |
| 82 assertHasResult(SearchResultKind.WRITE, 'fff = 30;'); |
| 83 }); |
| 84 } |
| 85 |
| 86 fail_test_hierarchyMembers_method() { |
| 87 // TODO(scheglov) implement |
| 88 addTestFile(''' |
| 89 class A { |
| 90 mmm() {} // in A |
| 91 } |
| 92 class B extends A { |
| 93 mmm() {} // in B |
| 94 } |
| 95 class C extends B { |
| 96 mmm() {} // in C |
| 97 } |
| 98 main(A a, B b, C c) { |
| 99 a.mmm(10); |
| 100 b.mmm(20); |
| 101 c.mmm(30); |
| 102 } |
| 103 '''); |
| 104 return findElementReferences('mmm() {} // in B', false).then((_) { |
| 105 assertHasResult(SearchResultKind.INVOCATION, 'mmm(10)'); |
| 106 assertHasResult(SearchResultKind.INVOCATION, 'mmm(20)'); |
| 107 assertHasResult(SearchResultKind.INVOCATION, 'mmm(30)'); |
| 108 }); |
| 109 } |
| 110 |
| 111 Future findElementReferences(String search, bool includePotential) { |
| 112 int offset = findOffset(search); |
| 113 return waitForTasksFinished().then((_) { |
| 114 Request request = new Request('0', SEARCH_FIND_ELEMENT_REFERENCES); |
| 115 request.setParameter(FILE, testFile); |
| 116 request.setParameter(OFFSET, offset); |
| 117 request.setParameter(INCLUDE_POTENTIAL, includePotential); |
| 118 Response response = handleSuccessfulRequest(request); |
| 119 searchId = response.getResult(ID); |
| 120 results.clear(); |
| 121 return _waitForSearchResults(); |
| 122 }); |
| 123 } |
| 124 |
| 125 void findResult(SearchResultKind kind, String file, int offset, int length, |
| 126 bool expected) { |
| 127 for (SearchResult result in results) { |
| 128 Location location = result.location; |
| 129 if (result.kind == kind && |
| 130 location.file == file && |
| 131 location.offset == offset && |
| 132 location.length == length) { |
| 133 if (!expected) { |
| 134 fail('Unexpected result $result in\n' + results.join('\n')); |
| 135 } |
| 136 this.result = result; |
| 137 return; |
| 138 } |
| 139 } |
| 140 if (expected) { |
| 141 fail( |
| 142 'Not found: "search" kind=$kind offset=$offset length=$length\nin\n' + |
| 143 results.join('\n')); |
| 144 } |
| 145 } |
| 146 |
| 147 String getPathString(List<Element> path) { |
| 148 return path.map((Element element) { |
| 149 return '${element.kind} ${element.name}'; |
| 150 }).join('\n'); |
| 151 } |
| 152 |
| 153 void processNotification(Notification notification) { |
| 154 if (notification.event == SEARCH_RESULTS) { |
| 155 String id = notification.getParameter(ID); |
| 156 if (id == searchId) { |
| 157 for (Map<String, Object> json in notification.getParameter(RESULTS)) { |
| 158 results.add(new SearchResult.fromJson(json)); |
| 159 } |
| 160 searchDone = notification.getParameter(LAST); |
| 161 } |
| 162 } |
| 163 } |
| 164 |
| 165 @override |
| 166 void setUp() { |
| 167 super.setUp(); |
| 168 createProject(); |
| 169 handler = new SearchDomainHandler(server); |
| 170 } |
| 171 |
| 172 test_constructor_named() { |
| 173 addTestFile(''' |
| 174 class A { |
| 175 A.named(p); |
| 176 } |
| 177 main() { |
| 178 new A.named(1); |
| 179 new A.named(2); |
| 180 } |
| 181 '''); |
| 182 return findElementReferences('named(p)', false).then((_) { |
| 183 assertHasResult(SearchResultKind.REFERENCE, '.named(1)', 6); |
| 184 assertHasResult(SearchResultKind.REFERENCE, '.named(2)', 6); |
| 185 }); |
| 186 } |
| 187 |
| 188 test_constructor_unamed() { |
| 189 addTestFile(''' |
| 190 class A { |
| 191 A(p); |
| 192 } |
| 193 main() { |
| 194 new A(1); |
| 195 new A(2); |
| 196 } |
| 197 '''); |
| 198 return findElementReferences('A(p)', false).then((_) { |
| 199 assertHasResult(SearchResultKind.REFERENCE, '(1)', 0); |
| 200 assertHasResult(SearchResultKind.REFERENCE, '(2)', 0); |
| 201 }); |
| 202 } |
| 203 |
| 204 test_field_explicit() { |
| 205 addTestFile(''' |
| 206 class A { |
| 207 var fff; // declaration |
| 208 A(this.fff); // in constructor |
| 209 m() { |
| 210 fff = 2; |
| 211 fff += 3; |
| 212 print(fff); // in m() |
| 213 fff(); // in m() |
| 214 } |
| 215 } |
| 216 main(A a) { |
| 217 a.fff = 20; |
| 218 a.fff += 30; |
| 219 print(a.fff); // in main() |
| 220 a.fff(); // in main() |
| 221 } |
| 222 '''); |
| 223 return findElementReferences('fff; // declaration', false).then((_) { |
| 224 expect(results, hasLength(10)); |
| 225 assertHasResult(SearchResultKind.DECLARATION, 'fff; // declaration'); |
| 226 assertHasResult(SearchResultKind.REFERENCE, 'fff); // in constructor'); |
| 227 // m() |
| 228 assertHasResult(SearchResultKind.WRITE, 'fff = 2;'); |
| 229 assertHasResult(SearchResultKind.WRITE, 'fff += 3;'); |
| 230 assertHasResult(SearchResultKind.READ, 'fff); // in m()'); |
| 231 assertHasResult(SearchResultKind.INVOCATION, 'fff(); // in m()'); |
| 232 // main() |
| 233 assertHasResult(SearchResultKind.WRITE, 'fff = 20;'); |
| 234 assertHasResult(SearchResultKind.WRITE, 'fff += 30;'); |
| 235 assertHasResult(SearchResultKind.READ, 'fff); // in main()'); |
| 236 assertHasResult(SearchResultKind.INVOCATION, 'fff(); // in main()'); |
| 237 }); |
| 238 } |
| 239 |
| 240 test_field_implicit() { |
| 241 addTestFile(''' |
| 242 class A { |
| 243 var get fff => null; |
| 244 void set fff(x) {} |
| 245 m() { |
| 246 print(fff); // in m() |
| 247 fff = 1; |
| 248 } |
| 249 } |
| 250 main(A a) { |
| 251 print(a.fff); // in main() |
| 252 a.fff = 10; |
| 253 } |
| 254 '''); |
| 255 var forGetter = findElementReferences('fff =>', false).then((_) { |
| 256 expect(results, hasLength(4)); |
| 257 assertHasResult(SearchResultKind.READ, 'fff); // in m()'); |
| 258 assertHasResult(SearchResultKind.WRITE, 'fff = 1;'); |
| 259 assertHasResult(SearchResultKind.READ, 'fff); // in main()'); |
| 260 assertHasResult(SearchResultKind.WRITE, 'fff = 10;'); |
| 261 }); |
| 262 var forSetter = findElementReferences('fff(x) {}', false).then((_) { |
| 263 expect(results, hasLength(4)); |
| 264 assertHasResult(SearchResultKind.READ, 'fff); // in m()'); |
| 265 assertHasResult(SearchResultKind.WRITE, 'fff = 1;'); |
| 266 assertHasResult(SearchResultKind.READ, 'fff); // in main()'); |
| 267 assertHasResult(SearchResultKind.WRITE, 'fff = 10;'); |
| 268 }); |
| 269 return Future.wait([forGetter, forSetter]); |
| 270 } |
| 271 |
| 272 test_field_inFormalParameter() { |
| 273 addTestFile(''' |
| 274 class A { |
| 275 var fff; // declaration |
| 276 A(this.fff); // in constructor |
| 277 m() { |
| 278 fff = 2; |
| 279 print(fff); // in m() |
| 280 } |
| 281 } |
| 282 '''); |
| 283 return findElementReferences('fff); // in constructor', false).then((_) { |
| 284 expect(results, hasLength(4)); |
| 285 assertHasResult(SearchResultKind.DECLARATION, 'fff; // declaration'); |
| 286 assertHasResult(SearchResultKind.REFERENCE, 'fff); // in constructor'); |
| 287 assertHasResult(SearchResultKind.WRITE, 'fff = 2;'); |
| 288 assertHasResult(SearchResultKind.READ, 'fff); // in m()'); |
| 289 }); |
| 290 } |
| 291 |
| 292 test_function() { |
| 293 addTestFile(''' |
| 294 fff(p) {} |
| 295 main() { |
| 296 fff(1); |
| 297 print(fff); |
| 298 } |
| 299 '''); |
| 300 return findElementReferences('fff(p) {}', false).then((_) { |
| 301 expect(results, hasLength(2)); |
| 302 assertHasResult(SearchResultKind.INVOCATION, 'fff(1)'); |
| 303 assertHasResult(SearchResultKind.REFERENCE, 'fff);'); |
| 304 }); |
| 305 } |
| 306 |
| 307 test_localVariable() { |
| 308 addTestFile(''' |
| 309 main() { |
| 310 var vvv = 1; |
| 311 print(vvv); |
| 312 vvv += 3; |
| 313 vvv = 2; |
| 314 vvv(); |
| 315 } |
| 316 '''); |
| 317 return findElementReferences('vvv = 1', false).then((_) { |
| 318 expect(results, hasLength(5)); |
| 319 assertHasResult(SearchResultKind.DECLARATION, 'vvv = 1'); |
| 320 assertHasResult(SearchResultKind.READ, 'vvv);'); |
| 321 assertHasResult(SearchResultKind.READ_WRITE, 'vvv += 3'); |
| 322 assertHasResult(SearchResultKind.WRITE, 'vvv = 2'); |
| 323 assertHasResult(SearchResultKind.INVOCATION, 'vvv();'); |
| 324 }); |
| 325 } |
| 326 |
| 327 test_method() { |
| 328 addTestFile(''' |
| 329 class A { |
| 330 mmm(p) {} |
| 331 m() { |
| 332 mmm(1); |
| 333 print(mmm); // in m() |
| 334 } |
| 335 } |
| 336 main(A a) { |
| 337 a.mmm(10); |
| 338 print(a.mmm); // in main() |
| 339 } |
| 340 '''); |
| 341 return findElementReferences('mmm(p) {}', false).then((_) { |
| 342 expect(results, hasLength(4)); |
| 343 assertHasResult(SearchResultKind.INVOCATION, 'mmm(1);'); |
| 344 assertHasResult(SearchResultKind.REFERENCE, 'mmm); // in m()'); |
| 345 assertHasResult(SearchResultKind.INVOCATION, 'mmm(10);'); |
| 346 assertHasResult(SearchResultKind.REFERENCE, 'mmm); // in main()'); |
| 347 }); |
| 348 } |
| 349 |
| 350 test_method_propagatedType() { |
| 351 addTestFile(''' |
| 352 class A { |
| 353 mmm(p) {} |
| 354 } |
| 355 main() { |
| 356 var a = new A(); |
| 357 a.mmm(10); |
| 358 print(a.mmm); |
| 359 } |
| 360 '''); |
| 361 return findElementReferences('mmm(p) {}', false).then((_) { |
| 362 expect(results, hasLength(2)); |
| 363 assertHasResult(SearchResultKind.INVOCATION, 'mmm(10);'); |
| 364 assertHasResult(SearchResultKind.REFERENCE, 'mmm);'); |
| 365 }); |
| 366 } |
| 367 |
| 368 test_oneUnit_twoLibraries() { |
| 369 var pathA = '/project/bin/libA.dart'; |
| 370 var pathB = '/project/bin/libB.dart'; |
| 371 var codeA = ''' |
| 372 library lib; |
| 373 part 'test.dart'; |
| 374 main() { |
| 375 fff(1); |
| 376 } |
| 377 '''; |
| 378 var codeB = ''' |
| 379 library lib; |
| 380 part 'test.dart'; |
| 381 main() { |
| 382 fff(2); |
| 383 } |
| 384 '''; |
| 385 addFile(pathA, codeA); |
| 386 addFile(pathB, codeB); |
| 387 addTestFile(''' |
| 388 part of lib; |
| 389 fff(p) {} |
| 390 '''); |
| 391 return findElementReferences('fff(p) {}', false).then((_) { |
| 392 expect(results, hasLength(2)); |
| 393 findResult( |
| 394 SearchResultKind.INVOCATION, |
| 395 pathA, |
| 396 codeA.indexOf('fff(1)'), |
| 397 3, |
| 398 true); |
| 399 findResult( |
| 400 SearchResultKind.INVOCATION, |
| 401 pathB, |
| 402 codeB.indexOf('fff(2)'), |
| 403 3, |
| 404 true); |
| 405 }); |
| 406 } |
| 407 |
| 408 test_oneUnit_zeroLibraries() { |
| 409 addTestFile(''' |
| 410 part of lib; |
| 411 fff(p) {} |
| 412 main() { |
| 413 fff(10); |
| 414 } |
| 415 '''); |
| 416 return findElementReferences('fff(p) {}', false).then((_) { |
| 417 expect(results, isEmpty); |
| 418 }); |
| 419 } |
| 420 |
| 421 test_parameter() { |
| 422 addTestFile(''' |
| 423 main(ppp) { |
| 424 print(ppp); |
| 425 ppp += 3; |
| 426 ppp = 2; |
| 427 ppp(); |
| 428 } |
| 429 '''); |
| 430 return findElementReferences('ppp) {', false).then((_) { |
| 431 expect(results, hasLength(5)); |
| 432 assertHasResult(SearchResultKind.DECLARATION, 'ppp) {'); |
| 433 assertHasResult(SearchResultKind.READ, 'ppp);'); |
| 434 assertHasResult(SearchResultKind.READ_WRITE, 'ppp += 3'); |
| 435 assertHasResult(SearchResultKind.WRITE, 'ppp = 2'); |
| 436 assertHasResult(SearchResultKind.INVOCATION, 'ppp();'); |
| 437 }); |
| 438 } |
| 439 |
| 440 test_path_inConstructor_named() { |
| 441 addTestFile(''' |
| 442 library my_lib; |
| 443 class A {} |
| 444 class B { |
| 445 B.named() { |
| 446 A a = null; |
| 447 } |
| 448 } |
| 449 '''); |
| 450 return findElementReferences('A {}', false).then((_) { |
| 451 assertHasResult(SearchResultKind.REFERENCE, 'A a = null;'); |
| 452 expect(getPathString(result.path), ''' |
| 453 LOCAL_VARIABLE a |
| 454 CONSTRUCTOR named |
| 455 CLASS B |
| 456 COMPILATION_UNIT test.dart |
| 457 LIBRARY my_lib'''); |
| 458 }); |
| 459 } |
| 460 |
| 461 test_path_inConstructor_unnamed() { |
| 462 addTestFile(''' |
| 463 library my_lib; |
| 464 class A {} |
| 465 class B { |
| 466 B() { |
| 467 A a = null; |
| 468 } |
| 469 } |
| 470 '''); |
| 471 return findElementReferences('A {}', false).then((_) { |
| 472 assertHasResult(SearchResultKind.REFERENCE, 'A a = null;'); |
| 473 expect(getPathString(result.path), ''' |
| 474 LOCAL_VARIABLE a |
| 475 CONSTRUCTOR |
| 476 CLASS B |
| 477 COMPILATION_UNIT test.dart |
| 478 LIBRARY my_lib'''); |
| 479 }); |
| 480 } |
| 481 |
| 482 test_path_inFunction() { |
| 483 addTestFile(''' |
| 484 library my_lib; |
| 485 class A {} |
| 486 main() { |
| 487 A a = null; |
| 488 } |
| 489 '''); |
| 490 return findElementReferences('A {}', false).then((_) { |
| 491 assertHasResult(SearchResultKind.REFERENCE, 'A a = null;'); |
| 492 expect(getPathString(result.path), ''' |
| 493 LOCAL_VARIABLE a |
| 494 FUNCTION main |
| 495 COMPILATION_UNIT test.dart |
| 496 LIBRARY my_lib'''); |
| 497 }); |
| 498 } |
| 499 |
| 500 test_potential_disabled() { |
| 501 addTestFile(''' |
| 502 class A { |
| 503 test(p) {} |
| 504 } |
| 505 main(A a, p) { |
| 506 a.test(1); |
| 507 p.test(2); |
| 508 } |
| 509 '''); |
| 510 return findElementReferences('test(p) {}', false).then((_) { |
| 511 assertHasResult(SearchResultKind.INVOCATION, 'test(1);'); |
| 512 assertNoResult(SearchResultKind.INVOCATION, 'test(2);'); |
| 513 }); |
| 514 } |
| 515 |
| 516 test_potential_field() { |
| 517 addTestFile(''' |
| 518 class A { |
| 519 test; // declaration |
| 520 } |
| 521 main(A a, p) { |
| 522 a.test = 1; |
| 523 p.test = 2; |
| 524 print(p.test); // p |
| 525 } |
| 526 '''); |
| 527 return findElementReferences('test; // declaration', true).then((_) { |
| 528 { |
| 529 assertHasResult(SearchResultKind.WRITE, 'test = 1;'); |
| 530 expect(result.isPotential, isFalse); |
| 531 } |
| 532 { |
| 533 assertHasResult(SearchResultKind.WRITE, 'test = 2;'); |
| 534 expect(result.isPotential, isTrue); |
| 535 } |
| 536 { |
| 537 assertHasResult(SearchResultKind.READ, 'test); // p'); |
| 538 expect(result.isPotential, isTrue); |
| 539 } |
| 540 }); |
| 541 } |
| 542 |
| 543 test_potential_method() { |
| 544 addTestFile(''' |
| 545 class A { |
| 546 test(p) {} |
| 547 } |
| 548 main(A a, p) { |
| 549 a.test(1); |
| 550 p.test(2); |
| 551 } |
| 552 '''); |
| 553 return findElementReferences('test(p) {}', true).then((_) { |
| 554 { |
| 555 assertHasResult(SearchResultKind.INVOCATION, 'test(1);'); |
| 556 expect(result.isPotential, isFalse); |
| 557 } |
| 558 { |
| 559 assertHasResult(SearchResultKind.INVOCATION, 'test(2);'); |
| 560 expect(result.isPotential, isTrue); |
| 561 } |
| 562 }); |
| 563 } |
| 564 |
| 565 test_topLevelVariable_explicit() { |
| 566 addTestFile(''' |
| 567 var vvv = 1; |
| 568 main() { |
| 569 print(vvv); |
| 570 vvv += 3; |
| 571 vvv = 2; |
| 572 vvv(); |
| 573 } |
| 574 '''); |
| 575 return findElementReferences('vvv = 1', false).then((_) { |
| 576 expect(results, hasLength(5)); |
| 577 assertHasResult(SearchResultKind.DECLARATION, 'vvv = 1;'); |
| 578 assertHasResult(SearchResultKind.READ, 'vvv);'); |
| 579 assertHasResult(SearchResultKind.WRITE, 'vvv += 3'); |
| 580 assertHasResult(SearchResultKind.WRITE, 'vvv = 2'); |
| 581 assertHasResult(SearchResultKind.INVOCATION, 'vvv();'); |
| 582 }); |
| 583 } |
| 584 |
| 585 test_topLevelVariable_implicit() { |
| 586 addTestFile(''' |
| 587 get vvv => null; |
| 588 set vvv(x) {} |
| 589 main() { |
| 590 print(vvv); |
| 591 vvv = 1; |
| 592 } |
| 593 '''); |
| 594 var forGetter = findElementReferences('vvv =>', false).then((_) { |
| 595 expect(results, hasLength(2)); |
| 596 assertHasResult(SearchResultKind.READ, 'vvv);'); |
| 597 assertHasResult(SearchResultKind.WRITE, 'vvv = 1;'); |
| 598 }); |
| 599 var forSetter = findElementReferences('vvv(x) {}', false).then((_) { |
| 600 expect(results, hasLength(2)); |
| 601 assertHasResult(SearchResultKind.READ, 'vvv);'); |
| 602 assertHasResult(SearchResultKind.WRITE, 'vvv = 1;'); |
| 603 }); |
| 604 return Future.wait([forGetter, forSetter]); |
| 605 } |
| 606 |
| 607 test_typeReference_class() { |
| 608 addTestFile(''' |
| 609 main() { |
| 610 int a = 1; |
| 611 int b = 2; |
| 612 } |
| 613 '''); |
| 614 return findElementReferences('int a', false).then((_) { |
| 615 assertHasResult(SearchResultKind.REFERENCE, 'int a'); |
| 616 assertHasResult(SearchResultKind.REFERENCE, 'int b'); |
| 617 }); |
| 618 } |
| 619 |
| 620 test_typeReference_functionType() { |
| 621 addTestFile(''' |
| 622 typedef F(); |
| 623 main(F f) { |
| 624 } |
| 625 '''); |
| 626 return findElementReferences('F()', false).then((_) { |
| 627 expect(results, hasLength(1)); |
| 628 assertHasResult(SearchResultKind.REFERENCE, 'F f'); |
| 629 }); |
| 630 } |
| 631 |
| 632 test_typeReference_typeVariable() { |
| 633 addTestFile(''' |
| 634 class A<T> { |
| 635 T f; |
| 636 T m() => null; |
| 637 } |
| 638 '''); |
| 639 return findElementReferences('T> {', false).then((_) { |
| 640 expect(results, hasLength(2)); |
| 641 assertHasResult(SearchResultKind.REFERENCE, 'T f;'); |
| 642 assertHasResult(SearchResultKind.REFERENCE, 'T m()'); |
| 643 }); |
| 644 } |
| 645 |
| 646 Future _waitForSearchResults() { |
| 647 if (searchDone) { |
| 648 return new Future.value(); |
| 649 } |
| 650 return new Future.delayed(Duration.ZERO, _waitForSearchResults); |
| 651 } |
| 652 } |
| OLD | NEW |