| 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.correction.assist; | 5 library test.services.correction.assist; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 | 8 |
| 9 import 'package:analysis_server/plugin/edit/assist/assist_core.dart'; | 9 import 'package:analysis_server/plugin/edit/assist/assist_core.dart'; |
| 10 import 'package:analysis_server/plugin/edit/assist/assist_dart.dart'; |
| 10 import 'package:analysis_server/plugin/protocol/protocol.dart'; | 11 import 'package:analysis_server/plugin/protocol/protocol.dart'; |
| 11 import 'package:analysis_server/src/plugin/server_plugin.dart'; | 12 import 'package:analysis_server/src/plugin/server_plugin.dart'; |
| 12 import 'package:analysis_server/src/services/correction/assist.dart'; | 13 import 'package:analysis_server/src/services/correction/assist.dart'; |
| 14 import 'package:analysis_server/src/services/correction/assist_internal.dart'; |
| 15 import 'package:analyzer/dart/ast/ast.dart'; |
| 13 import 'package:analyzer/dart/ast/standard_resolution_map.dart'; | 16 import 'package:analyzer/dart/ast/standard_resolution_map.dart'; |
| 17 import 'package:analyzer/dart/element/element.dart'; |
| 14 import 'package:analyzer/src/generated/engine.dart'; | 18 import 'package:analyzer/src/generated/engine.dart'; |
| 15 import 'package:analyzer/src/generated/source.dart'; | 19 import 'package:analyzer/src/generated/source.dart'; |
| 16 import 'package:plugin/manager.dart'; | 20 import 'package:plugin/manager.dart'; |
| 17 import 'package:plugin/plugin.dart'; | 21 import 'package:plugin/plugin.dart'; |
| 18 import 'package:test/test.dart'; | 22 import 'package:test/test.dart'; |
| 19 import 'package:test_reflective_loader/test_reflective_loader.dart'; | 23 import 'package:test_reflective_loader/test_reflective_loader.dart'; |
| 20 | 24 |
| 21 import '../../abstract_single_unit.dart'; | 25 import '../../abstract_single_unit.dart'; |
| 22 | 26 |
| 23 main() { | 27 main() { |
| 24 defineReflectiveSuite(() { | 28 defineReflectiveSuite(() { |
| 25 defineReflectiveTests(AssistProcessorTest); | 29 defineReflectiveTests(AssistProcessorTest); |
| 30 defineReflectiveTests(AssistProcessorTest_Driver); |
| 26 }); | 31 }); |
| 27 } | 32 } |
| 28 | 33 |
| 29 @reflectiveTest | 34 @reflectiveTest |
| 30 class AssistProcessorTest extends AbstractSingleUnitTest { | 35 class AssistProcessorTest extends AbstractSingleUnitTest { |
| 31 int offset; | 36 int offset; |
| 32 int length; | 37 int length; |
| 33 | 38 |
| 34 ServerPlugin plugin; | 39 ServerPlugin plugin; |
| 35 Assist assist; | 40 Assist assist; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 58 assertHasAssistAt( | 63 assertHasAssistAt( |
| 59 String offsetSearch, AssistKind kind, String expected) async { | 64 String offsetSearch, AssistKind kind, String expected) async { |
| 60 offset = findOffset(offsetSearch); | 65 offset = findOffset(offsetSearch); |
| 61 await assertHasAssist(kind, expected); | 66 await assertHasAssist(kind, expected); |
| 62 } | 67 } |
| 63 | 68 |
| 64 /** | 69 /** |
| 65 * Asserts that there is no [Assist] of the given [kind] at [offset]. | 70 * Asserts that there is no [Assist] of the given [kind] at [offset]. |
| 66 */ | 71 */ |
| 67 assertNoAssist(AssistKind kind) async { | 72 assertNoAssist(AssistKind kind) async { |
| 68 List<Assist> assists = await computeAssists( | 73 List<Assist> assists = await _computeAssists(); |
| 69 plugin, | |
| 70 context, | |
| 71 resolutionMap.elementDeclaredByCompilationUnit(testUnit).source, | |
| 72 offset, | |
| 73 length); | |
| 74 for (Assist assist in assists) { | 74 for (Assist assist in assists) { |
| 75 if (assist.kind == kind) { | 75 if (assist.kind == kind) { |
| 76 throw fail('Unexpected assist $kind in\n${assists.join('\n')}'); | 76 throw fail('Unexpected assist $kind in\n${assists.join('\n')}'); |
| 77 } | 77 } |
| 78 } | 78 } |
| 79 } | 79 } |
| 80 | 80 |
| 81 /** | 81 /** |
| 82 * Calls [assertNoAssist] at the offset of [offsetSearch] in [testCode]. | 82 * Calls [assertNoAssist] at the offset of [offsetSearch] in [testCode]. |
| 83 */ | 83 */ |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 498 main() { | 498 main() { |
| 499 var v = getFutureInt(); | 499 var v = getFutureInt(); |
| 500 } | 500 } |
| 501 '''; | 501 '''; |
| 502 // add sources | 502 // add sources |
| 503 Source appSource = addSource('/app.dart', appCode); | 503 Source appSource = addSource('/app.dart', appCode); |
| 504 testSource = addSource('/test.dart', testCode); | 504 testSource = addSource('/test.dart', testCode); |
| 505 // resolve | 505 // resolve |
| 506 context.resolveCompilationUnit2(appSource, appSource); | 506 context.resolveCompilationUnit2(appSource, appSource); |
| 507 testUnit = context.resolveCompilationUnit2(testSource, appSource); | 507 testUnit = context.resolveCompilationUnit2(testSource, appSource); |
| 508 assertNoErrorsInSource(testSource); | |
| 509 testUnitElement = testUnit.element; | 508 testUnitElement = testUnit.element; |
| 510 testLibraryElement = testUnitElement.library; | 509 testLibraryElement = testUnitElement.library; |
| 511 // prepare the assist | 510 // prepare the assist |
| 512 offset = findOffset('v = '); | 511 offset = findOffset('v = '); |
| 513 assist = await _assertHasAssist(DartAssistKind.ADD_TYPE_ANNOTATION); | 512 assist = await _assertHasAssist(DartAssistKind.ADD_TYPE_ANNOTATION); |
| 514 change = assist.change; | 513 change = assist.change; |
| 515 // verify | 514 // verify |
| 516 { | 515 { |
| 517 var testFileEdit = change.getFileEdit('/app.dart'); | 516 var testFileEdit = change.getFileEdit('/app.dart'); |
| 518 var resultCode = SourceEdit.applySequence(appCode, testFileEdit.edits); | 517 var resultCode = SourceEdit.applySequence(appCode, testFileEdit.edits); |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 806 }); | 805 }); |
| 807 } | 806 } |
| 808 '''); | 807 '''); |
| 809 } | 808 } |
| 810 | 809 |
| 811 test_assignToLocalVariable_invocationArgument() async { | 810 test_assignToLocalVariable_invocationArgument() async { |
| 812 await resolveTestUnit(r''' | 811 await resolveTestUnit(r''' |
| 813 main() { | 812 main() { |
| 814 f(12345); | 813 f(12345); |
| 815 } | 814 } |
| 816 int f(p) {} | 815 void f(p) {} |
| 817 '''); | 816 '''); |
| 818 await assertNoAssistAt('345', DartAssistKind.ASSIGN_TO_LOCAL_VARIABLE); | 817 await assertNoAssistAt('345', DartAssistKind.ASSIGN_TO_LOCAL_VARIABLE); |
| 819 } | 818 } |
| 820 | 819 |
| 821 test_assignToLocalVariable_throw() async { | 820 test_assignToLocalVariable_throw() async { |
| 822 await resolveTestUnit(''' | 821 await resolveTestUnit(''' |
| 823 main() { | 822 main() { |
| 824 throw 42; | 823 throw 42; |
| 825 } | 824 } |
| 826 '''); | 825 '''); |
| (...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1353 int aaa2; | 1352 int aaa2; |
| 1354 A(int aaa) : aaa2 = aaa * 2; | 1353 A(int aaa) : aaa2 = aaa * 2; |
| 1355 } | 1354 } |
| 1356 '''); | 1355 '''); |
| 1357 await assertNoAssistAt('aaa)', DartAssistKind.CONVERT_TO_FIELD_PARAMETER); | 1356 await assertNoAssistAt('aaa)', DartAssistKind.CONVERT_TO_FIELD_PARAMETER); |
| 1358 } | 1357 } |
| 1359 | 1358 |
| 1360 test_convertToFieldParameter_OK_firstInitializer() async { | 1359 test_convertToFieldParameter_OK_firstInitializer() async { |
| 1361 await resolveTestUnit(''' | 1360 await resolveTestUnit(''' |
| 1362 class A { | 1361 class A { |
| 1363 double aaa2; | 1362 int aaa2; |
| 1364 int bbb2; | 1363 int bbb2; |
| 1365 A(int aaa, int bbb) : aaa2 = aaa, bbb2 = bbb; | 1364 A(int aaa, int bbb) : aaa2 = aaa, bbb2 = bbb; |
| 1366 } | 1365 } |
| 1367 '''); | 1366 '''); |
| 1368 await assertHasAssistAt( | 1367 await assertHasAssistAt( |
| 1369 'aaa, ', | 1368 'aaa, ', |
| 1370 DartAssistKind.CONVERT_TO_FIELD_PARAMETER, | 1369 DartAssistKind.CONVERT_TO_FIELD_PARAMETER, |
| 1371 ''' | 1370 ''' |
| 1372 class A { | 1371 class A { |
| 1373 double aaa2; | 1372 int aaa2; |
| 1374 int bbb2; | 1373 int bbb2; |
| 1375 A(this.aaa2, int bbb) : bbb2 = bbb; | 1374 A(this.aaa2, int bbb) : bbb2 = bbb; |
| 1376 } | 1375 } |
| 1377 '''); | 1376 '''); |
| 1378 } | 1377 } |
| 1379 | 1378 |
| 1380 test_convertToFieldParameter_OK_onParameterName_inInitializer() async { | 1379 test_convertToFieldParameter_OK_onParameterName_inInitializer() async { |
| 1381 await resolveTestUnit(''' | 1380 await resolveTestUnit(''' |
| 1382 class A { | 1381 class A { |
| 1383 int test2; | 1382 int test2; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1413 int test; | 1412 int test; |
| 1414 A(this.test) { | 1413 A(this.test) { |
| 1415 } | 1414 } |
| 1416 } | 1415 } |
| 1417 '''); | 1416 '''); |
| 1418 } | 1417 } |
| 1419 | 1418 |
| 1420 test_convertToFieldParameter_OK_secondInitializer() async { | 1419 test_convertToFieldParameter_OK_secondInitializer() async { |
| 1421 await resolveTestUnit(''' | 1420 await resolveTestUnit(''' |
| 1422 class A { | 1421 class A { |
| 1423 double aaa2; | 1422 int aaa2; |
| 1424 int bbb2; | 1423 int bbb2; |
| 1425 A(int aaa, int bbb) : aaa2 = aaa, bbb2 = bbb; | 1424 A(int aaa, int bbb) : aaa2 = aaa, bbb2 = bbb; |
| 1426 } | 1425 } |
| 1427 '''); | 1426 '''); |
| 1428 await assertHasAssistAt( | 1427 await assertHasAssistAt( |
| 1429 'bbb)', | 1428 'bbb)', |
| 1430 DartAssistKind.CONVERT_TO_FIELD_PARAMETER, | 1429 DartAssistKind.CONVERT_TO_FIELD_PARAMETER, |
| 1431 ''' | 1430 ''' |
| 1432 class A { | 1431 class A { |
| 1433 double aaa2; | 1432 int aaa2; |
| 1434 int bbb2; | 1433 int bbb2; |
| 1435 A(int aaa, this.bbb2) : aaa2 = aaa; | 1434 A(int aaa, this.bbb2) : aaa2 = aaa; |
| 1436 } | 1435 } |
| 1437 '''); | 1436 '''); |
| 1438 } | 1437 } |
| 1439 | 1438 |
| 1440 test_convertToFinalField_BAD_hasSetter_inThisClass() async { | 1439 test_convertToFinalField_BAD_hasSetter_inThisClass() async { |
| 1441 await resolveTestUnit(''' | 1440 await resolveTestUnit(''' |
| 1442 class A { | 1441 class A { |
| 1443 int get foo => null; | 1442 int get foo => null; |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1768 for (int k = 0; k < items.length; k++) { | 1767 for (int k = 0; k < items.length; k++) { |
| 1769 String item = items[k]; | 1768 String item = items[k]; |
| 1770 print(item); | 1769 print(item); |
| 1771 int i = 0, j = 1; | 1770 int i = 0, j = 1; |
| 1772 } | 1771 } |
| 1773 } | 1772 } |
| 1774 '''); | 1773 '''); |
| 1775 } | 1774 } |
| 1776 | 1775 |
| 1777 test_convertToGetter_BAD_noInitializer() async { | 1776 test_convertToGetter_BAD_noInitializer() async { |
| 1777 verifyNoTestUnitErrors = false; |
| 1778 await resolveTestUnit(''' | 1778 await resolveTestUnit(''' |
| 1779 class A { | 1779 class A { |
| 1780 final int foo; | 1780 final int foo; |
| 1781 } | 1781 } |
| 1782 '''); | 1782 '''); |
| 1783 await assertNoAssistAt('foo', DartAssistKind.CONVERT_INTO_GETTER); | 1783 await assertNoAssistAt('foo', DartAssistKind.CONVERT_INTO_GETTER); |
| 1784 } | 1784 } |
| 1785 | 1785 |
| 1786 test_convertToGetter_BAD_notFinal() async { | 1786 test_convertToGetter_BAD_notFinal() async { |
| 1787 await resolveTestUnit(''' | 1787 await resolveTestUnit(''' |
| (...skipping 703 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2491 await resolveTestUnit(''' | 2491 await resolveTestUnit(''' |
| 2492 import 'dart:math' show PI; | 2492 import 'dart:math' show PI; |
| 2493 main() { | 2493 main() { |
| 2494 PI; | 2494 PI; |
| 2495 } | 2495 } |
| 2496 '''); | 2496 '''); |
| 2497 await assertNoAssistAt('import ', DartAssistKind.IMPORT_ADD_SHOW); | 2497 await assertNoAssistAt('import ', DartAssistKind.IMPORT_ADD_SHOW); |
| 2498 } | 2498 } |
| 2499 | 2499 |
| 2500 test_importAddShow_BAD_unresolvedUri() async { | 2500 test_importAddShow_BAD_unresolvedUri() async { |
| 2501 verifyNoTestUnitErrors = false; |
| 2501 await resolveTestUnit(''' | 2502 await resolveTestUnit(''' |
| 2502 import '/no/such/lib.dart'; | 2503 import '/no/such/lib.dart'; |
| 2503 '''); | 2504 '''); |
| 2504 await assertNoAssistAt('import ', DartAssistKind.IMPORT_ADD_SHOW); | 2505 await assertNoAssistAt('import ', DartAssistKind.IMPORT_ADD_SHOW); |
| 2505 } | 2506 } |
| 2506 | 2507 |
| 2507 test_importAddShow_BAD_unused() async { | 2508 test_importAddShow_BAD_unused() async { |
| 2508 await resolveTestUnit(''' | 2509 await resolveTestUnit(''' |
| 2509 import 'dart:math'; | 2510 import 'dart:math'; |
| 2510 '''); | 2511 '''); |
| (...skipping 1644 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4155 } | 4156 } |
| 4156 // end | 4157 // end |
| 4157 } | 4158 } |
| 4158 '''); | 4159 '''); |
| 4159 } | 4160 } |
| 4160 | 4161 |
| 4161 /** | 4162 /** |
| 4162 * Computes assists and verifies that there is an assist of the given kind. | 4163 * Computes assists and verifies that there is an assist of the given kind. |
| 4163 */ | 4164 */ |
| 4164 Future<Assist> _assertHasAssist(AssistKind kind) async { | 4165 Future<Assist> _assertHasAssist(AssistKind kind) async { |
| 4165 List<Assist> assists = await computeAssists( | 4166 List<Assist> assists = await _computeAssists(); |
| 4166 plugin, | |
| 4167 context, | |
| 4168 resolutionMap.elementDeclaredByCompilationUnit(testUnit).source, | |
| 4169 offset, | |
| 4170 length); | |
| 4171 for (Assist assist in assists) { | 4167 for (Assist assist in assists) { |
| 4172 if (assist.kind == kind) { | 4168 if (assist.kind == kind) { |
| 4173 return assist; | 4169 return assist; |
| 4174 } | 4170 } |
| 4175 } | 4171 } |
| 4176 throw fail('Expected to find assist $kind in\n${assists.join('\n')}'); | 4172 throw fail('Expected to find assist $kind in\n${assists.join('\n')}'); |
| 4177 } | 4173 } |
| 4178 | 4174 |
| 4179 void _assertLinkedGroup(LinkedEditGroup group, List<String> expectedStrings, | 4175 void _assertLinkedGroup(LinkedEditGroup group, List<String> expectedStrings, |
| 4180 [List<LinkedEditSuggestion> expectedSuggestions]) { | 4176 [List<LinkedEditSuggestion> expectedSuggestions]) { |
| 4181 List<Position> expectedPositions = _findResultPositions(expectedStrings); | 4177 List<Position> expectedPositions = _findResultPositions(expectedStrings); |
| 4182 expect(group.positions, unorderedEquals(expectedPositions)); | 4178 expect(group.positions, unorderedEquals(expectedPositions)); |
| 4183 if (expectedSuggestions != null) { | 4179 if (expectedSuggestions != null) { |
| 4184 expect(group.suggestions, unorderedEquals(expectedSuggestions)); | 4180 expect(group.suggestions, unorderedEquals(expectedSuggestions)); |
| 4185 } | 4181 } |
| 4186 } | 4182 } |
| 4187 | 4183 |
| 4184 Future<List<Assist>> _computeAssists() async { |
| 4185 CompilationUnitElement testUnitElement = |
| 4186 resolutionMap.elementDeclaredByCompilationUnit(testUnit); |
| 4187 DartAssistContext assistContext = new _DartAssistContextForValues( |
| 4188 testUnitElement.source, |
| 4189 offset, |
| 4190 length, |
| 4191 testUnitElement.context, |
| 4192 testUnit); |
| 4193 AssistProcessor processor = new AssistProcessor(assistContext); |
| 4194 return await processor.compute(); |
| 4195 } |
| 4196 |
| 4188 List<Position> _findResultPositions(List<String> searchStrings) { | 4197 List<Position> _findResultPositions(List<String> searchStrings) { |
| 4189 List<Position> positions = <Position>[]; | 4198 List<Position> positions = <Position>[]; |
| 4190 for (String search in searchStrings) { | 4199 for (String search in searchStrings) { |
| 4191 int offset = resultCode.indexOf(search); | 4200 int offset = resultCode.indexOf(search); |
| 4192 positions.add(new Position(testFile, offset)); | 4201 positions.add(new Position(testFile, offset)); |
| 4193 } | 4202 } |
| 4194 return positions; | 4203 return positions; |
| 4195 } | 4204 } |
| 4196 | 4205 |
| 4197 void _setStartEndSelection() { | 4206 void _setStartEndSelection() { |
| 4198 offset = findOffset('// start\n') + '// start\n'.length; | 4207 offset = findOffset('// start\n') + '// start\n'.length; |
| 4199 length = findOffset('// end') - offset; | 4208 length = findOffset('// end') - offset; |
| 4200 } | 4209 } |
| 4201 } | 4210 } |
| 4211 |
| 4212 @reflectiveTest |
| 4213 class AssistProcessorTest_Driver extends AssistProcessorTest { |
| 4214 @override |
| 4215 bool get enableNewAnalysisDriver => true; |
| 4216 |
| 4217 @failingTest |
| 4218 @override |
| 4219 test_addTypeAnnotation_local_OK_addImport_notLibraryUnit() { |
| 4220 return test_addTypeAnnotation_local_OK_addImport_notLibraryUnit(); |
| 4221 } |
| 4222 |
| 4223 @failingTest |
| 4224 @override |
| 4225 test_invalidSelection() { |
| 4226 return test_invalidSelection(); |
| 4227 } |
| 4228 } |
| 4229 |
| 4230 class _DartAssistContextForValues implements DartAssistContext { |
| 4231 @override |
| 4232 final Source source; |
| 4233 |
| 4234 @override |
| 4235 final int selectionOffset; |
| 4236 |
| 4237 @override |
| 4238 final int selectionLength; |
| 4239 |
| 4240 @override |
| 4241 final AnalysisContext analysisContext; |
| 4242 |
| 4243 @override |
| 4244 final CompilationUnit unit; |
| 4245 |
| 4246 _DartAssistContextForValues(this.source, this.selectionOffset, |
| 4247 this.selectionLength, this.analysisContext, this.unit); |
| 4248 } |
| OLD | NEW |