| 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; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 expect(completionOffset, isNot(equals(-1)), reason: 'missing ^'); | 48 expect(completionOffset, isNot(equals(-1)), reason: 'missing ^'); |
| 49 int nextOffset = content.indexOf('^', completionOffset + 1); | 49 int nextOffset = content.indexOf('^', completionOffset + 1); |
| 50 expect(nextOffset, equals(-1), reason: 'too many ^'); | 50 expect(nextOffset, equals(-1), reason: 'too many ^'); |
| 51 content = content.substring(0, completionOffset) + | 51 content = content.substring(0, completionOffset) + |
| 52 content.substring(completionOffset + 1); | 52 content.substring(completionOffset + 1); |
| 53 testSource = addSource(testFile, content); | 53 testSource = addSource(testFile, content); |
| 54 request = | 54 request = |
| 55 new DartCompletionRequest(context, searchEngine, testSource, completionO
ffset); | 55 new DartCompletionRequest(context, searchEngine, testSource, completionO
ffset); |
| 56 } | 56 } |
| 57 | 57 |
| 58 void assertNoSuggestions() { | 58 void assertNoSuggestions({CompletionSuggestionKind kind: null}) { |
| 59 if (request.suggestions.length > 0) { | 59 if (kind == null) { |
| 60 _failedCompletion('Expected no suggestions', request.suggestions); | 60 if (request.suggestions.length > 0) { |
| 61 failedCompletion('Expected no suggestions', request.suggestions); |
| 62 } |
| 63 return; |
| 64 } |
| 65 CompletionSuggestion suggestion = request.suggestions.firstWhere( |
| 66 (CompletionSuggestion cs) => cs.kind == kind, |
| 67 orElse: () => null); |
| 68 if (suggestion != null) { |
| 69 failedCompletion('did not expect completion: $completion\n $suggestion'); |
| 61 } | 70 } |
| 62 } | 71 } |
| 63 | 72 |
| 64 CompletionSuggestion assertNotSuggested(String completion) { | 73 CompletionSuggestion assertNotSuggested(String completion) { |
| 65 CompletionSuggestion suggestion = request.suggestions.firstWhere( | 74 CompletionSuggestion suggestion = request.suggestions.firstWhere( |
| 66 (cs) => cs.completion == completion, | 75 (CompletionSuggestion cs) => cs.completion == completion, |
| 67 orElse: () => null); | 76 orElse: () => null); |
| 68 if (suggestion != null) { | 77 if (suggestion != null) { |
| 69 _failedCompletion( | 78 failedCompletion('did not expect completion: $completion\n $suggestion'); |
| 70 'did not expect completion: $completion\n $suggestion'); | |
| 71 } | 79 } |
| 72 return null; | 80 return null; |
| 73 } | 81 } |
| 74 | 82 |
| 75 CompletionSuggestion assertSuggest(String completion, | 83 CompletionSuggestion assertSuggest(String completion, |
| 76 {CompletionSuggestionKind csKind: CompletionSuggestionKind.INVOCATION, | 84 {CompletionSuggestionKind csKind: CompletionSuggestionKind.INVOCATION, |
| 77 CompletionRelevance relevance: CompletionRelevance.DEFAULT, | 85 CompletionRelevance relevance: CompletionRelevance.DEFAULT, |
| 78 protocol.ElementKind elemKind: null, bool isDeprecated: false, bool isPote
ntial: | 86 protocol.ElementKind elemKind: null, bool isDeprecated: false, bool isPote
ntial: |
| 79 false}) { | 87 false}) { |
| 80 CompletionSuggestion cs; | 88 CompletionSuggestion cs = |
| 81 request.suggestions.forEach((s) { | 89 getSuggest(completion: completion, csKind: csKind, elemKind: elemKind); |
| 82 if (s.completion == completion && s.kind == csKind) { | |
| 83 protocol.Element element = s.element; | |
| 84 if (elemKind == null || (element != null && elemKind == element.kind)) { | |
| 85 if (cs == null) { | |
| 86 cs = s; | |
| 87 } else { | |
| 88 _failedCompletion( | |
| 89 'expected exactly one $completion', | |
| 90 request.suggestions.where((s) => s.completion == completion)); | |
| 91 } | |
| 92 } | |
| 93 } | |
| 94 }); | |
| 95 if (cs == null) { | 90 if (cs == null) { |
| 96 _failedCompletion('expected $completion $csKind', request.suggestions); | 91 failedCompletion('expected $completion $csKind', request.suggestions); |
| 97 } | 92 } |
| 98 expect(cs.kind, equals(csKind)); | 93 expect(cs.kind, equals(csKind)); |
| 99 if (isDeprecated) { | 94 if (isDeprecated) { |
| 100 expect(cs.relevance, equals(CompletionRelevance.LOW)); | 95 expect(cs.relevance, equals(CompletionRelevance.LOW)); |
| 101 } else { | 96 } else { |
| 102 expect(cs.relevance, equals(relevance)); | 97 expect(cs.relevance, equals(relevance)); |
| 103 } | 98 } |
| 104 expect(cs.selectionOffset, equals(completion.length)); | 99 expect(cs.selectionOffset, equals(completion.length)); |
| 105 expect(cs.selectionLength, equals(0)); | 100 expect(cs.selectionLength, equals(0)); |
| 106 expect(cs.isDeprecated, equals(isDeprecated)); | 101 expect(cs.isDeprecated, equals(isDeprecated)); |
| 107 expect(cs.isPotential, equals(isPotential)); | 102 expect(cs.isPotential, equals(isPotential)); |
| 108 return cs; | 103 return cs; |
| 109 } | 104 } |
| 110 | 105 |
| 106 void assertSuggestArgumentList(List<String> paramNames, List<String> paramType
s) { |
| 107 CompletionSuggestionKind csKind = CompletionSuggestionKind.ARGUMENT_LIST; |
| 108 CompletionSuggestion cs = getSuggest(csKind: csKind); |
| 109 if (cs == null) { |
| 110 failedCompletion('expected completion $csKind', request.suggestions); |
| 111 } |
| 112 assertSuggestArgumentList_params( |
| 113 paramNames, |
| 114 paramTypes, |
| 115 cs.parameterNames, |
| 116 cs.parameterTypes); |
| 117 expect(cs.relevance, CompletionRelevance.HIGH); |
| 118 } |
| 119 |
| 120 void assertSuggestArgumentList_params(List<String> expectedNames, |
| 121 List<String> expectedTypes, List<String> actualNames, |
| 122 List<String> actualTypes) { |
| 123 if (actualNames != null && |
| 124 actualNames.length == expectedNames.length && |
| 125 actualTypes != null && |
| 126 actualTypes.length == expectedTypes.length) { |
| 127 int index = 0; |
| 128 while (index < expectedNames.length) { |
| 129 if (actualNames[index] != expectedNames[index] || |
| 130 actualTypes[index] != expectedTypes[index]) { |
| 131 break; |
| 132 } |
| 133 ++index; |
| 134 } |
| 135 if (index == expectedNames.length) { |
| 136 return; |
| 137 } |
| 138 } |
| 139 StringBuffer msg = new StringBuffer(); |
| 140 msg.writeln('Argument list not the same'); |
| 141 msg.writeln(' Expected names: $expectedNames'); |
| 142 msg.writeln(' found: $actualNames'); |
| 143 msg.writeln(' Expected types: $expectedTypes'); |
| 144 msg.writeln(' found: $actualTypes'); |
| 145 fail(msg.toString()); |
| 146 } |
| 147 |
| 111 CompletionSuggestion assertSuggestClass(String name, | 148 CompletionSuggestion assertSuggestClass(String name, |
| 112 [CompletionRelevance relevance = CompletionRelevance.DEFAULT, | 149 [CompletionRelevance relevance = CompletionRelevance.DEFAULT, |
| 113 CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION]) { | 150 CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION]) { |
| 114 CompletionSuggestion cs = | 151 CompletionSuggestion cs = |
| 115 assertSuggest(name, csKind: kind, relevance: relevance); | 152 assertSuggest(name, csKind: kind, relevance: relevance); |
| 116 protocol.Element element = cs.element; | 153 protocol.Element element = cs.element; |
| 117 expect(element, isNotNull); | 154 expect(element, isNotNull); |
| 118 expect(element.kind, equals(protocol.ElementKind.CLASS)); | 155 expect(element.kind, equals(protocol.ElementKind.CLASS)); |
| 119 expect(element.name, equals(name)); | 156 expect(element.name, equals(name)); |
| 120 expect(element.parameters, isNull); | 157 expect(element.parameters, isNull); |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 414 } | 451 } |
| 415 | 452 |
| 416 result = context.performAnalysisTask(); | 453 result = context.performAnalysisTask(); |
| 417 } | 454 } |
| 418 if (!resolved) { | 455 if (!resolved) { |
| 419 fail('expected unit to be resolved'); | 456 fail('expected unit to be resolved'); |
| 420 } | 457 } |
| 421 return computer.computeFull(request); | 458 return computer.computeFull(request); |
| 422 } | 459 } |
| 423 | 460 |
| 424 @override | 461 void failedCompletion(String message, |
| 425 void setUp() { | |
| 426 super.setUp(); | |
| 427 index = createLocalMemoryIndex(); | |
| 428 searchEngine = new SearchEngineImpl(index); | |
| 429 } | |
| 430 | |
| 431 void _failedCompletion(String message, | |
| 432 [Iterable<CompletionSuggestion> completions]) { | 462 [Iterable<CompletionSuggestion> completions]) { |
| 433 StringBuffer sb = new StringBuffer(message); | 463 StringBuffer sb = new StringBuffer(message); |
| 434 if (completions != null) { | 464 if (completions != null) { |
| 435 sb.write('\n found'); | 465 sb.write('\n found'); |
| 436 completions.toList() | 466 completions.toList() |
| 437 ..sort((CompletionSuggestion s1, CompletionSuggestion s2) { | 467 ..sort((CompletionSuggestion s1, CompletionSuggestion s2) { |
| 438 String c1 = s1.completion.toLowerCase(); | 468 String c1 = s1.completion.toLowerCase(); |
| 439 String c2 = s2.completion.toLowerCase(); | 469 String c2 = s2.completion.toLowerCase(); |
| 440 return c1.compareTo(c2); | 470 return c1.compareTo(c2); |
| 441 }) | 471 }) |
| 442 ..forEach((CompletionSuggestion suggestion) { | 472 ..forEach((CompletionSuggestion suggestion) { |
| 443 sb.write('\n ${suggestion.completion} -> $suggestion'); | 473 sb.write('\n ${suggestion.completion} -> $suggestion'); |
| 444 }); | 474 }); |
| 445 } | 475 } |
| 446 if (completionNode != null) { | 476 if (completionNode != null) { |
| 447 sb.write('\n in'); | 477 sb.write('\n in'); |
| 448 AstNode node = completionNode; | 478 AstNode node = completionNode; |
| 449 while (node != null) { | 479 while (node != null) { |
| 450 sb.write('\n ${node.runtimeType}'); | 480 sb.write('\n ${node.runtimeType}'); |
| 451 node = node.parent; | 481 node = node.parent; |
| 452 } | 482 } |
| 453 } | 483 } |
| 454 fail(sb.toString()); | 484 fail(sb.toString()); |
| 455 } | 485 } |
| 486 |
| 487 CompletionSuggestion getSuggest({String completion: null, |
| 488 CompletionSuggestionKind csKind: null, protocol.ElementKind elemKind: null
}) { |
| 489 CompletionSuggestion cs; |
| 490 request.suggestions.forEach((CompletionSuggestion s) { |
| 491 if (completion != null && completion != s.completion) { |
| 492 return; |
| 493 } |
| 494 if (csKind != null && csKind != s.kind) { |
| 495 return; |
| 496 } |
| 497 if (elemKind != null) { |
| 498 protocol.Element element = s.element; |
| 499 if (element == null || elemKind != element.kind) { |
| 500 return; |
| 501 } |
| 502 } |
| 503 if (cs == null) { |
| 504 cs = s; |
| 505 } else { |
| 506 failedCompletion( |
| 507 'expected exactly one $cs', |
| 508 request.suggestions.where((s) => s.completion == completion)); |
| 509 } |
| 510 }); |
| 511 return cs; |
| 512 } |
| 513 |
| 514 @override |
| 515 void setUp() { |
| 516 super.setUp(); |
| 517 index = createLocalMemoryIndex(); |
| 518 searchEngine = new SearchEngineImpl(index); |
| 519 } |
| 456 } | 520 } |
| 457 | 521 |
| 458 /** | 522 /** |
| 459 * Common tests for `ImportedTypeComputerTest`, `InvocationComputerTest`, | 523 * Common tests for `ImportedTypeComputerTest`, `InvocationComputerTest`, |
| 460 * and `LocalComputerTest`. | 524 * and `LocalComputerTest`. |
| 461 */ | 525 */ |
| 462 class AbstractSelectorSuggestionTest extends AbstractCompletionTest { | 526 class AbstractSelectorSuggestionTest extends AbstractCompletionTest { |
| 463 | 527 |
| 464 CompletionSuggestion assertLocalSuggestMethod(String name, | 528 CompletionSuggestion assertLocalSuggestMethod(String name, |
| 465 String declaringType, String returnType, [CompletionRelevance relevance = | 529 String declaringType, String returnType, [CompletionRelevance relevance = |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 672 library A; | 736 library A; |
| 673 bool hasLength(int expected) { } | 737 bool hasLength(int expected) { } |
| 674 void baz() { }'''); | 738 void baz() { }'''); |
| 675 addTestSource(''' | 739 addTestSource(''' |
| 676 import '/libA.dart' | 740 import '/libA.dart' |
| 677 class B { } | 741 class B { } |
| 678 String bar() => true; | 742 String bar() => true; |
| 679 void main() {expect(^)}'''); | 743 void main() {expect(^)}'''); |
| 680 computeFast(); | 744 computeFast(); |
| 681 return computeFull(true).then((_) { | 745 return computeFull(true).then((_) { |
| 746 assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST); |
| 682 assertSuggestLocalFunction('bar', 'String'); | 747 assertSuggestLocalFunction('bar', 'String'); |
| 683 assertSuggestImportedFunction('hasLength', 'bool'); | 748 assertSuggestImportedFunction('hasLength', 'bool'); |
| 684 assertSuggestImportedFunction('identical', 'bool'); | 749 assertSuggestImportedFunction('identical', 'bool'); |
| 750 assertSuggestLocalClass('B'); |
| 751 assertSuggestImportedClass('Object'); |
| 752 assertNotSuggested('main'); |
| 753 assertNotSuggested('baz'); |
| 754 assertNotSuggested('print'); |
| 755 }); |
| 756 } |
| 757 |
| 758 test_ArgumentList_imported_function() { |
| 759 // ArgumentList MethodInvocation ExpressionStatement Block |
| 760 addSource('/libA.dart', ''' |
| 761 library A; |
| 762 bool hasLength(int expected) { } |
| 763 expect(arg) { } |
| 764 void baz() { }'''); |
| 765 addTestSource(''' |
| 766 import '/libA.dart' |
| 767 class B { } |
| 768 String bar() => true; |
| 769 void main() {expect(^)}'''); |
| 770 computeFast(); |
| 771 return computeFull(true).then((_) { |
| 772 assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST); |
| 773 assertSuggestLocalFunction('bar', 'String'); |
| 774 assertSuggestImportedFunction('hasLength', 'bool'); |
| 775 assertSuggestImportedFunction('identical', 'bool'); |
| 776 assertSuggestLocalClass('B'); |
| 777 assertSuggestImportedClass('Object'); |
| 778 assertNotSuggested('main'); |
| 779 assertNotSuggested('baz'); |
| 780 assertNotSuggested('print'); |
| 781 }); |
| 782 } |
| 783 |
| 784 test_ArgumentList_local_function() { |
| 785 // ArgumentList MethodInvocation ExpressionStatement Block |
| 786 addSource('/libA.dart', ''' |
| 787 library A; |
| 788 bool hasLength(int expected) { } |
| 789 void baz() { }'''); |
| 790 addTestSource(''' |
| 791 import '/libA.dart' |
| 792 expect(arg) { } |
| 793 class B { } |
| 794 String bar() => true; |
| 795 void main() {expect(^)}'''); |
| 796 computeFast(); |
| 797 return computeFull(true).then((_) { |
| 798 assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST); |
| 799 assertSuggestLocalFunction('bar', 'String'); |
| 800 assertSuggestImportedFunction('hasLength', 'bool'); |
| 801 assertSuggestImportedFunction('identical', 'bool'); |
| 802 assertSuggestLocalClass('B'); |
| 803 assertSuggestImportedClass('Object'); |
| 804 assertNotSuggested('main'); |
| 805 assertNotSuggested('baz'); |
| 806 assertNotSuggested('print'); |
| 807 }); |
| 808 } |
| 809 |
| 810 test_ArgumentList_local_method() { |
| 811 // ArgumentList MethodInvocation ExpressionStatement Block |
| 812 addSource('/libA.dart', ''' |
| 813 library A; |
| 814 bool hasLength(int expected) { } |
| 815 void baz() { }'''); |
| 816 addTestSource(''' |
| 817 import '/libA.dart' |
| 818 class B { |
| 819 expect(arg) { } |
| 820 void foo() {expect(^)}} |
| 821 String bar() => true;'''); |
| 822 computeFast(); |
| 823 return computeFull(true).then((_) { |
| 824 assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST); |
| 825 assertSuggestLocalFunction('bar', 'String'); |
| 826 assertSuggestImportedFunction('hasLength', 'bool'); |
| 827 assertSuggestImportedFunction('identical', 'bool'); |
| 685 assertSuggestLocalClass('B'); | 828 assertSuggestLocalClass('B'); |
| 686 assertSuggestImportedClass('Object'); | 829 assertSuggestImportedClass('Object'); |
| 687 assertNotSuggested('main'); | 830 assertNotSuggested('main'); |
| 688 assertNotSuggested('baz'); | 831 assertNotSuggested('baz'); |
| 689 assertNotSuggested('print'); | 832 assertNotSuggested('print'); |
| 690 }); | 833 }); |
| 691 } | 834 } |
| 692 | 835 |
| 693 test_ArgumentList_namedParam() { | 836 test_ArgumentList_namedParam() { |
| 694 // SimpleIdentifier NamedExpression ArgumentList MethodInvocation | 837 // SimpleIdentifier NamedExpression ArgumentList MethodInvocation |
| (...skipping 1190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1885 assertNotSuggested('bar2'); | 2028 assertNotSuggested('bar2'); |
| 1886 assertNotSuggested('_B'); | 2029 assertNotSuggested('_B'); |
| 1887 assertSuggestLocalClass('Y'); | 2030 assertSuggestLocalClass('Y'); |
| 1888 assertSuggestLocalClass('C'); | 2031 assertSuggestLocalClass('C'); |
| 1889 assertSuggestLocalVariable('f', null); | 2032 assertSuggestLocalVariable('f', null); |
| 1890 assertNotSuggested('x'); | 2033 assertNotSuggested('x'); |
| 1891 assertNotSuggested('e'); | 2034 assertNotSuggested('e'); |
| 1892 }); | 2035 }); |
| 1893 } | 2036 } |
| 1894 } | 2037 } |
| OLD | NEW |