| 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.fix; | 5 library test.services.correction.fix; |
| 6 | 6 |
| 7 import 'package:analysis_server/edit/fix/fix_core.dart'; | 7 import 'package:analysis_server/edit/fix/fix_core.dart'; |
| 8 import 'package:analysis_server/src/plugin/server_plugin.dart'; | |
| 9 import 'package:analysis_server/src/protocol.dart' hide AnalysisError; | 8 import 'package:analysis_server/src/protocol.dart' hide AnalysisError; |
| 10 import 'package:analysis_server/src/services/correction/fix.dart'; | 9 import 'package:analysis_server/src/services/correction/fix.dart'; |
| 10 import 'package:analysis_server/src/services/correction/fix_internal.dart'; |
| 11 import 'package:analyzer/file_system/file_system.dart'; | 11 import 'package:analyzer/file_system/file_system.dart'; |
| 12 import 'package:analyzer/source/package_map_resolver.dart'; | 12 import 'package:analyzer/source/package_map_resolver.dart'; |
| 13 import 'package:analyzer/src/generated/error.dart'; | 13 import 'package:analyzer/src/generated/error.dart'; |
| 14 import 'package:analyzer/src/generated/parser.dart'; | 14 import 'package:analyzer/src/generated/parser.dart'; |
| 15 import 'package:analyzer/src/generated/source.dart'; | 15 import 'package:analyzer/src/generated/source.dart'; |
| 16 import 'package:analyzer/src/plugin/plugin_impl.dart'; | |
| 17 import 'package:unittest/unittest.dart'; | 16 import 'package:unittest/unittest.dart'; |
| 18 | 17 |
| 19 import '../../abstract_context.dart'; | 18 import '../../abstract_context.dart'; |
| 20 import '../../abstract_single_unit.dart'; | 19 import '../../abstract_single_unit.dart'; |
| 21 import '../../reflective_tests.dart'; | 20 import '../../reflective_tests.dart'; |
| 22 | 21 |
| 23 main() { | 22 main() { |
| 24 groupSep = ' | '; | 23 groupSep = ' | '; |
| 25 runReflectiveTests(FixProcessorTest); | 24 runReflectiveTests(FixProcessorTest); |
| 26 } | 25 } |
| 27 | 26 |
| 28 typedef bool AnalysisErrorFilter(AnalysisError error); | 27 typedef bool AnalysisErrorFilter(AnalysisError error); |
| 29 | 28 |
| 30 @reflectiveTest | 29 @reflectiveTest |
| 31 class FixProcessorTest extends AbstractSingleUnitTest { | 30 class FixProcessorTest extends AbstractSingleUnitTest { |
| 32 AnalysisErrorFilter errorFilter = (AnalysisError error) { | 31 AnalysisErrorFilter errorFilter = (AnalysisError error) { |
| 33 return error.errorCode != HintCode.UNUSED_CATCH_CLAUSE && | 32 return error.errorCode != HintCode.UNUSED_CATCH_CLAUSE && |
| 34 error.errorCode != HintCode.UNUSED_CATCH_STACK && | 33 error.errorCode != HintCode.UNUSED_CATCH_STACK && |
| 35 error.errorCode != HintCode.UNUSED_ELEMENT && | 34 error.errorCode != HintCode.UNUSED_ELEMENT && |
| 36 error.errorCode != HintCode.UNUSED_FIELD && | 35 error.errorCode != HintCode.UNUSED_FIELD && |
| 37 error.errorCode != HintCode.UNUSED_LOCAL_VARIABLE; | 36 error.errorCode != HintCode.UNUSED_LOCAL_VARIABLE; |
| 38 }; | 37 }; |
| 39 | 38 |
| 40 ServerPlugin plugin; | |
| 41 Fix fix; | 39 Fix fix; |
| 42 SourceChange change; | 40 SourceChange change; |
| 43 String resultCode; | 41 String resultCode; |
| 44 | 42 |
| 45 void assert_undefinedFunction_create_returnType_bool(String lineWithTest) { | 43 void assert_undefinedFunction_create_returnType_bool(String lineWithTest) { |
| 46 resolveTestUnit(''' | 44 resolveTestUnit(''' |
| 47 main() { | 45 main() { |
| 48 bool b = true; | 46 bool b = true; |
| 49 $lineWithTest | 47 $lineWithTest |
| 50 } | 48 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 67 // apply to "file" | 65 // apply to "file" |
| 68 List<SourceFileEdit> fileEdits = change.edits; | 66 List<SourceFileEdit> fileEdits = change.edits; |
| 69 expect(fileEdits, hasLength(1)); | 67 expect(fileEdits, hasLength(1)); |
| 70 resultCode = SourceEdit.applySequence(testCode, change.edits[0].edits); | 68 resultCode = SourceEdit.applySequence(testCode, change.edits[0].edits); |
| 71 // verify | 69 // verify |
| 72 expect(resultCode, expected); | 70 expect(resultCode, expected); |
| 73 } | 71 } |
| 74 | 72 |
| 75 void assertNoFix(FixKind kind) { | 73 void assertNoFix(FixKind kind) { |
| 76 AnalysisError error = _findErrorToFix(); | 74 AnalysisError error = _findErrorToFix(); |
| 77 List<Fix> fixes = computeFixes(plugin, context, error); | 75 List<Fix> fixes = _computeFixes(error); |
| 78 for (Fix fix in fixes) { | 76 for (Fix fix in fixes) { |
| 79 if (fix.kind == kind) { | 77 if (fix.kind == kind) { |
| 80 throw fail('Unexpected fix $kind in\n${fixes.join('\n')}'); | 78 throw fail('Unexpected fix $kind in\n${fixes.join('\n')}'); |
| 81 } | 79 } |
| 82 } | 80 } |
| 83 } | 81 } |
| 84 | 82 |
| 85 Position expectedPosition(String search) { | 83 Position expectedPosition(String search) { |
| 86 int offset = resultCode.indexOf(search); | 84 int offset = resultCode.indexOf(search); |
| 87 return new Position(testFile, offset); | 85 return new Position(testFile, offset); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 98 List<LinkedEditSuggestion> expectedSuggestions( | 96 List<LinkedEditSuggestion> expectedSuggestions( |
| 99 LinkedEditSuggestionKind kind, List<String> values) { | 97 LinkedEditSuggestionKind kind, List<String> values) { |
| 100 return values.map((value) { | 98 return values.map((value) { |
| 101 return new LinkedEditSuggestion(value, kind); | 99 return new LinkedEditSuggestion(value, kind); |
| 102 }).toList(); | 100 }).toList(); |
| 103 } | 101 } |
| 104 | 102 |
| 105 void setUp() { | 103 void setUp() { |
| 106 super.setUp(); | 104 super.setUp(); |
| 107 verifyNoTestUnitErrors = false; | 105 verifyNoTestUnitErrors = false; |
| 108 ExtensionManager manager = new ExtensionManager(); | |
| 109 plugin = new ServerPlugin(); | |
| 110 manager.processPlugins([plugin]); | |
| 111 } | 106 } |
| 112 | 107 |
| 113 void test_addFieldFormalParameters_hasRequiredParameter() { | 108 void test_addFieldFormalParameters_hasRequiredParameter() { |
| 114 resolveTestUnit(''' | 109 resolveTestUnit(''' |
| 115 class Test { | 110 class Test { |
| 116 final int a; | 111 final int a; |
| 117 final int b; | 112 final int b; |
| 118 final int c; | 113 final int c; |
| 119 Test(this.a); | 114 Test(this.a); |
| 120 } | 115 } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 160 assertHasFix(DartFixKind.ADD_FIELD_FORMAL_PARAMETERS, ''' | 155 assertHasFix(DartFixKind.ADD_FIELD_FORMAL_PARAMETERS, ''' |
| 161 class Test { | 156 class Test { |
| 162 final int a; | 157 final int a; |
| 163 final int b; | 158 final int b; |
| 164 final int c; | 159 final int c; |
| 165 Test(this.a, this.b, [this.c]); | 160 Test(this.a, this.b, [this.c]); |
| 166 } | 161 } |
| 167 '''); | 162 '''); |
| 168 } | 163 } |
| 169 | 164 |
| 165 void test_addSync_BAD_nullFunctionBody() { |
| 166 resolveTestUnit(''' |
| 167 var F = await; |
| 168 '''); |
| 169 assertNoFix(DartFixKind.ADD_ASYNC); |
| 170 } |
| 171 |
| 170 void test_addSync_blockFunctionBody() { | 172 void test_addSync_blockFunctionBody() { |
| 171 resolveTestUnit(''' | 173 resolveTestUnit(''' |
| 172 foo() {} | 174 foo() {} |
| 173 main() { | 175 main() { |
| 174 await foo(); | 176 await foo(); |
| 175 } | 177 } |
| 176 '''); | 178 '''); |
| 177 List<AnalysisError> errors = context.computeErrors(testSource); | 179 List<AnalysisError> errors = context.computeErrors(testSource); |
| 178 expect(errors, hasLength(2)); | 180 expect(errors, hasLength(2)); |
| 179 // ParserError: Expected to find ';' | 181 // ParserError: Expected to find ';' |
| 180 { | 182 { |
| 181 AnalysisError error = errors[0]; | 183 AnalysisError error = errors[0]; |
| 182 expect(error.message, "Expected to find ';'"); | 184 expect(error.message, "Expected to find ';'"); |
| 183 List<Fix> fixes = computeFixes(plugin, context, error); | 185 List<Fix> fixes = _computeFixes(error); |
| 184 expect(fixes, isEmpty); | 186 expect(fixes, isEmpty); |
| 185 } | 187 } |
| 186 // Undefined name 'await' | 188 // Undefined name 'await' |
| 187 { | 189 { |
| 188 AnalysisError error = errors[1]; | 190 AnalysisError error = errors[1]; |
| 189 expect(error.message, "Undefined name 'await'"); | 191 expect(error.message, "Undefined name 'await'"); |
| 190 List<Fix> fixes = computeFixes(plugin, context, error); | 192 List<Fix> fixes = _computeFixes(error); |
| 191 // has exactly one fix | 193 // has exactly one fix |
| 192 expect(fixes, hasLength(1)); | 194 expect(fixes, hasLength(1)); |
| 193 Fix fix = fixes[0]; | 195 Fix fix = fixes[0]; |
| 194 expect(fix.kind, DartFixKind.ADD_ASYNC); | 196 expect(fix.kind, DartFixKind.ADD_ASYNC); |
| 195 // apply to "file" | 197 // apply to "file" |
| 196 List<SourceFileEdit> fileEdits = fix.change.edits; | 198 List<SourceFileEdit> fileEdits = fix.change.edits; |
| 197 expect(fileEdits, hasLength(1)); | 199 expect(fileEdits, hasLength(1)); |
| 198 resultCode = SourceEdit.applySequence(testCode, fileEdits[0].edits); | 200 resultCode = SourceEdit.applySequence(testCode, fileEdits[0].edits); |
| 199 // verify | 201 // verify |
| 200 expect(resultCode, ''' | 202 expect(resultCode, ''' |
| (...skipping 2218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2419 '''); | 2421 '''); |
| 2420 } | 2422 } |
| 2421 | 2423 |
| 2422 void test_noException_1() { | 2424 void test_noException_1() { |
| 2423 resolveTestUnit(''' | 2425 resolveTestUnit(''' |
| 2424 main(p) { | 2426 main(p) { |
| 2425 p i s Null; | 2427 p i s Null; |
| 2426 }'''); | 2428 }'''); |
| 2427 List<AnalysisError> errors = context.computeErrors(testSource); | 2429 List<AnalysisError> errors = context.computeErrors(testSource); |
| 2428 for (var error in errors) { | 2430 for (var error in errors) { |
| 2429 computeFixes(plugin, context, error); | 2431 _computeFixes(error); |
| 2430 } | 2432 } |
| 2431 } | 2433 } |
| 2432 | 2434 |
| 2433 void test_removeParentheses_inGetterDeclaration() { | 2435 void test_removeParentheses_inGetterDeclaration() { |
| 2434 resolveTestUnit(''' | 2436 resolveTestUnit(''' |
| 2435 class A { | 2437 class A { |
| 2436 int get foo() => 0; | 2438 int get foo() => 0; |
| 2437 } | 2439 } |
| 2438 '''); | 2440 '''); |
| 2439 assertHasFix(DartFixKind.REMOVE_PARAMETERS_IN_GETTER_DECLARATION, ''' | 2441 assertHasFix(DartFixKind.REMOVE_PARAMETERS_IN_GETTER_DECLARATION, ''' |
| (...skipping 1037 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3477 var b = 2; | 3479 var b = 2; |
| 3478 print(a ~/ b); | 3480 print(a ~/ b); |
| 3479 } | 3481 } |
| 3480 '''); | 3482 '''); |
| 3481 } | 3483 } |
| 3482 | 3484 |
| 3483 /** | 3485 /** |
| 3484 * Computes fixes and verifies that there is a fix of the given kind. | 3486 * Computes fixes and verifies that there is a fix of the given kind. |
| 3485 */ | 3487 */ |
| 3486 Fix _assertHasFix(FixKind kind, AnalysisError error) { | 3488 Fix _assertHasFix(FixKind kind, AnalysisError error) { |
| 3487 List<Fix> fixes = computeFixes(plugin, context, error); | 3489 List<Fix> fixes = _computeFixes(error); |
| 3488 for (Fix fix in fixes) { | 3490 for (Fix fix in fixes) { |
| 3489 if (fix.kind == kind) { | 3491 if (fix.kind == kind) { |
| 3490 return fix; | 3492 return fix; |
| 3491 } | 3493 } |
| 3492 } | 3494 } |
| 3493 throw fail('Expected to find fix $kind in\n${fixes.join('\n')}'); | 3495 throw fail('Expected to find fix $kind in\n${fixes.join('\n')}'); |
| 3494 } | 3496 } |
| 3495 | 3497 |
| 3496 void _assertLinkedGroup(LinkedEditGroup group, List<String> expectedStrings, | 3498 void _assertLinkedGroup(LinkedEditGroup group, List<String> expectedStrings, |
| 3497 [List<LinkedEditSuggestion> expectedSuggestions]) { | 3499 [List<LinkedEditSuggestion> expectedSuggestions]) { |
| 3498 List<Position> expectedPositions = _findResultPositions(expectedStrings); | 3500 List<Position> expectedPositions = _findResultPositions(expectedStrings); |
| 3499 expect(group.positions, unorderedEquals(expectedPositions)); | 3501 expect(group.positions, unorderedEquals(expectedPositions)); |
| 3500 if (expectedSuggestions != null) { | 3502 if (expectedSuggestions != null) { |
| 3501 expect(group.suggestions, unorderedEquals(expectedSuggestions)); | 3503 expect(group.suggestions, unorderedEquals(expectedSuggestions)); |
| 3502 } | 3504 } |
| 3503 } | 3505 } |
| 3504 | 3506 |
| 3505 /** | 3507 /** |
| 3508 * Computes fixes for the given [error] in [testUnit]. |
| 3509 */ |
| 3510 List<Fix> _computeFixes(AnalysisError error) { |
| 3511 FixProcessor processor = new FixProcessor(testUnit, error); |
| 3512 return processor.compute(); |
| 3513 } |
| 3514 |
| 3515 /** |
| 3506 * Configures the [SourceFactory] to have the `my_pkg` package in | 3516 * Configures the [SourceFactory] to have the `my_pkg` package in |
| 3507 * `/packages/my_pkg/lib` folder. | 3517 * `/packages/my_pkg/lib` folder. |
| 3508 */ | 3518 */ |
| 3509 void _configureMyPkg(String myLibCode) { | 3519 void _configureMyPkg(String myLibCode) { |
| 3510 provider.newFile('/packages/my_pkg/lib/my_lib.dart', myLibCode); | 3520 provider.newFile('/packages/my_pkg/lib/my_lib.dart', myLibCode); |
| 3511 // configure SourceFactory | 3521 // configure SourceFactory |
| 3512 Folder myPkgFolder = provider.getResource('/packages/my_pkg/lib'); | 3522 Folder myPkgFolder = provider.getResource('/packages/my_pkg/lib'); |
| 3513 UriResolver pkgResolver = | 3523 UriResolver pkgResolver = |
| 3514 new PackageMapUriResolver(provider, {'my_pkg': [myPkgFolder]}); | 3524 new PackageMapUriResolver(provider, {'my_pkg': [myPkgFolder]}); |
| 3515 context.sourceFactory = new SourceFactory( | 3525 context.sourceFactory = new SourceFactory( |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3529 | 3539 |
| 3530 List<Position> _findResultPositions(List<String> searchStrings) { | 3540 List<Position> _findResultPositions(List<String> searchStrings) { |
| 3531 List<Position> positions = <Position>[]; | 3541 List<Position> positions = <Position>[]; |
| 3532 for (String search in searchStrings) { | 3542 for (String search in searchStrings) { |
| 3533 int offset = resultCode.indexOf(search); | 3543 int offset = resultCode.indexOf(search); |
| 3534 positions.add(new Position(testFile, offset)); | 3544 positions.add(new Position(testFile, offset)); |
| 3535 } | 3545 } |
| 3536 return positions; | 3546 return positions; |
| 3537 } | 3547 } |
| 3538 } | 3548 } |
| OLD | NEW |