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 'dart:async'; | 7 import 'dart:async'; |
8 | 8 |
9 import 'package:analysis_server/plugin/edit/fix/fix_core.dart'; | 9 import 'package:analysis_server/plugin/edit/fix/fix_core.dart'; |
10 import 'package:analysis_server/plugin/edit/fix/fix_dart.dart'; | 10 import 'package:analysis_server/plugin/edit/fix/fix_dart.dart'; |
11 import 'package:analysis_server/plugin/protocol/protocol.dart' | 11 import 'package:analysis_server/plugin/protocol/protocol.dart' |
12 hide AnalysisError; | 12 hide AnalysisError; |
13 import 'package:analysis_server/src/services/correction/fix.dart'; | 13 import 'package:analysis_server/src/services/correction/fix.dart'; |
14 import 'package:analysis_server/src/services/correction/fix_internal.dart'; | 14 import 'package:analysis_server/src/services/correction/fix_internal.dart'; |
15 import 'package:analyzer/file_system/file_system.dart'; | 15 import 'package:analyzer/file_system/file_system.dart'; |
16 import 'package:analyzer/source/package_map_resolver.dart'; | 16 import 'package:analyzer/source/package_map_resolver.dart'; |
17 import 'package:analyzer/src/generated/error.dart'; | 17 import 'package:analyzer/src/generated/error.dart'; |
18 import 'package:analyzer/src/generated/parser.dart'; | 18 import 'package:analyzer/src/generated/parser.dart'; |
19 import 'package:analyzer/src/generated/source.dart'; | 19 import 'package:analyzer/src/generated/source.dart'; |
20 import 'package:test_reflective_loader/test_reflective_loader.dart'; | 20 import 'package:test_reflective_loader/test_reflective_loader.dart'; |
21 import 'package:unittest/unittest.dart'; | 21 import 'package:unittest/unittest.dart'; |
22 | 22 |
23 import '../../abstract_context.dart'; | 23 import '../../abstract_context.dart'; |
24 import '../../abstract_single_unit.dart'; | 24 import '../../abstract_single_unit.dart'; |
25 import '../../utils.dart'; | 25 import '../../utils.dart'; |
26 | 26 |
27 main() { | 27 main() { |
28 initializeTestEnvironment(); | 28 initializeTestEnvironment(); |
29 defineReflectiveTests(FixProcessorTest); | 29 defineReflectiveTests(FixProcessorTest); |
| 30 defineReflectiveTests(LintFixTest); |
30 } | 31 } |
31 | 32 |
32 typedef bool AnalysisErrorFilter(AnalysisError error); | 33 typedef bool AnalysisErrorFilter(AnalysisError error); |
33 | 34 |
34 @reflectiveTest | 35 /** |
35 class FixProcessorTest extends AbstractSingleUnitTest { | 36 * Base class for fix processor tests. |
| 37 */ |
| 38 class BaseFixProcessorTest extends AbstractSingleUnitTest { |
36 AnalysisErrorFilter errorFilter = (AnalysisError error) { | 39 AnalysisErrorFilter errorFilter = (AnalysisError error) { |
37 return error.errorCode != HintCode.UNUSED_CATCH_CLAUSE && | 40 return error.errorCode != HintCode.UNUSED_CATCH_CLAUSE && |
38 error.errorCode != HintCode.UNUSED_CATCH_STACK && | 41 error.errorCode != HintCode.UNUSED_CATCH_STACK && |
39 error.errorCode != HintCode.UNUSED_ELEMENT && | 42 error.errorCode != HintCode.UNUSED_ELEMENT && |
40 error.errorCode != HintCode.UNUSED_FIELD && | 43 error.errorCode != HintCode.UNUSED_FIELD && |
41 error.errorCode != HintCode.UNUSED_LOCAL_VARIABLE; | 44 error.errorCode != HintCode.UNUSED_LOCAL_VARIABLE; |
42 }; | 45 }; |
43 | 46 |
44 Fix fix; | 47 Fix fix; |
45 SourceChange change; | 48 SourceChange change; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
105 return values.map((value) { | 108 return values.map((value) { |
106 return new LinkedEditSuggestion(value, kind); | 109 return new LinkedEditSuggestion(value, kind); |
107 }).toList(); | 110 }).toList(); |
108 } | 111 } |
109 | 112 |
110 void setUp() { | 113 void setUp() { |
111 super.setUp(); | 114 super.setUp(); |
112 verifyNoTestUnitErrors = false; | 115 verifyNoTestUnitErrors = false; |
113 } | 116 } |
114 | 117 |
| 118 /** |
| 119 * Computes fixes and verifies that there is a fix of the given kind. |
| 120 */ |
| 121 Future<Fix> _assertHasFix(FixKind kind, AnalysisError error) async { |
| 122 List<Fix> fixes = await _computeFixes(error); |
| 123 for (Fix fix in fixes) { |
| 124 if (fix.kind == kind) { |
| 125 return fix; |
| 126 } |
| 127 } |
| 128 throw fail('Expected to find fix $kind in\n${fixes.join('\n')}'); |
| 129 } |
| 130 |
| 131 void _assertLinkedGroup(LinkedEditGroup group, List<String> expectedStrings, |
| 132 [List<LinkedEditSuggestion> expectedSuggestions]) { |
| 133 List<Position> expectedPositions = _findResultPositions(expectedStrings); |
| 134 expect(group.positions, unorderedEquals(expectedPositions)); |
| 135 if (expectedSuggestions != null) { |
| 136 expect(group.suggestions, unorderedEquals(expectedSuggestions)); |
| 137 } |
| 138 } |
| 139 |
| 140 /** |
| 141 * Computes fixes for the given [error] in [testUnit]. |
| 142 */ |
| 143 Future<List<Fix>> _computeFixes(AnalysisError error) async { |
| 144 DartFixContext dartContext = new DartFixContextImpl( |
| 145 new FixContextImpl(provider, context, error), testUnit); |
| 146 FixProcessor processor = new FixProcessor(dartContext); |
| 147 return processor.compute(); |
| 148 } |
| 149 |
| 150 /** |
| 151 * Configures the [SourceFactory] to have the `my_pkg` package in |
| 152 * `/packages/my_pkg/lib` folder. |
| 153 */ |
| 154 void _configureMyPkg(String myLibCode) { |
| 155 provider.newFile('/packages/my_pkg/lib/my_lib.dart', myLibCode); |
| 156 // configure SourceFactory |
| 157 Folder myPkgFolder = provider.getResource('/packages/my_pkg/lib'); |
| 158 UriResolver pkgResolver = new PackageMapUriResolver(provider, { |
| 159 'my_pkg': [myPkgFolder] |
| 160 }); |
| 161 context.sourceFactory = new SourceFactory( |
| 162 [AbstractContextTest.SDK_RESOLVER, pkgResolver, resourceResolver]); |
| 163 // force 'my_pkg' resolution |
| 164 addSource('/tmp/other.dart', "import 'package:my_pkg/my_lib.dart';"); |
| 165 } |
| 166 |
| 167 AnalysisError _findErrorToFix() { |
| 168 List<AnalysisError> errors = context.computeErrors(testSource); |
| 169 if (errorFilter != null) { |
| 170 errors = errors.where(errorFilter).toList(); |
| 171 } |
| 172 expect(errors, hasLength(1)); |
| 173 return errors[0]; |
| 174 } |
| 175 |
| 176 List<Position> _findResultPositions(List<String> searchStrings) { |
| 177 List<Position> positions = <Position>[]; |
| 178 for (String search in searchStrings) { |
| 179 int offset = resultCode.indexOf(search); |
| 180 positions.add(new Position(testFile, offset)); |
| 181 } |
| 182 return positions; |
| 183 } |
| 184 |
| 185 void _performAnalysis() { |
| 186 while (context.performAnalysisTask().hasMoreWork); |
| 187 } |
| 188 } |
| 189 |
| 190 @reflectiveTest |
| 191 class FixProcessorTest extends BaseFixProcessorTest { |
115 test_addFieldFormalParameters_hasRequiredParameter() async { | 192 test_addFieldFormalParameters_hasRequiredParameter() async { |
116 resolveTestUnit(''' | 193 resolveTestUnit(''' |
117 class Test { | 194 class Test { |
118 final int a; | 195 final int a; |
119 final int b; | 196 final int b; |
120 final int c; | 197 final int c; |
121 Test(this.a); | 198 Test(this.a); |
122 } | 199 } |
123 '''); | 200 '''); |
124 await assertHasFix( | 201 await assertHasFix( |
(...skipping 4814 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4939 await assertHasFix( | 5016 await assertHasFix( |
4940 DartFixKind.IMPORT_LIBRARY_PREFIX, | 5017 DartFixKind.IMPORT_LIBRARY_PREFIX, |
4941 ''' | 5018 ''' |
4942 import 'dart:math' as pref; | 5019 import 'dart:math' as pref; |
4943 main() { | 5020 main() { |
4944 print(pref.E); | 5021 print(pref.E); |
4945 print(pref.PI); | 5022 print(pref.PI); |
4946 } | 5023 } |
4947 '''); | 5024 '''); |
4948 } | 5025 } |
| 5026 } |
| 5027 |
| 5028 @reflectiveTest |
| 5029 class LintFixTest extends BaseFixProcessorTest { |
| 5030 AnalysisError error; |
| 5031 |
| 5032 Future applyFix(FixKind kind) async { |
| 5033 fix = await _assertHasFix(kind, error); |
| 5034 change = fix.change; |
| 5035 // apply to "file" |
| 5036 List<SourceFileEdit> fileEdits = change.edits; |
| 5037 expect(fileEdits, hasLength(1)); |
| 5038 resultCode = SourceEdit.applySequence(testCode, change.edits[0].edits); |
| 5039 } |
| 5040 |
| 5041 void findLint(String src, String lintCode) { |
| 5042 int errorOffset = src.indexOf('/*LINT*/'); |
| 5043 resolveTestUnit(src.replaceAll('/*LINT*/', '')); |
| 5044 error = new AnalysisError(testUnit.element.source, errorOffset, 1, |
| 5045 new LintCode(lintCode, '<ignored>')); |
| 5046 } |
| 5047 |
| 5048 test_lint_addMissingOverride_field() async { |
| 5049 String src = ''' |
| 5050 class abstract Test { |
| 5051 int get t; |
| 5052 } |
| 5053 class Sub extends Test { |
| 5054 int /*LINT*/t = 42; |
| 5055 } |
| 5056 '''; |
| 5057 findLint(src, LintNames.annotate_overrides); |
| 5058 |
| 5059 await applyFix(DartFixKind.LINT_ADD_OVERRIDE); |
| 5060 |
| 5061 verifyResult(''' |
| 5062 class abstract Test { |
| 5063 int get t; |
| 5064 } |
| 5065 class Sub extends Test { |
| 5066 @override |
| 5067 int t = 42; |
| 5068 } |
| 5069 '''); |
| 5070 } |
4949 | 5071 |
4950 /** | 5072 test_lint_addMissingOverride_getter() async { |
4951 * Computes fixes and verifies that there is a fix of the given kind. | 5073 String src = ''' |
4952 */ | 5074 class Test { |
4953 Future<Fix> _assertHasFix(FixKind kind, AnalysisError error) async { | 5075 int get t => null; |
4954 List<Fix> fixes = await _computeFixes(error); | 5076 } |
4955 for (Fix fix in fixes) { | 5077 class Sub extends Test { |
4956 if (fix.kind == kind) { | 5078 int get /*LINT*/t => null; |
4957 return fix; | 5079 } |
4958 } | 5080 '''; |
4959 } | 5081 findLint(src, LintNames.annotate_overrides); |
4960 throw fail('Expected to find fix $kind in\n${fixes.join('\n')}'); | 5082 |
| 5083 await applyFix(DartFixKind.LINT_ADD_OVERRIDE); |
| 5084 |
| 5085 verifyResult(''' |
| 5086 class Test { |
| 5087 int get t => null; |
| 5088 } |
| 5089 class Sub extends Test { |
| 5090 @override |
| 5091 int get t => null; |
| 5092 } |
| 5093 '''); |
4961 } | 5094 } |
4962 | 5095 |
4963 void _assertLinkedGroup(LinkedEditGroup group, List<String> expectedStrings, | 5096 test_lint_addMissingOverride_method() async { |
4964 [List<LinkedEditSuggestion> expectedSuggestions]) { | 5097 String src = ''' |
4965 List<Position> expectedPositions = _findResultPositions(expectedStrings); | 5098 class Test { |
4966 expect(group.positions, unorderedEquals(expectedPositions)); | 5099 void t() { } |
4967 if (expectedSuggestions != null) { | 5100 } |
4968 expect(group.suggestions, unorderedEquals(expectedSuggestions)); | 5101 class Sub extends Test { |
4969 } | 5102 void /*LINT*/t() { } |
| 5103 } |
| 5104 '''; |
| 5105 findLint(src, LintNames.annotate_overrides); |
| 5106 |
| 5107 await applyFix(DartFixKind.LINT_ADD_OVERRIDE); |
| 5108 |
| 5109 verifyResult(''' |
| 5110 class Test { |
| 5111 void t() { } |
| 5112 } |
| 5113 class Sub extends Test { |
| 5114 @override |
| 5115 void t() { } |
| 5116 } |
| 5117 '''); |
4970 } | 5118 } |
4971 | 5119 |
4972 /** | 5120 void verifyResult(String expectedResult) { |
4973 * Computes fixes for the given [error] in [testUnit]. | 5121 expect(resultCode, expectedResult); |
4974 */ | |
4975 Future<List<Fix>> _computeFixes(AnalysisError error) async { | |
4976 DartFixContext dartContext = new DartFixContextImpl( | |
4977 new FixContextImpl(provider, context, error), testUnit); | |
4978 FixProcessor processor = new FixProcessor(dartContext); | |
4979 return processor.compute(); | |
4980 } | |
4981 | |
4982 /** | |
4983 * Configures the [SourceFactory] to have the `my_pkg` package in | |
4984 * `/packages/my_pkg/lib` folder. | |
4985 */ | |
4986 void _configureMyPkg(String myLibCode) { | |
4987 provider.newFile('/packages/my_pkg/lib/my_lib.dart', myLibCode); | |
4988 // configure SourceFactory | |
4989 Folder myPkgFolder = provider.getResource('/packages/my_pkg/lib'); | |
4990 UriResolver pkgResolver = new PackageMapUriResolver(provider, { | |
4991 'my_pkg': [myPkgFolder] | |
4992 }); | |
4993 context.sourceFactory = new SourceFactory( | |
4994 [AbstractContextTest.SDK_RESOLVER, pkgResolver, resourceResolver]); | |
4995 // force 'my_pkg' resolution | |
4996 addSource('/tmp/other.dart', "import 'package:my_pkg/my_lib.dart';"); | |
4997 } | |
4998 | |
4999 AnalysisError _findErrorToFix() { | |
5000 List<AnalysisError> errors = context.computeErrors(testSource); | |
5001 if (errorFilter != null) { | |
5002 errors = errors.where(errorFilter).toList(); | |
5003 } | |
5004 expect(errors, hasLength(1)); | |
5005 return errors[0]; | |
5006 } | |
5007 | |
5008 List<Position> _findResultPositions(List<String> searchStrings) { | |
5009 List<Position> positions = <Position>[]; | |
5010 for (String search in searchStrings) { | |
5011 int offset = resultCode.indexOf(search); | |
5012 positions.add(new Position(testFile, offset)); | |
5013 } | |
5014 return positions; | |
5015 } | |
5016 | |
5017 void _performAnalysis() { | |
5018 while (context.performAnalysisTask().hasMoreWork); | |
5019 } | 5122 } |
5020 } | 5123 } |
OLD | NEW |