| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library test.services.completion.util; | 5 library test.services.completion.util; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 | 8 |
| 9 import 'package:analysis_server/src/protocol.dart' as protocol show Element, | 9 import 'package:analysis_server/src/protocol.dart' as protocol show Element, |
| 10 ElementKind; | 10 ElementKind; |
| 11 import 'package:analysis_server/src/protocol.dart' hide Element; | 11 import 'package:analysis_server/src/protocol.dart' hide Element; |
| 12 import 'package:analysis_server/src/services/completion/dart_completion_manager.
dart'; | 12 import 'package:analysis_server/src/services/completion/dart_completion_manager.
dart'; |
| 13 import 'package:analysis_server/src/services/completion/imported_computer.dart'; |
| 14 import 'package:analysis_server/src/services/completion/invocation_computer.dart
'; |
| 15 import 'package:analysis_server/src/services/completion/local_computer.dart'; |
| 13 import 'package:analysis_server/src/services/index/index.dart'; | 16 import 'package:analysis_server/src/services/index/index.dart'; |
| 14 import 'package:analysis_server/src/services/index/local_memory_index.dart'; | 17 import 'package:analysis_server/src/services/index/local_memory_index.dart'; |
| 15 import 'package:analysis_server/src/services/search/search_engine_internal.dart'
; | 18 import 'package:analysis_server/src/services/search/search_engine_internal.dart'
; |
| 16 import 'package:analyzer/src/generated/ast.dart'; | 19 import 'package:analyzer/src/generated/ast.dart'; |
| 17 import 'package:analyzer/src/generated/element.dart'; | 20 import 'package:analyzer/src/generated/element.dart'; |
| 18 import 'package:analyzer/src/generated/engine.dart'; | 21 import 'package:analyzer/src/generated/engine.dart'; |
| 19 import 'package:analyzer/src/generated/source.dart'; | 22 import 'package:analyzer/src/generated/source.dart'; |
| 20 import 'package:unittest/unittest.dart'; | 23 import 'package:unittest/unittest.dart'; |
| 21 | 24 |
| 22 import '../../abstract_context.dart'; | 25 import '../../abstract_context.dart'; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 46 int nextOffset = content.indexOf('^', completionOffset + 1); | 49 int nextOffset = content.indexOf('^', completionOffset + 1); |
| 47 expect(nextOffset, equals(-1), reason: 'too many ^'); | 50 expect(nextOffset, equals(-1), reason: 'too many ^'); |
| 48 content = content.substring(0, completionOffset) + | 51 content = content.substring(0, completionOffset) + |
| 49 content.substring(completionOffset + 1); | 52 content.substring(completionOffset + 1); |
| 50 testSource = addSource(testFile, content); | 53 testSource = addSource(testFile, content); |
| 51 request = | 54 request = |
| 52 new DartCompletionRequest(context, searchEngine, testSource, completionO
ffset); | 55 new DartCompletionRequest(context, searchEngine, testSource, completionO
ffset); |
| 53 } | 56 } |
| 54 | 57 |
| 55 void assertNoSuggestions() { | 58 void assertNoSuggestions() { |
| 56 expect(request.suggestions, equals(0)); | 59 expect(request.suggestions, hasLength(0)); |
| 57 } | 60 } |
| 58 | 61 |
| 59 void assertNotSuggested(String completion) { | 62 CompletionSuggestion assertNotSuggested(String completion) { |
| 60 CompletionSuggestion suggestion = request.suggestions.firstWhere( | 63 CompletionSuggestion suggestion = request.suggestions.firstWhere( |
| 61 (cs) => cs.completion == completion, | 64 (cs) => cs.completion == completion, |
| 62 orElse: () => null); | 65 orElse: () => null); |
| 63 if (suggestion != null) { | 66 if (suggestion != null) { |
| 64 _failedCompletion( | 67 _failedCompletion( |
| 65 'did not expect completion: $completion\n $suggestion'); | 68 'did not expect completion: $completion\n $suggestion'); |
| 66 } | 69 } |
| 70 return null; |
| 67 } | 71 } |
| 68 | 72 |
| 69 CompletionSuggestion assertSuggest(CompletionSuggestionKind kind, | 73 CompletionSuggestion assertSuggest(CompletionSuggestionKind kind, |
| 70 String completion, [CompletionRelevance relevance = CompletionRelevance.DE
FAULT, | 74 String completion, [CompletionRelevance relevance = CompletionRelevance.DE
FAULT, |
| 71 bool isDeprecated = false, bool isPotential = false]) { | 75 bool isDeprecated = false, bool isPotential = false]) { |
| 72 CompletionSuggestion cs; | 76 CompletionSuggestion cs; |
| 73 request.suggestions.forEach((s) { | 77 request.suggestions.forEach((s) { |
| 74 if (s.completion == completion && s.kind == kind) { | 78 if (s.completion == completion && s.kind == kind) { |
| 75 if (cs == null) { | 79 if (cs == null) { |
| 76 cs = s; | 80 cs = s; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 expect(element.kind, equals(protocol.ElementKind.GETTER)); | 151 expect(element.kind, equals(protocol.ElementKind.GETTER)); |
| 148 expect(element.name, equals(name)); | 152 expect(element.name, equals(name)); |
| 149 expect( | 153 expect( |
| 150 element.returnType, | 154 element.returnType, |
| 151 equals(returnType != null ? returnType : 'dynamic')); | 155 equals(returnType != null ? returnType : 'dynamic')); |
| 152 return cs; | 156 return cs; |
| 153 } | 157 } |
| 154 | 158 |
| 155 CompletionSuggestion assertSuggestLibraryPrefix(String prefix, | 159 CompletionSuggestion assertSuggestLibraryPrefix(String prefix, |
| 156 [CompletionRelevance relevance = CompletionRelevance.DEFAULT]) { | 160 [CompletionRelevance relevance = CompletionRelevance.DEFAULT]) { |
| 157 CompletionSuggestion cs = | 161 // Library prefix should only be suggested by ImportedComputer |
| 158 assertSuggest(CompletionSuggestionKind.LIBRARY_PREFIX, prefix, relevance
); | 162 if (computer is ImportedComputer) { |
| 159 protocol.Element element = cs.element; | 163 CompletionSuggestion cs = |
| 160 expect(element, isNotNull); | 164 assertSuggest(CompletionSuggestionKind.LIBRARY_PREFIX, prefix, relevan
ce); |
| 161 expect(element.kind, equals(protocol.ElementKind.LIBRARY)); | 165 protocol.Element element = cs.element; |
| 162 expect(element.returnType, isNull); | 166 expect(element, isNotNull); |
| 163 return cs; | 167 expect(element.kind, equals(protocol.ElementKind.LIBRARY)); |
| 168 expect(element.returnType, isNull); |
| 169 return cs; |
| 170 } else { |
| 171 return null; |
| 172 } |
| 164 } | 173 } |
| 165 | 174 |
| 166 CompletionSuggestion assertSuggestLocalVariable(String name, | 175 CompletionSuggestion assertSuggestLocalVariable(String name, |
| 167 String returnType, [CompletionRelevance relevance = | 176 String returnType, [CompletionRelevance relevance = |
| 168 CompletionRelevance.DEFAULT]) { | 177 CompletionRelevance.DEFAULT]) { |
| 169 CompletionSuggestion cs = | 178 // Local variables should only be suggested by LocalComputer |
| 170 assertSuggest(CompletionSuggestionKind.LOCAL_VARIABLE, name, relevance); | 179 if (computer is LocalComputer) { |
| 171 expect(cs.returnType, equals(returnType)); | 180 CompletionSuggestion cs = |
| 172 protocol.Element element = cs.element; | 181 assertSuggest(CompletionSuggestionKind.LOCAL_VARIABLE, name, relevance
); |
| 173 expect(element, isNotNull); | 182 expect(cs.returnType, equals(returnType)); |
| 174 expect(element.kind, equals(protocol.ElementKind.LOCAL_VARIABLE)); | 183 protocol.Element element = cs.element; |
| 175 expect(element.name, equals(name)); | 184 expect(element, isNotNull); |
| 176 expect( | 185 expect(element.kind, equals(protocol.ElementKind.LOCAL_VARIABLE)); |
| 177 element.returnType, | 186 expect(element.name, equals(name)); |
| 178 equals(returnType != null ? returnType : 'dynamic')); | 187 expect( |
| 179 return cs; | 188 element.returnType, |
| 189 equals(returnType != null ? returnType : 'dynamic')); |
| 190 return cs; |
| 191 } else { |
| 192 return null; |
| 193 } |
| 180 } | 194 } |
| 181 | 195 |
| 182 CompletionSuggestion assertSuggestMethod(String name, String declaringType, | 196 CompletionSuggestion assertSuggestMethod(String name, String declaringType, |
| 183 String returnType, [CompletionRelevance relevance = | 197 String returnType, [CompletionRelevance relevance = |
| 184 CompletionRelevance.DEFAULT]) { | 198 CompletionRelevance.DEFAULT]) { |
| 185 CompletionSuggestion cs = | 199 CompletionSuggestion cs = |
| 186 assertSuggest(CompletionSuggestionKind.METHOD, name, relevance); | 200 assertSuggest(CompletionSuggestionKind.METHOD, name, relevance); |
| 187 expect(cs.declaringType, equals(declaringType)); | 201 expect(cs.declaringType, equals(declaringType)); |
| 188 expect(cs.returnType, equals(returnType)); | 202 expect(cs.returnType, equals(returnType)); |
| 189 protocol.Element element = cs.element; | 203 protocol.Element element = cs.element; |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 331 sb.write('\n in'); | 345 sb.write('\n in'); |
| 332 AstNode node = completionNode; | 346 AstNode node = completionNode; |
| 333 while (node != null) { | 347 while (node != null) { |
| 334 sb.write('\n ${node.runtimeType}'); | 348 sb.write('\n ${node.runtimeType}'); |
| 335 node = node.parent; | 349 node = node.parent; |
| 336 } | 350 } |
| 337 } | 351 } |
| 338 fail(sb.toString()); | 352 fail(sb.toString()); |
| 339 } | 353 } |
| 340 } | 354 } |
| 355 |
| 356 /** |
| 357 * Common tests for `ImportedTypeComputerTest`, `InvocationComputerTest`, |
| 358 * and `LocalComputerTest`. |
| 359 */ |
| 360 class AbstractSelectorSuggestionTest extends AbstractCompletionTest { |
| 361 |
| 362 CompletionSuggestion assertLocalSuggestMethod(String name, |
| 363 String declaringType, String returnType, [CompletionRelevance relevance = |
| 364 CompletionRelevance.DEFAULT]) { |
| 365 if (computer is LocalComputer) { |
| 366 return assertSuggestMethod(name, declaringType, returnType, relevance); |
| 367 } else { |
| 368 return assertNotSuggested(name); |
| 369 } |
| 370 } |
| 371 |
| 372 CompletionSuggestion assertSuggestImportedClass(String name, |
| 373 [CompletionRelevance relevance = CompletionRelevance.DEFAULT]) { |
| 374 if (computer is ImportedComputer) { |
| 375 return assertSuggestClass(name, relevance); |
| 376 } else { |
| 377 return assertNotSuggested(name); |
| 378 } |
| 379 } |
| 380 |
| 381 CompletionSuggestion assertSuggestInvocationGetter(String name, String returnT
ype, |
| 382 [CompletionRelevance relevance = CompletionRelevance.DEFAULT]) { |
| 383 if (computer is InvocationComputer) { |
| 384 return assertSuggestGetter(name, returnType, relevance); |
| 385 } else { |
| 386 return null; |
| 387 } |
| 388 } |
| 389 |
| 390 CompletionSuggestion assertSuggestLocalClass(String name, |
| 391 [CompletionRelevance relevance = CompletionRelevance.DEFAULT]) { |
| 392 if (computer is LocalComputer) { |
| 393 return assertSuggestClass(name, relevance); |
| 394 } else { |
| 395 return assertNotSuggested(name); |
| 396 } |
| 397 } |
| 398 |
| 399 test_Block() { |
| 400 addSource('/testAB.dart', ''' |
| 401 class A {int x;} |
| 402 class _B { }'''); |
| 403 addSource('/testCD.dart', ''' |
| 404 class C { } |
| 405 class D { }'''); |
| 406 addSource('/testEEF.dart', ''' |
| 407 class EE { } |
| 408 class F { }'''); |
| 409 addSource('/testG.dart', 'class G { }'); |
| 410 addSource('/testH.dart', 'class H { }'); // not imported |
| 411 addTestSource(''' |
| 412 import "/testAB.dart"; |
| 413 import "/testCD.dart" hide D; |
| 414 import "/testEEF.dart" show EE; |
| 415 import "/testG.dart" as g; |
| 416 class X {a() {var f; {var x;} ^ var r;} Z b() { }} |
| 417 class Z { }'''); |
| 418 computeFast(); |
| 419 return computeFull(true).then((_) { |
| 420 |
| 421 assertSuggestLocalClass('X'); |
| 422 assertSuggestLocalClass('Z'); |
| 423 assertLocalSuggestMethod('a', 'X', null); |
| 424 assertLocalSuggestMethod('b', 'X', 'Z'); |
| 425 assertSuggestLocalVariable('f', null); |
| 426 // Don't suggest locals out of scope |
| 427 assertNotSuggested('r'); |
| 428 assertNotSuggested('x'); |
| 429 |
| 430 assertSuggestImportedClass('A'); |
| 431 assertNotSuggested('_B'); |
| 432 assertSuggestImportedClass('C'); |
| 433 // hidden element suggested as low relevance |
| 434 assertSuggestImportedClass('D', CompletionRelevance.LOW); |
| 435 assertSuggestImportedClass('EE'); |
| 436 // hidden element suggested as low relevance |
| 437 assertSuggestImportedClass('F', CompletionRelevance.LOW); |
| 438 assertSuggestLibraryPrefix('g'); |
| 439 assertNotSuggested('G'); |
| 440 assertSuggestImportedClass('H', CompletionRelevance.LOW); |
| 441 assertSuggestImportedClass('Object'); |
| 442 // TODO (danrubel) suggest HtmlElement as low relevance |
| 443 assertNotSuggested('HtmlElement'); |
| 444 }); |
| 445 } |
| 446 |
| 447 test_CascadeExpression_selector1() { |
| 448 addSource('/testB.dart', ''' |
| 449 class B { }'''); |
| 450 addTestSource(''' |
| 451 import "/testB.dart"; |
| 452 class A {var b; X _c;} |
| 453 class X{} |
| 454 // looks like a cascade to the parser |
| 455 // but the user is trying to get completions for a non-cascade |
| 456 main() {A a; a.^.z}'''); |
| 457 computeFast(); |
| 458 return computeFull(true).then((_) { |
| 459 assertSuggestInvocationGetter('b', null); |
| 460 assertSuggestInvocationGetter('_c', 'X'); |
| 461 assertNotSuggested('Object'); |
| 462 assertNotSuggested('A'); |
| 463 assertNotSuggested('B'); |
| 464 assertNotSuggested('X'); |
| 465 assertNotSuggested('z'); |
| 466 }); |
| 467 } |
| 468 |
| 469 test_CascadeExpression_selector2() { |
| 470 addSource('/testB.dart', ''' |
| 471 class B { }'''); |
| 472 addTestSource(''' |
| 473 import "/testB.dart"; |
| 474 class A {var b; X _c;} |
| 475 class X{} |
| 476 main() {A a; a..^z}'''); |
| 477 computeFast(); |
| 478 assertNoSuggestions(); |
| 479 return computeFull(true).then((_) { |
| 480 assertSuggestInvocationGetter('b', null); |
| 481 assertSuggestInvocationGetter('_c', 'X'); |
| 482 assertNotSuggested('Object'); |
| 483 assertNotSuggested('A'); |
| 484 assertNotSuggested('B'); |
| 485 assertNotSuggested('X'); |
| 486 assertNotSuggested('z'); |
| 487 }); |
| 488 } |
| 489 } |
| OLD | NEW |