| Index: pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart
|
| diff --git a/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart b/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart
|
| index 1b99cfed2f6992a0819587c184cf7ad930e2e456..e6d4077c69988fc975ead13829195c295242767c 100644
|
| --- a/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart
|
| +++ b/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart
|
| @@ -14,17 +14,84 @@ import '../../../abstract_single_unit.dart';
|
|
|
| main() {
|
| defineReflectiveSuite(() {
|
| - defineReflectiveTests(StatementCompletionTest);
|
| + defineReflectiveTests(_DoCompletionTest);
|
| + defineReflectiveTests(_ForCompletionTest);
|
| + defineReflectiveTests(_IfCompletionTest);
|
| + defineReflectiveTests(_SimpleCompletionTest);
|
| + defineReflectiveTests(_WhileCompletionTest);
|
| });
|
| }
|
|
|
| -@reflectiveTest
|
| class StatementCompletionTest extends AbstractSingleUnitTest {
|
| SourceChange change;
|
|
|
| bool get enableNewAnalysisDriver => true;
|
|
|
| - test_completeDoEmptyCondition() async {
|
| + int _after(String source, String match) =>
|
| + source.indexOf(match) + match.length;
|
| +
|
| + int _afterLast(String source, String match) =>
|
| + source.lastIndexOf(match) + match.length;
|
| +
|
| + void _assertHasChange(String message, String expectedCode, [Function cmp]) {
|
| + if (change.message == message) {
|
| + if (!change.edits.isEmpty) {
|
| + String resultCode =
|
| + SourceEdit.applySequence(testCode, change.edits[0].edits);
|
| + expect(resultCode, expectedCode.replaceAll('////', ''));
|
| + if (cmp != null) {
|
| + int offset = cmp(resultCode);
|
| + expect(change.selection.offset, offset);
|
| + }
|
| + } else {
|
| + if (cmp != null) {
|
| + int offset = cmp(testCode);
|
| + expect(change.selection.offset, offset);
|
| + }
|
| + }
|
| + return;
|
| + }
|
| + fail("Expected to find |$message| but got: " + change.message);
|
| + }
|
| +
|
| + _computeCompletion(int offset) async {
|
| + driver.changeFile(testFile);
|
| + AnalysisResult result = await driver.getResult(testFile);
|
| + StatementCompletionContext context = new StatementCompletionContext(
|
| + testFile,
|
| + result.lineInfo,
|
| + offset,
|
| + testUnit,
|
| + testUnitElement,
|
| + result.errors);
|
| + StatementCompletionProcessor processor =
|
| + new StatementCompletionProcessor(context);
|
| + StatementCompletion completion = await processor.compute();
|
| + change = completion.change;
|
| + }
|
| +
|
| + _prepareCompletion(String search, String sourceCode,
|
| + {bool atStart: false, bool atEnd: false, int delta: 0}) async {
|
| + testCode = sourceCode.replaceAll('////', '');
|
| + int offset = findOffset(search);
|
| + if (atStart) {
|
| + delta = 0;
|
| + } else if (atEnd) {
|
| + delta = search.length;
|
| + }
|
| + await _prepareCompletionAt(offset + delta, testCode);
|
| + }
|
| +
|
| + _prepareCompletionAt(int offset, String sourceCode) async {
|
| + verifyNoTestUnitErrors = false;
|
| + await resolveTestUnit(sourceCode);
|
| + await _computeCompletion(offset);
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class _DoCompletionTest extends StatementCompletionTest {
|
| + test_emptyCondition() async {
|
| await _prepareCompletion(
|
| 'while ()',
|
| '''
|
| @@ -42,10 +109,10 @@ main() {
|
| } while ();
|
| }
|
| ''',
|
| - (s) => s.indexOf('while (') + 'while ('.length);
|
| + (s) => _after(s, 'while ('));
|
| }
|
|
|
| - test_completeDoKeywordOnly() async {
|
| + test_keywordOnly() async {
|
| await _prepareCompletion(
|
| 'do',
|
| '''
|
| @@ -63,10 +130,10 @@ main() {
|
| } while ();
|
| }
|
| ''',
|
| - (s) => s.indexOf('while (') + 'while ('.length);
|
| + (s) => _after(s, 'while ('));
|
| }
|
|
|
| - test_completeDoNoBody() async {
|
| + test_noBody() async {
|
| await _prepareCompletion(
|
| 'do',
|
| '''
|
| @@ -85,10 +152,10 @@ main() {
|
| } while ();
|
| }
|
| ''',
|
| - (s) => s.indexOf('while (') + 'while ('.length);
|
| + (s) => _after(s, 'while ('));
|
| }
|
|
|
| - test_completeDoNoCondition() async {
|
| + test_noCondition() async {
|
| await _prepareCompletion(
|
| 'while',
|
| '''
|
| @@ -106,10 +173,10 @@ main() {
|
| } while ();
|
| }
|
| ''',
|
| - (s) => s.indexOf('while (') + 'while ('.length);
|
| + (s) => _after(s, 'while ('));
|
| }
|
|
|
| - test_completeDoNoWhile() async {
|
| + test_noWhile() async {
|
| await _prepareCompletion(
|
| '}',
|
| '''
|
| @@ -127,10 +194,163 @@ main() {
|
| } while ();
|
| }
|
| ''',
|
| - (s) => s.indexOf('while (') + 'while ('.length);
|
| + (s) => _after(s, 'while ('));
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class _ForCompletionTest extends StatementCompletionTest {
|
| + test_emptyCondition() async {
|
| + await _prepareCompletion(
|
| + '}',
|
| + '''
|
| +main() {
|
| + for (int i = 0;) {
|
| + }
|
| +}
|
| +''',
|
| + atEnd: true);
|
| + _assertHasChange(
|
| + 'Complete for-statement',
|
| + '''
|
| +main() {
|
| + for (int i = 0; ) {
|
| + }
|
| +}
|
| +''',
|
| + (s) => _after(s, '0; '));
|
| + }
|
| +
|
| + test_emptyInitializers() async {
|
| + await _prepareCompletion(
|
| + '}',
|
| + '''
|
| +main() {
|
| + for () {
|
| + }
|
| +}
|
| +''',
|
| + atEnd: true);
|
| + _assertHasChange(
|
| + 'Complete for-statement',
|
| + '''
|
| +main() {
|
| + for () {
|
| + }
|
| +}
|
| +''',
|
| + (s) => _after(s, 'for ('));
|
| + }
|
| +
|
| + test_emptyInitializersEmptyCondition() async {
|
| + await _prepareCompletion(
|
| + '}',
|
| + '''
|
| +main() {
|
| + for (;/**/) {
|
| + }
|
| +}
|
| +''',
|
| + atEnd: true);
|
| + _assertHasChange(
|
| + 'Complete for-statement',
|
| + '''
|
| +main() {
|
| + for (;/**/) {
|
| + }
|
| +}
|
| +''',
|
| + (s) => _after(s, '/**/'));
|
| }
|
|
|
| - test_completeIfAfterCondition_BAD() async {
|
| + test_emptyParts() async {
|
| + await _prepareCompletion(
|
| + ';)',
|
| + '''
|
| +main() {
|
| + for (;;)
|
| +}
|
| +''',
|
| + atEnd: true);
|
| + _assertHasChange(
|
| + 'Complete for-statement',
|
| + '''
|
| +main() {
|
| + for (;;) {
|
| + ////
|
| + }
|
| +}
|
| +''',
|
| + (s) => _after(s, ' '));
|
| + }
|
| +
|
| + test_emptyUpdaters() async {
|
| + await _prepareCompletion(
|
| + '}',
|
| + '''
|
| +main() {
|
| + for (int i = 0; i < 10 /**/) {
|
| + }
|
| +}
|
| +''',
|
| + atEnd: true);
|
| + _assertHasChange(
|
| + 'Complete for-statement',
|
| + '''
|
| +main() {
|
| + for (int i = 0; i < 10 /**/; ) {
|
| + }
|
| +}
|
| +''',
|
| + (s) => _after(s, '10 /**/; '));
|
| + }
|
| +
|
| + test_keywordOnly() async {
|
| + await _prepareCompletion(
|
| + 'for',
|
| + '''
|
| +main() {
|
| + for
|
| +}
|
| +''',
|
| + atEnd: true);
|
| + _assertHasChange(
|
| + 'Complete for-statement',
|
| + '''
|
| +main() {
|
| + for () {
|
| + ////
|
| + }
|
| +}
|
| +''',
|
| + (s) => _after(s, 'for ('));
|
| + }
|
| +
|
| + test_missingLeftSeparator() async {
|
| + await _prepareCompletion(
|
| + '}',
|
| + '''
|
| +main() {
|
| + for (int i = 0) {
|
| + }
|
| +}
|
| +''',
|
| + atEnd: true);
|
| + _assertHasChange(
|
| + 'Complete for-statement',
|
| + '''
|
| +main() {
|
| + for (int i = 0; ) {
|
| + }
|
| +}
|
| +''',
|
| + (s) => _after(s, '0; '));
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class _IfCompletionTest extends StatementCompletionTest {
|
| + test_afterCondition_BAD() async {
|
| // TODO(messick): Fix the code to make this like test_completeIfWithCondition.
|
| // Recap: Finding the node at the selectionOffset returns the block, not the
|
| // if-statement. Need to understand if that only happens when the if-statement
|
| @@ -153,10 +373,10 @@ main() {
|
| }
|
| }
|
| ''',
|
| - (s) => s.indexOf('if (true) ') + 'if (true) '.length);
|
| + (s) => _after(s, 'if (true) '));
|
| }
|
|
|
| - test_completeIfEmptyCondition() async {
|
| + test_emptyCondition() async {
|
| await _prepareCompletion(
|
| 'if ()',
|
| '''
|
| @@ -174,10 +394,10 @@ main() {
|
| }
|
| }
|
| ''',
|
| - (s) => s.indexOf('if (') + 'if ('.length);
|
| + (s) => _after(s, 'if ('));
|
| }
|
|
|
| - test_completeIfKeywordOnly() async {
|
| + test_keywordOnly() async {
|
| await _prepareCompletion(
|
| 'if',
|
| '''
|
| @@ -195,10 +415,10 @@ main() {
|
| }
|
| }
|
| ''',
|
| - (s) => s.indexOf('if (') + 'if ('.length);
|
| + (s) => _after(s, 'if ('));
|
| }
|
|
|
| - test_completeIfWithCondition() async {
|
| + test_withCondition() async {
|
| await _prepareCompletion(
|
| 'if (tr', // Trigger completion from within expression.
|
| '''
|
| @@ -216,10 +436,10 @@ main() {
|
| }
|
| }
|
| ''',
|
| - (s) => s.indexOf(' ') + ' '.length);
|
| + (s) => _after(s, ' '));
|
| }
|
|
|
| - test_completeIfWithElse_BAD() async {
|
| + test_withElse_BAD() async {
|
| await _prepareCompletion(
|
| 'if ()',
|
| '''
|
| @@ -239,10 +459,10 @@ main() {
|
| }
|
| }
|
| ''',
|
| - (s) => s.indexOf('if ()') + 'if ()'.length);
|
| + (s) => _after(s, 'if ()'));
|
| }
|
|
|
| - test_completeIfWithinEmptyCondition() async {
|
| + test_withinEmptyCondition() async {
|
| await _prepareCompletion(
|
| 'if (',
|
| '''
|
| @@ -260,31 +480,13 @@ main() {
|
| }
|
| }
|
| ''',
|
| - (s) => s.indexOf('if (') + 'if ('.length);
|
| + (s) => _after(s, 'if ('));
|
| }
|
| -
|
| - test_completeWhileKeywordOnly() async {
|
| - await _prepareCompletion(
|
| - 'while',
|
| - '''
|
| -main() {
|
| - while ////
|
| }
|
| -''',
|
| - atEnd: true);
|
| - _assertHasChange(
|
| - 'Complete while-statement',
|
| - '''
|
| -main() {
|
| - while () {
|
| - ////
|
| - }
|
| -}
|
| -''',
|
| - (s) => s.indexOf('while (') + 'while ('.length);
|
| - }
|
|
|
| - test_simpleEnter() async {
|
| +@reflectiveTest
|
| +class _SimpleCompletionTest extends StatementCompletionTest {
|
| + test_enter() async {
|
| await _prepareCompletion(
|
| 'v = 1;',
|
| '''
|
| @@ -303,7 +505,7 @@ main() {
|
| ''');
|
| }
|
|
|
| - test_simpleSemicolon() async {
|
| + test_semicolon() async {
|
| await _prepareCompletion(
|
| 'v = 1',
|
| '''
|
| @@ -320,61 +522,37 @@ main() {
|
| ////
|
| }
|
| ''',
|
| - (s) => s.lastIndexOf(' ') + ' '.length);
|
| - }
|
| -
|
| - void _assertHasChange(String message, String expectedCode, [Function cmp]) {
|
| - if (change.message == message) {
|
| - if (!change.edits.isEmpty) {
|
| - String resultCode =
|
| - SourceEdit.applySequence(testCode, change.edits[0].edits);
|
| - expect(resultCode, expectedCode.replaceAll('////', ''));
|
| - if (cmp != null) {
|
| - int offset = cmp(resultCode);
|
| - expect(change.selection.offset, offset);
|
| - }
|
| - } else {
|
| - if (cmp != null) {
|
| - int offset = cmp(testCode);
|
| - expect(change.selection.offset, offset);
|
| - }
|
| - }
|
| - return;
|
| - }
|
| - fail("Expected to find |$message| but got: " + change.message);
|
| - }
|
| -
|
| - _computeCompletion(int offset) async {
|
| - driver.changeFile(testFile);
|
| - AnalysisResult result = await driver.getResult(testFile);
|
| - StatementCompletionContext context = new StatementCompletionContext(
|
| - testFile,
|
| - result.lineInfo,
|
| - offset,
|
| - testUnit,
|
| - testUnitElement,
|
| - result.errors);
|
| - StatementCompletionProcessor processor =
|
| - new StatementCompletionProcessor(context);
|
| - StatementCompletion completion = await processor.compute();
|
| - change = completion.change;
|
| + (s) => _afterLast(s, ' '));
|
| }
|
| +}
|
|
|
| - _prepareCompletion(String search, String sourceCode,
|
| - {bool atStart: false, bool atEnd: false, int delta: 0}) async {
|
| - testCode = sourceCode.replaceAll('////', '');
|
| - int offset = findOffset(search);
|
| - if (atStart) {
|
| - delta = 0;
|
| - } else if (atEnd) {
|
| - delta = search.length;
|
| - }
|
| - await _prepareCompletionAt(offset + delta, testCode);
|
| +@reflectiveTest
|
| +class _WhileCompletionTest extends StatementCompletionTest {
|
| + /*
|
| + The implementation of completion for while-statements is shared with
|
| + if-statements. Here we check that the wrapper for while-statements
|
| + functions as expected. The individual test cases are covered by the
|
| + _IfCompletionTest tests. If the implementation changes then the same
|
| + set of tests defined for if-statements should be duplicated here.
|
| + */
|
| + test_keywordOnly() async {
|
| + await _prepareCompletion(
|
| + 'while',
|
| + '''
|
| +main() {
|
| + while ////
|
| +}
|
| +''',
|
| + atEnd: true);
|
| + _assertHasChange(
|
| + 'Complete while-statement',
|
| + '''
|
| +main() {
|
| + while () {
|
| + ////
|
| }
|
| -
|
| - _prepareCompletionAt(int offset, String sourceCode) async {
|
| - verifyNoTestUnitErrors = false;
|
| - await resolveTestUnit(sourceCode);
|
| - await _computeCompletion(offset);
|
| +}
|
| +''',
|
| + (s) => _after(s, 'while ('));
|
| }
|
| }
|
|
|