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 // This code was auto-generated, is not intended to be edited, and is subject to | 5 // This code was auto-generated, is not intended to be edited, and is subject to |
6 // significant change. Please see the README file for more information. | 6 // significant change. Please see the README file for more information. |
7 | 7 |
8 library services.src.correction.fix; | 8 library services.src.correction.fix; |
9 | 9 |
10 import 'package:analysis_services/correction/change.dart'; | 10 import 'package:analysis_services/correction/change.dart'; |
11 import 'package:analysis_services/correction/fix.dart'; | 11 import 'package:analysis_services/correction/fix.dart'; |
12 import 'package:analysis_services/search/search_engine.dart'; | 12 import 'package:analysis_services/search/search_engine.dart'; |
13 import 'package:analysis_services/src/correction/name_suggestion.dart'; | 13 import 'package:analysis_services/src/correction/name_suggestion.dart'; |
14 import 'package:analysis_services/src/correction/source_buffer.dart'; | 14 import 'package:analysis_services/src/correction/source_buffer.dart'; |
15 import 'package:analysis_services/src/correction/source_range.dart' as rf; | 15 import 'package:analysis_services/src/correction/source_range.dart' as rf; |
| 16 import 'package:analysis_services/src/correction/strings.dart'; |
16 import 'package:analysis_services/src/correction/util.dart'; | 17 import 'package:analysis_services/src/correction/util.dart'; |
17 import 'package:analyzer/src/generated/ast.dart'; | 18 import 'package:analyzer/src/generated/ast.dart'; |
18 import 'package:analyzer/src/generated/element.dart'; | 19 import 'package:analyzer/src/generated/element.dart'; |
19 import 'package:analyzer/src/generated/error.dart'; | 20 import 'package:analyzer/src/generated/error.dart'; |
20 import 'package:analyzer/src/generated/java_core.dart'; | 21 import 'package:analyzer/src/generated/java_core.dart'; |
21 import 'package:analyzer/src/generated/parser.dart'; | 22 import 'package:analyzer/src/generated/parser.dart'; |
| 23 import 'package:analyzer/src/generated/scanner.dart'; |
22 import 'package:analyzer/src/generated/source.dart'; | 24 import 'package:analyzer/src/generated/source.dart'; |
23 import 'package:analyzer/src/generated/utilities_dart.dart'; | 25 import 'package:analyzer/src/generated/utilities_dart.dart'; |
24 | 26 |
25 | 27 |
26 /** | 28 /** |
27 * The computer for Dart fixes. | 29 * The computer for Dart fixes. |
28 */ | 30 */ |
29 class FixProcessor { | 31 class FixProcessor { |
30 final SearchEngine searchEngine; | 32 final SearchEngine searchEngine; |
| 33 final Source source; |
31 final String file; | 34 final String file; |
32 final CompilationUnit unit; | 35 final CompilationUnit unit; |
33 final AnalysisError error; | 36 final AnalysisError error; |
| 37 CompilationUnitElement unitElement; |
| 38 LibraryElement unitLibraryElement; |
34 | 39 |
35 final List<Edit> edits = <Edit>[]; | 40 final List<Edit> edits = <Edit>[]; |
36 final Map<String, LinkedPositionGroup> linkedPositionGroups = <String, | 41 final Map<String, LinkedPositionGroup> linkedPositionGroups = <String, |
37 LinkedPositionGroup>{}; | 42 LinkedPositionGroup>{}; |
| 43 Position endPosition = null; |
38 final List<Fix> fixes = <Fix>[]; | 44 final List<Fix> fixes = <Fix>[]; |
39 | 45 |
40 CorrectionUtils utils; | 46 CorrectionUtils utils; |
41 int errorOffset; | 47 int errorOffset; |
42 int errorLength; | 48 int errorLength; |
43 int errorEnd; | 49 int errorEnd; |
44 AstNode node; | 50 AstNode node; |
45 AstNode coveredNode; | 51 AstNode coveredNode; |
46 | 52 |
47 | 53 |
48 FixProcessor(this.searchEngine, this.file, this.unit, this.error); | 54 FixProcessor(this.searchEngine, this.source, this.file, this.unit, this.error) |
| 55 { |
| 56 unitElement = unit.element; |
| 57 unitLibraryElement = unitElement.library; |
| 58 } |
| 59 |
| 60 DartType get coreTypeBool => _getCoreType("bool"); |
| 61 |
| 62 /** |
| 63 * Returns the EOL to use for this [CompilationUnit]. |
| 64 */ |
| 65 String get eol => utils.endOfLine; |
49 | 66 |
50 List<Fix> compute() { | 67 List<Fix> compute() { |
51 utils = new CorrectionUtils(unit); | 68 utils = new CorrectionUtils(unit); |
52 errorOffset = error.offset; | 69 errorOffset = error.offset; |
53 errorLength = error.length; | 70 errorLength = error.length; |
54 errorEnd = errorOffset + errorLength; | 71 errorEnd = errorOffset + errorLength; |
55 node = new NodeLocator.con1(errorOffset).searchWithin(unit); | 72 node = new NodeLocator.con1(errorOffset).searchWithin(unit); |
56 coveredNode = new NodeLocator.con2( | 73 coveredNode = new NodeLocator.con2( |
57 errorOffset, | 74 errorOffset, |
58 errorOffset + errorLength).searchWithin(unit); | 75 errorOffset + errorLength).searchWithin(unit); |
59 // analyze ErrorCode | 76 // analyze ErrorCode |
60 ErrorCode errorCode = error.errorCode; | 77 ErrorCode errorCode = error.errorCode; |
61 if (errorCode == StaticWarningCode.UNDEFINED_CLASS_BOOLEAN) { | 78 if (errorCode == StaticWarningCode.UNDEFINED_CLASS_BOOLEAN) { |
62 _addFix_boolInsteadOfBoolean(); | 79 _addFix_boolInsteadOfBoolean(); |
63 } | 80 } |
64 if (errorCode == | 81 if (errorCode == |
65 CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE) { | 82 CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE) { |
66 _addFix_replaceWithConstInstanceCreation(); | 83 _addFix_replaceWithConstInstanceCreation(); |
67 } | 84 } |
68 if (errorCode == | 85 if (errorCode == |
69 CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT) { | 86 CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT) { |
70 _addFix_createConstructorSuperExplicit(); | 87 _addFix_createConstructorSuperExplicit(); |
71 } | 88 } |
72 // if (identical( | 89 if (errorCode == |
73 // errorCode, | 90 CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT) { |
74 // CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT)) { | 91 _addFix_createConstructorSuperImplicit(); |
75 // _addFix_createConstructorSuperImplicit(); | 92 } |
76 // } | |
77 if (errorCode == | 93 if (errorCode == |
78 CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT) { | 94 CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT) { |
79 _addFix_createConstructorSuperExplicit(); | 95 _addFix_createConstructorSuperExplicit(); |
80 } | 96 } |
81 // if (identical(errorCode, CompileTimeErrorCode.URI_DOES_NOT_EXIST)) { | 97 // if (identical(errorCode, CompileTimeErrorCode.URI_DOES_NOT_EXIST)) { |
82 // _addFix_createPart(); | 98 // _addFix_createPart(); |
83 // _addFix_addPackageDependency(); | 99 // _addFix_addPackageDependency(); |
84 // } | 100 // } |
85 if (errorCode == HintCode.DIVISION_OPTIMIZATION) { | 101 if (errorCode == HintCode.DIVISION_OPTIMIZATION) { |
86 _addFix_useEffectiveIntegerDivision(); | 102 _addFix_useEffectiveIntegerDivision(); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 List<ExecutableElement> missingOverrides = | 148 List<ExecutableElement> missingOverrides = |
133 property as List<ExecutableElement>; | 149 property as List<ExecutableElement>; |
134 _addFix_createMissingOverrides(missingOverrides); | 150 _addFix_createMissingOverrides(missingOverrides); |
135 _addFix_createNoSuchMethod(); | 151 _addFix_createNoSuchMethod(); |
136 } | 152 } |
137 if (errorCode == StaticWarningCode.UNDEFINED_CLASS) { | 153 if (errorCode == StaticWarningCode.UNDEFINED_CLASS) { |
138 _addFix_importLibrary_withType(); | 154 _addFix_importLibrary_withType(); |
139 _addFix_createClass(); | 155 _addFix_createClass(); |
140 _addFix_undefinedClass_useSimilar(); | 156 _addFix_undefinedClass_useSimilar(); |
141 } | 157 } |
142 // if (identical(errorCode, StaticWarningCode.UNDEFINED_IDENTIFIER)) { | 158 if (errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER) { |
143 // _addFix_createFunction_forFunctionType(); | 159 _addFix_createFunction_forFunctionType(); |
144 // _addFix_importLibrary_withType(); | 160 _addFix_importLibrary_withType(); |
145 // _addFix_importLibrary_withTopLevelVariable(); | 161 _addFix_importLibrary_withTopLevelVariable(); |
146 // } | 162 } |
147 if (errorCode == StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER) { | 163 if (errorCode == StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER) { |
148 _addFix_useStaticAccess_method(); | 164 _addFix_useStaticAccess_method(); |
149 _addFix_useStaticAccess_property(); | 165 _addFix_useStaticAccess_property(); |
150 } | 166 } |
151 if (errorCode == StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION) { | 167 if (errorCode == StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION) { |
152 _addFix_removeParentheses_inGetterInvocation(); | 168 _addFix_removeParentheses_inGetterInvocation(); |
153 } | 169 } |
154 // if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_FUNCTION)) { | 170 // if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_FUNCTION)) { |
155 // _addFix_importLibrary_withFunction(); | 171 // _addFix_importLibrary_withFunction(); |
156 // _addFix_undefinedFunction_useSimilar(); | 172 // _addFix_undefinedFunction_useSimilar(); |
157 // _addFix_undefinedFunction_create(); | 173 // _addFix_undefinedFunction_create(); |
158 // } | 174 // } |
159 // if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_GETTER)) { | 175 if (errorCode == StaticTypeWarningCode.UNDEFINED_GETTER) { |
160 // _addFix_createFunction_forFunctionType(); | 176 _addFix_createFunction_forFunctionType(); |
161 // } | 177 } |
162 // if (identical(errorCode, HintCode.UNDEFINED_METHOD) || | 178 if (errorCode == HintCode.UNDEFINED_METHOD || |
163 // identical(errorCode, StaticTypeWarningCode.UNDEFINED_METHOD)) { | 179 errorCode == StaticTypeWarningCode.UNDEFINED_METHOD) { |
164 // _addFix_undefinedMethod_useSimilar(); | 180 _addFix_undefinedMethod_useSimilar(); |
165 // _addFix_undefinedMethod_create(); | 181 _addFix_undefinedMethod_create(); |
166 // _addFix_undefinedFunction_create(); | 182 _addFix_undefinedFunction_create(); |
167 // } | 183 } |
168 // done | 184 // done |
169 return fixes; | 185 return fixes; |
170 } | 186 } |
171 | 187 |
172 void _addFix(FixKind kind, List args, {String fixFile}) { | 188 void _addFix(FixKind kind, List args, {String fixFile}) { |
173 if (fixFile == null) { | 189 if (fixFile == null) { |
174 fixFile = file; | 190 fixFile = file; |
175 } | 191 } |
176 FileEdit fileEdit = new FileEdit(file); | 192 FileEdit fileEdit = new FileEdit(file); |
177 edits.forEach((edit) => fileEdit.add(edit)); | 193 edits.forEach((edit) => fileEdit.add(edit)); |
178 // prepare Change | 194 // prepare Change |
179 String message = JavaString.format(kind.message, args); | 195 String message = JavaString.format(kind.message, args); |
180 Change change = new Change(message); | 196 Change change = new Change(message); |
181 change.add(fileEdit); | 197 change.add(fileEdit); |
182 linkedPositionGroups.values.forEach( | 198 linkedPositionGroups.values.forEach( |
183 (group) => change.addLinkedPositionGroup(group)); | 199 (group) => change.addLinkedPositionGroup(group)); |
| 200 change.endPosition = endPosition; |
184 // add Fix | 201 // add Fix |
185 Fix fix = new Fix(kind, change); | 202 Fix fix = new Fix(kind, change); |
186 fixes.add(fix); | 203 fixes.add(fix); |
| 204 // clear |
| 205 edits.clear(); |
| 206 linkedPositionGroups.clear(); |
| 207 endPosition = null; |
187 } | 208 } |
188 | 209 |
| 210 |
189 void _addFix_addPackageDependency() { | 211 void _addFix_addPackageDependency() { |
190 // TODO(scheglov) implement | 212 // TODO(scheglov) implement |
191 // if (node is SimpleStringLiteral && node.parent is NamespaceDirective) { | 213 // if (node is SimpleStringLiteral && node.parent is NamespaceDirective) { |
192 // SimpleStringLiteral uriLiteral = node as SimpleStringLiteral; | 214 // SimpleStringLiteral uriLiteral = node as SimpleStringLiteral; |
193 // String uriString = uriLiteral.value; | 215 // String uriString = uriLiteral.value; |
194 // // we need package: import | 216 // // we need package: import |
195 // if (!uriString.startsWith("package:")) { | 217 // if (!uriString.startsWith("package:")) { |
196 // return; | 218 // return; |
197 // } | 219 // } |
198 // // prepare package name | 220 // // prepare package name |
199 // String packageName = StringUtils.removeStart(uriString, "package:"); | 221 // String packageName = StringUtils.removeStart(uriString, "package:"); |
200 // packageName = StringUtils.substringBefore(packageName, "/"); | 222 // packageName = StringUtils.substringBefore(packageName, "/"); |
201 // // add proposal | 223 // // add proposal |
202 // _proposals.add( | 224 // _proposals.add( |
203 // new AddDependencyCorrectionProposal( | 225 // new AddDependencyCorrectionProposal( |
204 // _unitFile, | 226 // _unitFile, |
205 // packageName, | 227 // packageName, |
206 // FixKind.ADD_PACKAGE_DEPENDENCY, | 228 // FixKind.ADD_PACKAGE_DEPENDENCY, |
207 // [packageName])); | 229 // [packageName])); |
208 // } | 230 // } |
209 } | 231 } |
210 | 232 |
| 233 |
211 void _addFix_boolInsteadOfBoolean() { | 234 void _addFix_boolInsteadOfBoolean() { |
212 SourceRange range = rf.rangeError(error); | 235 SourceRange range = rf.rangeError(error); |
213 _addReplaceEdit(range, "bool"); | 236 _addReplaceEdit(range, "bool"); |
214 _addFix(FixKind.REPLACE_BOOLEAN_WITH_BOOL, []); | 237 _addFix(FixKind.REPLACE_BOOLEAN_WITH_BOOL, []); |
215 } | 238 } |
216 | 239 |
217 | |
218 void _addFix_createClass() { | 240 void _addFix_createClass() { |
219 if (_mayBeTypeIdentifier(node)) { | 241 if (_mayBeTypeIdentifier(node)) { |
220 String name = (node as SimpleIdentifier).name; | 242 String name = (node as SimpleIdentifier).name; |
221 // prepare environment | 243 // prepare environment |
222 String eol = utils.endOfLine; | |
223 CompilationUnitMember enclosingMember = | 244 CompilationUnitMember enclosingMember = |
224 node.getAncestor((node) => node is CompilationUnitMember); | 245 node.getAncestor((node) => node is CompilationUnitMember); |
225 int offset = enclosingMember.end; | 246 int offset = enclosingMember.end; |
226 String prefix = ""; | 247 String prefix = ""; |
227 // prepare source | 248 // prepare source |
228 SourceBuilder sb = new SourceBuilder(file, offset); | 249 SourceBuilder sb = new SourceBuilder(file, offset); |
229 { | 250 { |
230 sb.append("${eol}${eol}"); | 251 sb.append("${eol}${eol}"); |
231 sb.append(prefix); | 252 sb.append(prefix); |
232 // "class" | 253 // "class" |
(...skipping 10 matching lines...) Expand all Loading... |
243 sb.append("}"); | 264 sb.append("}"); |
244 } | 265 } |
245 // insert source | 266 // insert source |
246 _insertBuilder(sb); | 267 _insertBuilder(sb); |
247 _addLinkedPosition("NAME", rf.rangeNode(node)); | 268 _addLinkedPosition("NAME", rf.rangeNode(node)); |
248 // add proposal | 269 // add proposal |
249 _addFix(FixKind.CREATE_CLASS, [name]); | 270 _addFix(FixKind.CREATE_CLASS, [name]); |
250 } | 271 } |
251 } | 272 } |
252 | 273 |
253 | |
254 void _addFix_createConstructorSuperExplicit() { | 274 void _addFix_createConstructorSuperExplicit() { |
255 ConstructorDeclaration targetConstructor = | 275 ConstructorDeclaration targetConstructor = |
256 node.parent as ConstructorDeclaration; | 276 node.parent as ConstructorDeclaration; |
257 ClassDeclaration targetClassNode = | 277 ClassDeclaration targetClassNode = |
258 targetConstructor.parent as ClassDeclaration; | 278 targetConstructor.parent as ClassDeclaration; |
259 ClassElement targetClassElement = targetClassNode.element; | 279 ClassElement targetClassElement = targetClassNode.element; |
260 ClassElement superClassElement = targetClassElement.supertype.element; | 280 ClassElement superClassElement = targetClassElement.supertype.element; |
261 // add proposals for all super constructors | 281 // add proposals for all super constructors |
262 List<ConstructorElement> superConstructors = superClassElement.constructors; | 282 List<ConstructorElement> superConstructors = superClassElement.constructors; |
263 for (ConstructorElement superConstructor in superConstructors) { | 283 for (ConstructorElement superConstructor in superConstructors) { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
312 sb.append(")"); | 332 sb.append(")"); |
313 // insert proposal | 333 // insert proposal |
314 _insertBuilder(sb); | 334 _insertBuilder(sb); |
315 // add proposal | 335 // add proposal |
316 String proposalName = _getConstructorProposalName(superConstructor); | 336 String proposalName = _getConstructorProposalName(superConstructor); |
317 _addFix(FixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION, [proposalName]); | 337 _addFix(FixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION, [proposalName]); |
318 } | 338 } |
319 } | 339 } |
320 | 340 |
321 void _addFix_createConstructorSuperImplicit() { | 341 void _addFix_createConstructorSuperImplicit() { |
322 // TODO(scheglov) implement | 342 ClassDeclaration targetClassNode = node.parent as ClassDeclaration; |
323 // ClassDeclaration targetClassNode = node.parent as ClassDeclaration; | 343 ClassElement targetClassElement = targetClassNode.element; |
324 // ClassElement targetClassElement = targetClassNode.element; | 344 ClassElement superClassElement = targetClassElement.supertype.element; |
325 // ClassElement superClassElement = targetClassElement.supertype.element; | 345 String targetClassName = targetClassElement.name; |
326 // String targetClassName = targetClassElement.name; | 346 // add proposals for all super constructors |
327 // // add proposals for all super constructors | 347 List<ConstructorElement> superConstructors = superClassElement.constructors; |
328 // List<ConstructorElement> superConstructors = superClassElement.constructor
s; | 348 for (ConstructorElement superConstructor in superConstructors) { |
329 // for (ConstructorElement superConstructor in superConstructors) { | 349 String constructorName = superConstructor.name; |
330 // String constructorName = superConstructor.name; | 350 // skip private |
331 // // skip private | 351 if (Identifier.isPrivateName(constructorName)) { |
332 // if (Identifier.isPrivateName(constructorName)) { | 352 continue; |
333 // continue; | 353 } |
334 // } | 354 // prepare parameters and arguments |
335 // // prepare parameters and arguments | 355 SourceBuilder parametersBuffer = new SourceBuilder.buffer(); |
336 // JavaStringBuilder parametersBuffer = new JavaStringBuilder(); | 356 SourceBuilder argumentsBuffer = new SourceBuilder.buffer(); |
337 // JavaStringBuilder argumentsBuffer = new JavaStringBuilder(); | 357 bool firstParameter = true; |
338 // bool firstParameter = true; | 358 for (ParameterElement parameter in superConstructor.parameters) { |
339 // for (ParameterElement parameter in superConstructor.parameters) { | 359 // skip non-required parameters |
340 // // skip non-required parameters | 360 if (parameter.parameterKind != ParameterKind.REQUIRED) { |
341 // if (parameter.parameterKind != ParameterKind.REQUIRED) { | 361 break; |
342 // break; | 362 } |
343 // } | 363 // comma |
344 // // comma | 364 if (firstParameter) { |
345 // if (firstParameter) { | 365 firstParameter = false; |
346 // firstParameter = false; | 366 } else { |
347 // } else { | 367 parametersBuffer.append(', '); |
348 // parametersBuffer.append(", "); | 368 argumentsBuffer.append(', '); |
349 // argumentsBuffer.append(", "); | 369 } |
350 // } | 370 // name |
351 // // name | 371 String parameterName = parameter.displayName; |
352 // String parameterName = parameter.displayName; | 372 if (parameterName.length > 1 && parameterName.startsWith('_')) { |
353 // if (parameterName.length > 1 && parameterName.startsWith("_")) { | 373 parameterName = parameterName.substring(1); |
354 // parameterName = parameterName.substring(1); | 374 } |
355 // } | 375 // parameter & argument |
356 // // parameter & argument | 376 _appendParameterSource(parametersBuffer, parameter.type, parameterName); |
357 // _appendParameterSource(parametersBuffer, parameter.type, parameterName
); | 377 argumentsBuffer.append(parameterName); |
358 // argumentsBuffer.append(parameterName); | 378 } |
359 // } | 379 // add proposal |
360 // // add proposal | 380 _ConstructorLocation targetLocation = |
361 // String eol = utils.endOfLine; | 381 _prepareNewConstructorLocation(targetClassNode); |
362 // QuickFixProcessorImpl_NewConstructorLocation targetLocation = | 382 SourceBuilder sb = new SourceBuilder(file, targetLocation._offset); |
363 // _prepareNewConstructorLocation(targetClassNode, eol); | 383 { |
364 // SourceBuilder sb = new SourceBuilder.con1(targetLocation._offset); | 384 String indent = utils.getIndent(1); |
365 // { | 385 sb.append(targetLocation._prefix); |
366 // String indent = utils.getIndent(1); | 386 sb.append(indent); |
367 // sb.append(targetLocation._prefix); | 387 sb.append(targetClassName); |
368 // sb.append(indent); | 388 if (!constructorName.isEmpty) { |
369 // sb.append(targetClassName); | 389 sb.startPosition('NAME'); |
370 // if (!constructorName.isEmpty) { | 390 sb.append('.'); |
371 // sb.startPosition("NAME"); | 391 sb.append(constructorName); |
372 // sb.append("."); | 392 sb.endPosition(); |
373 // sb.append(constructorName); | 393 } |
374 // sb.endPosition(); | 394 sb.append("("); |
375 // } | 395 sb.append(parametersBuffer.toString()); |
376 // sb.append("("); | 396 sb.append(') : super'); |
377 // sb.append(parametersBuffer.toString()); | 397 if (!constructorName.isEmpty) { |
378 // sb.append(") : super"); | 398 sb.append('.'); |
379 // if (!constructorName.isEmpty) { | 399 sb.append(constructorName); |
380 // sb.append("."); | 400 } |
381 // sb.append(constructorName); | 401 sb.append('('); |
382 // } | 402 sb.append(argumentsBuffer.toString()); |
383 // sb.append("("); | 403 sb.append(');'); |
384 // sb.append(argumentsBuffer.toString()); | 404 sb.append(targetLocation._suffix); |
385 // sb.append(");"); | 405 } |
386 // sb.append(targetLocation._suffix); | 406 _insertBuilder(sb); |
387 // } | 407 // add proposal |
388 // _addInsertEdit3(sb); | 408 String proposalName = _getConstructorProposalName(superConstructor); |
389 // // add proposal | 409 _addFix(FixKind.CREATE_CONSTRUCTOR_SUPER, [proposalName]); |
390 // String proposalName = _getConstructorProposalName(superConstructor); | 410 } |
391 // _addFix( | |
392 // FixKind.CREATE_CONSTRUCTOR_SUPER, | |
393 // [proposalName]); | |
394 // } | |
395 } | 411 } |
396 | 412 |
397 void _addFix_createConstructor_insteadOfSyntheticDefault() { | 413 void _addFix_createConstructor_insteadOfSyntheticDefault() { |
398 TypeName typeName = null; | 414 TypeName typeName = null; |
399 ConstructorName constructorName = null; | 415 ConstructorName constructorName = null; |
400 InstanceCreationExpression instanceCreation = null; | 416 InstanceCreationExpression instanceCreation = null; |
401 if (node is SimpleIdentifier) { | 417 if (node is SimpleIdentifier) { |
402 if (node.parent is TypeName) { | 418 if (node.parent is TypeName) { |
403 typeName = node.parent as TypeName; | 419 typeName = node.parent as TypeName; |
404 if (typeName.name == node && typeName.parent is ConstructorName) { | 420 if (typeName.name == node && typeName.parent is ConstructorName) { |
(...skipping 16 matching lines...) Expand all Loading... |
421 return; | 437 return; |
422 } | 438 } |
423 } | 439 } |
424 } | 440 } |
425 } | 441 } |
426 } | 442 } |
427 // do we have enough information? | 443 // do we have enough information? |
428 if (instanceCreation == null) { | 444 if (instanceCreation == null) { |
429 return; | 445 return; |
430 } | 446 } |
431 // prepare environment | |
432 String eol = utils.endOfLine; | |
433 // prepare target | 447 // prepare target |
434 DartType targetType = typeName.type; | 448 DartType targetType = typeName.type; |
435 if (targetType is! InterfaceType) { | 449 if (targetType is! InterfaceType) { |
436 return; | 450 return; |
437 } | 451 } |
438 ClassElement targetElement = targetType.element as ClassElement; | 452 ClassElement targetElement = targetType.element as ClassElement; |
439 String targetFile = targetElement.source.fullName; | 453 String targetFile = targetElement.source.fullName; |
440 ClassDeclaration targetClass = targetElement.node; | 454 ClassDeclaration targetClass = targetElement.node; |
441 QuickFixProcessorImpl_NewConstructorLocation targetLocation = | 455 _ConstructorLocation targetLocation = |
442 _prepareNewConstructorLocation(targetClass, eol); | 456 _prepareNewConstructorLocation(targetClass); |
443 // build method source | 457 // build method source |
444 SourceBuilder sb = new SourceBuilder(targetFile, targetLocation._offset); | 458 SourceBuilder sb = new SourceBuilder(targetFile, targetLocation._offset); |
445 { | 459 { |
446 String indent = " "; | 460 String indent = " "; |
447 sb.append(targetLocation._prefix); | 461 sb.append(targetLocation._prefix); |
448 sb.append(indent); | 462 sb.append(indent); |
449 sb.append(targetElement.name); | 463 sb.append(targetElement.name); |
450 _addFix_undefinedMethod_create_parameters( | 464 _addFix_undefinedMethod_create_parameters( |
451 sb, | 465 sb, |
452 instanceCreation.argumentList); | 466 instanceCreation.argumentList); |
(...skipping 25 matching lines...) Expand all Loading... |
478 return; | 492 return; |
479 } | 493 } |
480 } | 494 } |
481 } | 495 } |
482 } | 496 } |
483 } | 497 } |
484 // do we have enough information? | 498 // do we have enough information? |
485 if (instanceCreation == null) { | 499 if (instanceCreation == null) { |
486 return; | 500 return; |
487 } | 501 } |
488 // prepare environment | |
489 String eol = utils.endOfLine; | |
490 // prepare target interface type | 502 // prepare target interface type |
491 DartType targetType = constructorName.type.type; | 503 DartType targetType = constructorName.type.type; |
492 if (targetType is! InterfaceType) { | 504 if (targetType is! InterfaceType) { |
493 return; | 505 return; |
494 } | 506 } |
495 ClassElement targetElement = targetType.element as ClassElement; | 507 ClassElement targetElement = targetType.element as ClassElement; |
496 String targetFile = targetElement.source.fullName; | 508 String targetFile = targetElement.source.fullName; |
497 ClassDeclaration targetClass = targetElement.node; | 509 ClassDeclaration targetClass = targetElement.node; |
498 QuickFixProcessorImpl_NewConstructorLocation targetLocation = | 510 _ConstructorLocation targetLocation = |
499 _prepareNewConstructorLocation(targetClass, eol); | 511 _prepareNewConstructorLocation(targetClass); |
500 // build method source | 512 // build method source |
501 SourceBuilder sb = new SourceBuilder(targetFile, targetLocation._offset); | 513 SourceBuilder sb = new SourceBuilder(targetFile, targetLocation._offset); |
502 { | 514 { |
503 String indent = " "; | 515 String indent = " "; |
504 sb.append(targetLocation._prefix); | 516 sb.append(targetLocation._prefix); |
505 sb.append(indent); | 517 sb.append(indent); |
506 sb.append(targetElement.name); | 518 sb.append(targetElement.name); |
507 sb.append("."); | 519 sb.append("."); |
508 // append name | 520 // append name |
509 { | 521 { |
(...skipping 10 matching lines...) Expand all Loading... |
520 // insert source | 532 // insert source |
521 _insertBuilder(sb); | 533 _insertBuilder(sb); |
522 if (targetFile == file) { | 534 if (targetFile == file) { |
523 _addLinkedPosition("NAME", rf.rangeNode(name)); | 535 _addLinkedPosition("NAME", rf.rangeNode(name)); |
524 } | 536 } |
525 // add proposal | 537 // add proposal |
526 _addFix(FixKind.CREATE_CONSTRUCTOR, [constructorName], fixFile: targetFile); | 538 _addFix(FixKind.CREATE_CONSTRUCTOR, [constructorName], fixFile: targetFile); |
527 } | 539 } |
528 | 540 |
529 void _addFix_createFunction_forFunctionType() { | 541 void _addFix_createFunction_forFunctionType() { |
530 // TODO(scheglov) implement | 542 if (node is SimpleIdentifier) { |
531 // if (node is SimpleIdentifier) { | 543 SimpleIdentifier nameNode = node as SimpleIdentifier; |
532 // SimpleIdentifier nameNode = node as SimpleIdentifier; | 544 // prepare argument expression (to get parameter) |
533 // // prepare argument expression (to get parameter) | 545 ClassElement targetElement; |
534 // ClassElement targetElement; | 546 Expression argument; |
535 // Expression argument; | 547 { |
536 // { | 548 Expression target = getQualifiedPropertyTarget(node); |
537 // Expression target = CorrectionUtils.getQualifiedPropertyTarget(node); | 549 if (target != null) { |
538 // if (target != null) { | 550 DartType targetType = target.bestType; |
539 // DartType targetType = target.bestType; | 551 if (targetType != null && targetType.element is ClassElement) { |
540 // if (targetType != null && targetType.element is ClassElement) { | 552 targetElement = targetType.element as ClassElement; |
541 // targetElement = targetType.element as ClassElement; | 553 argument = target.parent as Expression; |
542 // argument = target.parent as Expression; | 554 } else { |
543 // } else { | 555 return; |
544 // return; | 556 } |
545 // } | 557 } else { |
546 // } else { | 558 ClassDeclaration enclosingClass = |
547 // ClassDeclaration enclosingClass = | 559 node.getAncestor((node) => node is ClassDeclaration); |
548 // node.getAncestor((node) => node is ClassDeclaration); | 560 targetElement = enclosingClass != null ? |
549 // targetElement = enclosingClass != null ? | 561 enclosingClass.element : |
550 // enclosingClass.element : | 562 null; |
551 // null; | 563 argument = nameNode; |
552 // argument = nameNode; | 564 } |
553 // } | 565 } |
554 // } | 566 // should be argument of some invocation |
555 // // should be argument of some invocation | 567 ParameterElement parameterElement = argument.bestParameterElement; |
556 // ParameterElement parameterElement = argument.bestParameterElement; | 568 if (parameterElement == null) { |
557 // if (parameterElement == null) { | 569 return; |
558 // return; | 570 } |
559 // } | 571 // should be parameter of function type |
560 // // should be parameter of function type | 572 DartType parameterType = parameterElement.type; |
561 // DartType parameterType = parameterElement.type; | 573 if (parameterType is! FunctionType) { |
562 // if (parameterType is! FunctionType) { | 574 return; |
563 // return; | 575 } |
564 // } | 576 FunctionType functionType = parameterType as FunctionType; |
565 // FunctionType functionType = parameterType as FunctionType; | 577 // add proposal |
566 // // add proposal | 578 if (targetElement != null) { |
567 // if (targetElement != null) { | 579 _addProposal_createFunction_method(targetElement, functionType); |
568 // _addProposal_createFunction_method(targetElement, functionType); | 580 } else { |
569 // } else { | 581 _addProposal_createFunction_function(functionType); |
570 // _addProposal_createFunction_function(functionType); | 582 } |
571 // } | 583 } |
572 // } | |
573 } | 584 } |
574 | 585 |
575 void | 586 void |
576 _addFix_createMissingOverrides(List<ExecutableElement> missingOverrides) { | 587 _addFix_createMissingOverrides(List<ExecutableElement> missingOverrides) { |
577 // TODO(scheglov) implement | 588 // sort by name |
578 // // sort by name | 589 missingOverrides.sort((Element firstElement, Element secondElement) { |
579 // missingOverrides.sort( | 590 return compareStrings( |
580 // (Element firstElement, Element secondElement) => | 591 firstElement.displayName, |
581 // ObjectUtils.compare(firstElement.displayName, secondElement.displa
yName)); | 592 secondElement.displayName); |
582 // // add elements | 593 }); |
583 // ClassDeclaration targetClass = node.parent as ClassDeclaration; | 594 // TODO |
584 // bool isFirst = true; | 595 ClassDeclaration targetClass = node.parent as ClassDeclaration; |
585 // for (ExecutableElement missingOverride in missingOverrides) { | 596 int insertOffset = targetClass.end - 1; |
586 // _addFix_createMissingOverrides_single( | 597 SourceBuilder sb = new SourceBuilder(file, insertOffset); |
587 // targetClass, | 598 // add elements |
588 // missingOverride, | 599 bool isFirst = true; |
589 // isFirst); | 600 for (ExecutableElement missingOverride in missingOverrides) { |
590 // isFirst = false; | 601 if (!isFirst || !targetClass.members.isEmpty) { |
591 // } | 602 sb.append(eol); |
592 // // add proposal | 603 } |
593 // _addFix( | 604 _addFix_createMissingOverrides_single(sb, targetClass, missingOverride); |
594 // FixKind.CREATE_MISSING_OVERRIDES, | 605 isFirst = false; |
595 // [missingOverrides.length]); | 606 } |
| 607 // add proposal |
| 608 endPosition = new Position(file, insertOffset, 0); |
| 609 _insertBuilder(sb); |
| 610 _addFix(FixKind.CREATE_MISSING_OVERRIDES, [missingOverrides.length]); |
596 } | 611 } |
597 | 612 |
598 void _addFix_createMissingOverrides_single(ClassDeclaration targetClass, | 613 void _addFix_createMissingOverrides_single(SourceBuilder sb, |
599 ExecutableElement missingOverride, bool isFirst) { | 614 ClassDeclaration targetClass, ExecutableElement missingOverride) { |
600 // TODO(scheglov) implement | 615 // prepare environment |
601 // // prepare environment | 616 String prefix = utils.getIndent(1); |
602 // String eol = utils.endOfLine; | 617 String prefix2 = utils.getIndent(2); |
603 // String prefix = utils.getIndent(1); | 618 // may be property |
604 // String prefix2 = utils.getIndent(2); | 619 ElementKind elementKind = missingOverride.kind; |
605 // int insertOffset = targetClass.end - 1; | 620 bool isGetter = elementKind == ElementKind.GETTER; |
606 // // prepare source | 621 bool isSetter = elementKind == ElementKind.SETTER; |
607 // JavaStringBuilder sb = new JavaStringBuilder(); | 622 bool isMethod = elementKind == ElementKind.METHOD; |
608 // // may be empty line | 623 bool isOperator = isMethod && (missingOverride as MethodElement).isOperator; |
609 // if (!isFirst || !targetClass.members.isEmpty) { | 624 sb.append(prefix); |
610 // sb.append(eol); | 625 if (isGetter) { |
611 // } | 626 sb.append('// TODO: implement ${missingOverride.displayName}'); |
612 // // may be property | 627 sb.append(eol); |
613 // ElementKind elementKind = missingOverride.kind; | 628 sb.append(prefix); |
614 // bool isGetter = elementKind == ElementKind.GETTER; | 629 } |
615 // bool isSetter = elementKind == ElementKind.SETTER; | 630 // @override |
616 // bool isMethod = elementKind == ElementKind.METHOD; | 631 { |
617 // bool isOperator = isMethod && (missingOverride as MethodElement).isOperato
r; | 632 sb.append('@override'); |
618 // sb.append(prefix); | 633 sb.append(eol); |
619 // if (isGetter) { | 634 sb.append(prefix); |
620 // sb.append("// TODO: implement ${missingOverride.displayName}"); | 635 } |
621 // sb.append(eol); | 636 // return type |
622 // sb.append(prefix); | 637 _appendType(sb, missingOverride.type.returnType); |
623 // } | 638 if (isGetter) { |
624 // // @override | 639 sb.append('get '); |
625 // { | 640 } else if (isSetter) { |
626 // sb.append("@override"); | 641 sb.append('set '); |
627 // sb.append(eol); | 642 } else if (isOperator) { |
628 // sb.append(prefix); | 643 sb.append('operator '); |
629 // } | 644 } |
630 // // return type | 645 // name |
631 // _appendType(sb, missingOverride.type.returnType); | 646 sb.append(missingOverride.displayName); |
632 // if (isGetter) { | 647 // parameters + body |
633 // sb.append("get "); | 648 if (isGetter) { |
634 // } else if (isSetter) { | 649 sb.append(' => null;'); |
635 // sb.append("set "); | 650 } else { |
636 // } else if (isOperator) { | 651 List<ParameterElement> parameters = missingOverride.parameters; |
637 // sb.append("operator "); | 652 _appendParameters(sb, parameters, _getDefaultValueMap(parameters)); |
638 // } | 653 sb.append(' {'); |
639 // // name | 654 // TO-DO |
640 // sb.append(missingOverride.displayName); | 655 sb.append(eol); |
641 // // parameters + body | 656 sb.append(prefix2); |
642 // if (isGetter) { | 657 sb.append('// TODO: implement ${missingOverride.displayName}'); |
643 // sb.append(" => null;"); | 658 sb.append(eol); |
644 // } else if (isMethod || isSetter) { | 659 // close method |
645 // List<ParameterElement> parameters = missingOverride.parameters; | 660 sb.append(prefix); |
646 // _appendParameters(sb, parameters); | 661 sb.append('}'); |
647 // sb.append(" {"); | 662 } |
648 // // TO-DO | 663 sb.append(eol); |
649 // sb.append(eol); | |
650 // sb.append(prefix2); | |
651 // if (isMethod) { | |
652 // sb.append("// TODO: implement ${missingOverride.displayName}"); | |
653 // } else { | |
654 // sb.append("// TODO: implement ${missingOverride.displayName}"); | |
655 // } | |
656 // sb.append(eol); | |
657 // // close method | |
658 // sb.append(prefix); | |
659 // sb.append("}"); | |
660 // } | |
661 // sb.append(eol); | |
662 // // done | |
663 // _addInsertEdit(insertOffset, sb.toString()); | |
664 // // maybe set end range | |
665 // if (_endRange == null) { | |
666 // _endRange = SourceRangeFactory.rangeStartLength(insertOffset, 0); | |
667 // } | |
668 } | 664 } |
669 | 665 |
670 void _addFix_createNoSuchMethod() { | 666 void _addFix_createNoSuchMethod() { |
671 // TODO(scheglov) implement | 667 ClassDeclaration targetClass = node.parent as ClassDeclaration; |
672 // ClassDeclaration targetClass = node.parent as ClassDeclaration; | 668 // prepare environment |
673 // // prepare environment | 669 String prefix = utils.getIndent(1); |
674 // String eol = utils.endOfLine; | 670 int insertOffset = targetClass.end - 1; |
675 // String prefix = utils.getIndent(1); | 671 // prepare source |
676 // int insertOffset = targetClass.end - 1; | 672 SourceBuilder sb = new SourceBuilder(file, insertOffset); |
677 // // prepare source | 673 { |
678 // SourceBuilder sb = new SourceBuilder.con1(insertOffset); | 674 // insert empty line before existing member |
679 // { | 675 if (!targetClass.members.isEmpty) { |
680 // // insert empty line before existing member | 676 sb.append(eol); |
681 // if (!targetClass.members.isEmpty) { | 677 } |
682 // sb.append(eol); | 678 // append method |
683 // } | 679 sb.append(prefix); |
684 // // append method | 680 sb.append( |
685 // sb.append(prefix); | 681 "noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation)
;"); |
686 // sb.append( | 682 sb.append(eol); |
687 // "noSuchMethod(Invocation invocation) => super.noSuchMethod(invocatio
n);"); | 683 } |
688 // sb.append(eol); | 684 // done |
689 // } | 685 _insertBuilder(sb); |
690 // // done | 686 endPosition = new Position(file, insertOffset, 0); |
691 // _addInsertEdit3(sb); | 687 // add proposal |
692 // _endRange = SourceRangeFactory.rangeStartLength(insertOffset, 0); | 688 _addFix(FixKind.CREATE_NO_SUCH_METHOD, []); |
693 // // add proposal | |
694 // _addFix(FixKind.CREATE_NO_SUCH_METHOD, []); | |
695 } | 689 } |
696 | 690 |
| 691 |
697 void _addFix_createPart() { | 692 void _addFix_createPart() { |
698 // TODO(scheglov) implement | 693 // TODO(scheglov) implement |
699 // if (node is SimpleStringLiteral && node.parent is PartDirective) { | 694 // if (node is SimpleStringLiteral && node.parent is PartDirective) { |
700 // SimpleStringLiteral uriLiteral = node as SimpleStringLiteral; | 695 // SimpleStringLiteral uriLiteral = node as SimpleStringLiteral; |
701 // String uriString = uriLiteral.value; | 696 // String uriString = uriLiteral.value; |
702 // // prepare referenced File | 697 // // prepare referenced File |
703 // JavaFile newFile; | 698 // JavaFile newFile; |
704 // { | 699 // { |
705 // Uri uri = parseUriWithException(uriString); | 700 // Uri uri = parseUriWithException(uriString); |
706 // if (uri.isAbsolute) { | 701 // if (uri.isAbsolute) { |
707 // return; | 702 // return; |
708 // } | 703 // } |
709 // newFile = new JavaFile.relative(_unitLibraryFolder, uriString); | 704 // newFile = new JavaFile.relative(_unitLibraryFolder, uriString); |
710 // } | 705 // } |
711 // if (!newFile.exists()) { | 706 // if (!newFile.exists()) { |
712 // // prepare new source | 707 // // prepare new source |
713 // String source; | 708 // String source; |
714 // { | 709 // { |
715 // String eol = utils.endOfLine; | |
716 // String libraryName = _unitLibraryElement.displayName; | 710 // String libraryName = _unitLibraryElement.displayName; |
717 // source = "part of ${libraryName};${eol}${eol}"; | 711 // source = "part of ${libraryName};${eol}${eol}"; |
718 // } | 712 // } |
719 // // add proposal | 713 // // add proposal |
720 // _proposals.add( | 714 // _proposals.add( |
721 // new CreateFileCorrectionProposal( | 715 // new CreateFileCorrectionProposal( |
722 // newFile, | 716 // newFile, |
723 // source, | 717 // source, |
724 // FixKind.CREATE_PART, | 718 // FixKind.CREATE_PART, |
725 // [uriString])); | 719 // [uriString])); |
726 // } | 720 // } |
727 // } | 721 // } |
728 } | 722 } |
729 | 723 |
730 void _addFix_importLibrary(FixKind kind, String importPath) { | 724 void _addFix_importLibrary(FixKind kind, String importPath) { |
731 // TODO(scheglov) implement | 725 // TODO(scheglov) implement |
732 // CompilationUnitElement libraryUnitElement = | 726 // CompilationUnitElement libraryUnitElement = |
733 // _unitLibraryElement.definingCompilationUnit; | 727 // _unitLibraryElement.definingCompilationUnit; |
734 // CompilationUnit libraryUnit = libraryUnitElement.node; | 728 // CompilationUnit libraryUnit = libraryUnitElement.node; |
735 // // prepare new import location | 729 // // prepare new import location |
736 // int offset = 0; | 730 // int offset = 0; |
737 // String prefix; | 731 // String prefix; |
738 // String suffix; | 732 // String suffix; |
739 // { | 733 // { |
740 // String eol = utils.endOfLine; | |
741 // // if no directives | 734 // // if no directives |
742 // prefix = ""; | 735 // prefix = ""; |
743 // suffix = eol; | 736 // suffix = eol; |
744 // CorrectionUtils libraryUtils = new CorrectionUtils(libraryUnit); | 737 // CorrectionUtils libraryUtils = new CorrectionUtils(libraryUnit); |
745 // // after last directive in library | 738 // // after last directive in library |
746 // for (Directive directive in libraryUnit.directives) { | 739 // for (Directive directive in libraryUnit.directives) { |
747 // if (directive is LibraryDirective || directive is ImportDirective) { | 740 // if (directive is LibraryDirective || directive is ImportDirective) { |
748 // offset = directive.end; | 741 // offset = directive.end; |
749 // prefix = eol; | 742 // prefix = eol; |
750 // suffix = ""; | 743 // suffix = ""; |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1070 // return; | 1063 // return; |
1071 // } | 1064 // } |
1072 // String name = (node as SimpleIdentifier).name; | 1065 // String name = (node as SimpleIdentifier).name; |
1073 // MethodInvocation invocation = node.parent as MethodInvocation; | 1066 // MethodInvocation invocation = node.parent as MethodInvocation; |
1074 // // function invocation has no target | 1067 // // function invocation has no target |
1075 // Expression target = invocation.realTarget; | 1068 // Expression target = invocation.realTarget; |
1076 // if (target != null) { | 1069 // if (target != null) { |
1077 // return; | 1070 // return; |
1078 // } | 1071 // } |
1079 // // prepare environment | 1072 // // prepare environment |
1080 // String eol = utils.endOfLine; | |
1081 // int insertOffset; | 1073 // int insertOffset; |
1082 // String sourcePrefix; | 1074 // String sourcePrefix; |
1083 // AstNode enclosingMember = | 1075 // AstNode enclosingMember = |
1084 // node.getAncestor((node) => node is CompilationUnitMember); | 1076 // node.getAncestor((node) => node is CompilationUnitMember); |
1085 // insertOffset = enclosingMember.end; | 1077 // insertOffset = enclosingMember.end; |
1086 // sourcePrefix = "${eol}${eol}"; | 1078 // sourcePrefix = "${eol}${eol}"; |
1087 // // build method source | 1079 // // build method source |
1088 // SourceBuilder sb = new SourceBuilder.con1(insertOffset); | 1080 // SourceBuilder sb = new SourceBuilder.con1(insertOffset); |
1089 // { | 1081 // { |
1090 // sb.append(sourcePrefix); | 1082 // sb.append(sourcePrefix); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1144 // String closestName = null; | 1136 // String closestName = null; |
1145 // if (finder != null && finder._distance < 5) { | 1137 // if (finder != null && finder._distance < 5) { |
1146 // closestName = finder._element.name; | 1138 // closestName = finder._element.name; |
1147 // _addReplaceEdit(SourceRangeFactory.rangeNode(node), closestName); | 1139 // _addReplaceEdit(SourceRangeFactory.rangeNode(node), closestName); |
1148 // _addFix(FixKind.CHANGE_TO, [closestName]); | 1140 // _addFix(FixKind.CHANGE_TO, [closestName]); |
1149 // } | 1141 // } |
1150 // } | 1142 // } |
1151 } | 1143 } |
1152 | 1144 |
1153 void _addFix_undefinedMethod_create() { | 1145 void _addFix_undefinedMethod_create() { |
1154 // TODO(scheglov) implement | 1146 if (node is SimpleIdentifier && node.parent is MethodInvocation) { |
1155 // if (node is SimpleIdentifier && node.parent is MethodInvocation) { | 1147 String name = (node as SimpleIdentifier).name; |
1156 // String name = (node as SimpleIdentifier).name; | 1148 MethodInvocation invocation = node.parent as MethodInvocation; |
1157 // MethodInvocation invocation = node.parent as MethodInvocation; | 1149 // prepare environment |
1158 // // prepare environment | 1150 Source targetSource; |
1159 // String eol = utils.endOfLine; | 1151 String prefix; |
1160 // Source targetSource; | 1152 int insertOffset; |
1161 // String prefix; | 1153 String sourcePrefix; |
1162 // int insertOffset; | 1154 String sourceSuffix; |
1163 // String sourcePrefix; | 1155 bool staticModifier = false; |
1164 // String sourceSuffix; | 1156 Expression target = invocation.realTarget; |
1165 // bool staticModifier = false; | 1157 if (target == null) { |
1166 // Expression target = invocation.realTarget; | 1158 targetSource = source; |
1167 // if (target == null) { | 1159 ClassMember enclosingMember = |
1168 // targetSource = _source; | 1160 node.getAncestor((node) => node is ClassMember); |
1169 // ClassMember enclosingMember = | 1161 staticModifier = _inStaticContext(); |
1170 // node.getAncestor((node) => node is ClassMember); | 1162 prefix = utils.getNodePrefix(enclosingMember); |
1171 // staticModifier = _inStaticMemberContext2(enclosingMember); | 1163 insertOffset = enclosingMember.end; |
1172 // prefix = utils.getNodePrefix(enclosingMember); | 1164 sourcePrefix = "${eol}${prefix}${eol}"; |
1173 // insertOffset = enclosingMember.end; | 1165 sourceSuffix = ""; |
1174 // sourcePrefix = "${eol}${prefix}${eol}"; | 1166 } else { |
1175 // sourceSuffix = ""; | 1167 // prepare target interface type |
1176 // } else { | 1168 DartType targetType = target.bestType; |
1177 // // prepare target interface type | 1169 if (targetType is! InterfaceType) { |
1178 // DartType targetType = target.bestType; | 1170 return; |
1179 // if (targetType is! InterfaceType) { | 1171 } |
1180 // return; | 1172 ClassElement targetElement = targetType.element as ClassElement; |
1181 // } | 1173 targetSource = targetElement.source; |
1182 // ClassElement targetElement = targetType.element as ClassElement; | 1174 // may be static |
1183 // targetSource = targetElement.source; | 1175 if (target is Identifier) { |
1184 // // may be static | 1176 staticModifier = target.bestElement.kind == ElementKind.CLASS; |
1185 // if (target is Identifier) { | 1177 } |
1186 // staticModifier = target.bestElement.kind == ElementKind.CLASS; | 1178 // prepare insert offset |
1187 // } | 1179 ClassDeclaration targetClass = targetElement.node; |
1188 // // prepare insert offset | 1180 prefix = " "; |
1189 // ClassDeclaration targetClass = targetElement.node; | 1181 insertOffset = targetClass.end - 1; |
1190 // prefix = " "; | 1182 if (targetClass.members.isEmpty) { |
1191 // insertOffset = targetClass.end - 1; | 1183 sourcePrefix = ""; |
1192 // if (targetClass.members.isEmpty) { | 1184 } else { |
1193 // sourcePrefix = ""; | 1185 sourcePrefix = eol; |
1194 // } else { | 1186 } |
1195 // sourcePrefix = "${prefix}${eol}"; | 1187 sourceSuffix = eol; |
1196 // } | 1188 } |
1197 // sourceSuffix = eol; | 1189 String targetFile = targetSource.fullName; |
1198 // } | 1190 // build method source |
1199 // // build method source | 1191 SourceBuilder sb = new SourceBuilder(targetFile, insertOffset); |
1200 // SourceBuilder sb = new SourceBuilder.con1(insertOffset); | 1192 { |
1201 // { | 1193 sb.append(sourcePrefix); |
1202 // sb.append(sourcePrefix); | 1194 sb.append(prefix); |
1203 // sb.append(prefix); | 1195 // maybe "static" |
1204 // // may be "static" | 1196 if (staticModifier) { |
1205 // if (staticModifier) { | 1197 sb.append("static "); |
1206 // sb.append("static "); | 1198 } |
1207 // } | 1199 // append return type |
1208 // // may be return type | 1200 _appendType(sb, _inferReturnType(invocation), 'RETURN_TYPE'); |
1209 // { | 1201 // append name |
1210 // DartType type = | 1202 { |
1211 // _addFix_undefinedMethod_create_getReturnType(invocation); | 1203 sb.startPosition("NAME"); |
1212 // if (type != null) { | 1204 sb.append(name); |
1213 // String typeSource = utils.getTypeSource2(type); | 1205 sb.endPosition(); |
1214 // if (typeSource != "dynamic") { | 1206 } |
1215 // sb.startPosition("RETURN_TYPE"); | 1207 _addFix_undefinedMethod_create_parameters(sb, invocation.argumentList); |
1216 // sb.append(typeSource); | 1208 sb.append(") {${eol}${prefix}}"); |
1217 // sb.endPosition(); | 1209 sb.append(sourceSuffix); |
1218 // sb.append(" "); | 1210 } |
1219 // } | 1211 // insert source |
1220 // } | 1212 _insertBuilder(sb); |
1221 // } | 1213 // add linked positions |
1222 // // append name | 1214 if (targetSource == source) { |
1223 // { | 1215 _addLinkedPosition3('NAME', sb, rf.rangeNode(node)); |
1224 // sb.startPosition("NAME"); | 1216 } |
1225 // sb.append(name); | 1217 // add proposal |
1226 // sb.endPosition(); | 1218 _addFix(FixKind.CREATE_METHOD, [name], fixFile: targetFile); |
1227 // } | 1219 } |
1228 // _addFix_undefinedMethod_create_parameters(sb, invocation.argumentList)
; | |
1229 // sb.append(") {${eol}${prefix}}"); | |
1230 // sb.append(sourceSuffix); | |
1231 // } | |
1232 // // insert source | |
1233 // _addInsertEdit(insertOffset, sb.toString()); | |
1234 // // add linked positions | |
1235 // if (targetSource == _source) { | |
1236 // _addLinkedPosition("NAME", sb, SourceRangeFactory.rangeNode(node)); | |
1237 // } | |
1238 // _addLinkedPositions(sb); | |
1239 // // add proposal | |
1240 // _addUnitCorrectionProposal2( | |
1241 // targetSource, | |
1242 // FixKind.CREATE_METHOD, | |
1243 // [name]); | |
1244 // } | |
1245 } | |
1246 | |
1247 /** | |
1248 * @return the possible return [Type], may be <code>null</code> if can not be
identified. | |
1249 */ | |
1250 DartType | |
1251 _addFix_undefinedMethod_create_getReturnType(MethodInvocation invocation)
{ | |
1252 // TODO(scheglov) implement | |
1253 // AstNode parent = invocation.parent; | |
1254 // // myFunction(); | |
1255 // if (parent is ExpressionStatement) { | |
1256 // return VoidTypeImpl.instance; | |
1257 // } | |
1258 // // return myFunction(); | |
1259 // if (parent is ReturnStatement) { | |
1260 // ExecutableElement executable = | |
1261 // CorrectionUtils.getEnclosingExecutableElement(invocation); | |
1262 // return executable != null ? executable.returnType : null; | |
1263 // } | |
1264 // // int v = myFunction(); | |
1265 // if (parent is VariableDeclaration) { | |
1266 // VariableDeclaration variableDeclaration = parent; | |
1267 // if (identical(variableDeclaration.initializer, invocation)) { | |
1268 // VariableElement variableElement = variableDeclaration.element; | |
1269 // if (variableElement != null) { | |
1270 // return variableElement.type; | |
1271 // } | |
1272 // } | |
1273 // } | |
1274 // // v = myFunction(); | |
1275 // if (parent is AssignmentExpression) { | |
1276 // AssignmentExpression assignment = parent; | |
1277 // if (identical(assignment.rightHandSide, invocation)) { | |
1278 // if (assignment.operator.type == TokenType.EQ) { | |
1279 // // v = myFunction(); | |
1280 // Expression lhs = assignment.leftHandSide; | |
1281 // if (lhs != null) { | |
1282 // return lhs.bestType; | |
1283 // } | |
1284 // } else { | |
1285 // // v += myFunction(); | |
1286 // MethodElement method = assignment.bestElement; | |
1287 // if (method != null) { | |
1288 // List<ParameterElement> parameters = method.parameters; | |
1289 // if (parameters.length == 1) { | |
1290 // return parameters[0].type; | |
1291 // } | |
1292 // } | |
1293 // } | |
1294 // } | |
1295 // } | |
1296 // // v + myFunction(); | |
1297 // if (parent is BinaryExpression) { | |
1298 // BinaryExpression binary = parent; | |
1299 // MethodElement method = binary.bestElement; | |
1300 // if (method != null) { | |
1301 // if (identical(binary.rightOperand, invocation)) { | |
1302 // List<ParameterElement> parameters = method.parameters; | |
1303 // return parameters.length == 1 ? parameters[0].type : null; | |
1304 // } | |
1305 // } | |
1306 // } | |
1307 // // foo( myFunction() ); | |
1308 // if (parent is ArgumentList) { | |
1309 // ParameterElement parameter = invocation.bestParameterElement; | |
1310 // return parameter != null ? parameter.type : null; | |
1311 // } | |
1312 // // bool | |
1313 // { | |
1314 // // assert( myFunction() ); | |
1315 // if (parent is AssertStatement) { | |
1316 // AssertStatement statement = parent; | |
1317 // if (identical(statement.condition, invocation)) { | |
1318 // return coreTypeBool; | |
1319 // } | |
1320 // } | |
1321 // // if ( myFunction() ) {} | |
1322 // if (parent is IfStatement) { | |
1323 // IfStatement statement = parent; | |
1324 // if (identical(statement.condition, invocation)) { | |
1325 // return coreTypeBool; | |
1326 // } | |
1327 // } | |
1328 // // while ( myFunction() ) {} | |
1329 // if (parent is WhileStatement) { | |
1330 // WhileStatement statement = parent; | |
1331 // if (identical(statement.condition, invocation)) { | |
1332 // return coreTypeBool; | |
1333 // } | |
1334 // } | |
1335 // // do {} while ( myFunction() ); | |
1336 // if (parent is DoStatement) { | |
1337 // DoStatement statement = parent; | |
1338 // if (identical(statement.condition, invocation)) { | |
1339 // return coreTypeBool; | |
1340 // } | |
1341 // } | |
1342 // // !myFunction() | |
1343 // if (parent is PrefixExpression) { | |
1344 // PrefixExpression prefixExpression = parent; | |
1345 // if (prefixExpression.operator.type == TokenType.BANG) { | |
1346 // return coreTypeBool; | |
1347 // } | |
1348 // } | |
1349 // // binary expression '&&' or '||' | |
1350 // if (parent is BinaryExpression) { | |
1351 // BinaryExpression binaryExpression = parent; | |
1352 // TokenType operatorType = binaryExpression.operator.type; | |
1353 // if (operatorType == TokenType.AMPERSAND_AMPERSAND || | |
1354 // operatorType == TokenType.BAR_BAR) { | |
1355 // return coreTypeBool; | |
1356 // } | |
1357 // } | |
1358 // } | |
1359 // we don't know | |
1360 return null; | |
1361 } | 1220 } |
1362 | 1221 |
1363 void _addFix_undefinedMethod_create_parameters(SourceBuilder sb, | 1222 void _addFix_undefinedMethod_create_parameters(SourceBuilder sb, |
1364 ArgumentList argumentList) { | 1223 ArgumentList argumentList) { |
1365 // append parameters | 1224 // append parameters |
1366 sb.append("("); | 1225 sb.append("("); |
1367 Set<String> excluded = new Set(); | 1226 Set<String> excluded = new Set(); |
1368 List<Expression> arguments = argumentList.arguments; | 1227 List<Expression> arguments = argumentList.arguments; |
1369 for (int i = 0; i < arguments.length; i++) { | 1228 for (int i = 0; i < arguments.length; i++) { |
1370 Expression argument = arguments[i]; | 1229 Expression argument = arguments[i]; |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1510 void _addLinkedPosition2(String groupId, Position position) { | 1369 void _addLinkedPosition2(String groupId, Position position) { |
1511 LinkedPositionGroup group = linkedPositionGroups[groupId]; | 1370 LinkedPositionGroup group = linkedPositionGroups[groupId]; |
1512 if (group == null) { | 1371 if (group == null) { |
1513 group = new LinkedPositionGroup(groupId); | 1372 group = new LinkedPositionGroup(groupId); |
1514 linkedPositionGroups[groupId] = group; | 1373 linkedPositionGroups[groupId] = group; |
1515 } | 1374 } |
1516 group.add(position); | 1375 group.add(position); |
1517 } | 1376 } |
1518 | 1377 |
1519 /** | 1378 /** |
| 1379 * Adds a single linked position to [groupId]. |
| 1380 */ |
| 1381 void _addLinkedPosition3(String groupId, SourceBuilder sb, |
| 1382 SourceRange range) { |
| 1383 if (sb.offset < range.offset) { |
| 1384 int delta = sb.length; |
| 1385 range = range.getTranslated(delta); |
| 1386 } |
| 1387 _addLinkedPosition(groupId, range); |
| 1388 } |
| 1389 |
| 1390 /** |
| 1391 * Prepares proposal for creating function corresponding to the given [Functio
nType]. |
| 1392 */ |
| 1393 void _addProposal_createFunction(FunctionType functionType, String name, |
| 1394 Source targetSource, int insertOffset, bool isStatic, String prefix, |
| 1395 String sourcePrefix, String sourceSuffix) { |
| 1396 // build method source |
| 1397 String targetFile = targetSource.fullName; |
| 1398 SourceBuilder sb = new SourceBuilder(targetFile, insertOffset); |
| 1399 { |
| 1400 sb.append(sourcePrefix); |
| 1401 sb.append(prefix); |
| 1402 // may be static |
| 1403 if (isStatic) { |
| 1404 sb.append("static "); |
| 1405 } |
| 1406 // append return type |
| 1407 _appendType(sb, functionType.returnType, 'RETURN_TYPE'); |
| 1408 // append name |
| 1409 { |
| 1410 sb.startPosition("NAME"); |
| 1411 sb.append(name); |
| 1412 sb.endPosition(); |
| 1413 } |
| 1414 // append parameters |
| 1415 sb.append("("); |
| 1416 List<ParameterElement> parameters = functionType.parameters; |
| 1417 for (int i = 0; i < parameters.length; i++) { |
| 1418 ParameterElement parameter = parameters[i]; |
| 1419 // append separator |
| 1420 if (i != 0) { |
| 1421 sb.append(", "); |
| 1422 } |
| 1423 // append type name |
| 1424 DartType type = parameter.type; |
| 1425 if (!type.isDynamic) { |
| 1426 String typeSource = utils.getTypeSource(type); |
| 1427 { |
| 1428 sb.startPosition("TYPE${i}"); |
| 1429 sb.append(typeSource); |
| 1430 _addSuperTypeProposals(sb, new Set(), type); |
| 1431 sb.endPosition(); |
| 1432 } |
| 1433 sb.append(" "); |
| 1434 } |
| 1435 // append parameter name |
| 1436 { |
| 1437 sb.startPosition("ARG${i}"); |
| 1438 sb.append(parameter.displayName); |
| 1439 sb.endPosition(); |
| 1440 } |
| 1441 } |
| 1442 sb.append(")"); |
| 1443 // close method |
| 1444 sb.append(" {${eol}${prefix}}"); |
| 1445 sb.append(sourceSuffix); |
| 1446 } |
| 1447 // insert source |
| 1448 _insertBuilder(sb); |
| 1449 // add linked positions |
| 1450 if (targetSource == source) { |
| 1451 _addLinkedPosition3("NAME", sb, rf.rangeNode(node)); |
| 1452 } |
| 1453 } |
| 1454 |
| 1455 /** |
| 1456 * Adds proposal for creating method corresponding to the given [FunctionType]
in the given |
| 1457 * [ClassElement]. |
| 1458 */ |
| 1459 void _addProposal_createFunction_function(FunctionType functionType) { |
| 1460 String name = (node as SimpleIdentifier).name; |
| 1461 // prepare environment |
| 1462 int insertOffset = unit.end; |
| 1463 // prepare prefix |
| 1464 String prefix = ""; |
| 1465 String sourcePrefix = "${eol}"; |
| 1466 String sourceSuffix = eol; |
| 1467 _addProposal_createFunction( |
| 1468 functionType, |
| 1469 name, |
| 1470 source, |
| 1471 insertOffset, |
| 1472 false, |
| 1473 prefix, |
| 1474 sourcePrefix, |
| 1475 sourceSuffix); |
| 1476 // add proposal |
| 1477 _addFix(FixKind.CREATE_FUNCTION, [name], fixFile: file); |
| 1478 } |
| 1479 |
| 1480 /** |
| 1481 * Adds proposal for creating method corresponding to the given [FunctionType]
in the given |
| 1482 * [ClassElement]. |
| 1483 */ |
| 1484 void _addProposal_createFunction_method(ClassElement targetClassElement, |
| 1485 FunctionType functionType) { |
| 1486 String name = (node as SimpleIdentifier).name; |
| 1487 // prepare environment |
| 1488 Source targetSource = targetClassElement.source; |
| 1489 String targetFile = targetSource.fullName; |
| 1490 // prepare insert offset |
| 1491 ClassDeclaration targetClassNode = targetClassElement.node; |
| 1492 int insertOffset = targetClassNode.end - 1; |
| 1493 // prepare prefix |
| 1494 String prefix = " "; |
| 1495 String sourcePrefix; |
| 1496 if (targetClassNode.members.isEmpty) { |
| 1497 sourcePrefix = ""; |
| 1498 } else { |
| 1499 sourcePrefix = eol; |
| 1500 } |
| 1501 String sourceSuffix = eol; |
| 1502 _addProposal_createFunction( |
| 1503 functionType, |
| 1504 name, |
| 1505 targetSource, |
| 1506 insertOffset, |
| 1507 _inStaticContext(), |
| 1508 prefix, |
| 1509 sourcePrefix, |
| 1510 sourceSuffix); |
| 1511 // add proposal |
| 1512 _addFix(FixKind.CREATE_METHOD, [name], fixFile: targetFile); |
| 1513 } |
| 1514 |
| 1515 /** |
1520 * Adds a new [Edit] to [edits]. | 1516 * Adds a new [Edit] to [edits]. |
1521 */ | 1517 */ |
1522 void _addRemoveEdit(SourceRange range) { | 1518 void _addRemoveEdit(SourceRange range) { |
1523 _addReplaceEdit(range, ''); | 1519 _addReplaceEdit(range, ''); |
1524 } | 1520 } |
1525 | 1521 |
1526 /** | 1522 /** |
1527 * Adds a new [Edit] to [edits]. | 1523 * Adds a new [Edit] to [edits]. |
1528 */ | 1524 */ |
1529 void _addReplaceEdit(SourceRange range, String text) { | 1525 void _addReplaceEdit(SourceRange range, String text) { |
1530 Edit edit = new Edit(range.offset, range.length, text); | 1526 Edit edit = new Edit(range.offset, range.length, text); |
1531 edits.add(edit); | 1527 edits.add(edit); |
1532 } | 1528 } |
1533 | 1529 |
1534 void _appendParameterSource(StringBuffer sb, DartType type, String name) { | 1530 void _appendParameterSource(SourceBuilder sb, DartType type, String name) { |
1535 String parameterSource = utils.getParameterSource(type, name); | 1531 String parameterSource = utils.getParameterSource(type, name); |
1536 sb.write(parameterSource); | 1532 sb.append(parameterSource); |
1537 } | 1533 } |
1538 | 1534 |
1539 void _appendParameters(StringBuffer sb, List<ParameterElement> parameters, | 1535 void _appendParameters(SourceBuilder sb, List<ParameterElement> parameters, |
1540 Map<ParameterElement, String> defaultValueMap) { | 1536 Map<ParameterElement, String> defaultValueMap) { |
1541 sb.write("("); | 1537 sb.append("("); |
1542 bool firstParameter = true; | 1538 bool firstParameter = true; |
1543 bool sawNamed = false; | 1539 bool sawNamed = false; |
1544 bool sawPositional = false; | 1540 bool sawPositional = false; |
1545 for (ParameterElement parameter in parameters) { | 1541 for (ParameterElement parameter in parameters) { |
1546 if (!firstParameter) { | 1542 if (!firstParameter) { |
1547 sb.write(", "); | 1543 sb.append(", "); |
1548 } else { | 1544 } else { |
1549 firstParameter = false; | 1545 firstParameter = false; |
1550 } | 1546 } |
1551 // may be optional | 1547 // may be optional |
1552 ParameterKind parameterKind = parameter.parameterKind; | 1548 ParameterKind parameterKind = parameter.parameterKind; |
1553 if (parameterKind == ParameterKind.NAMED) { | 1549 if (parameterKind == ParameterKind.NAMED) { |
1554 if (!sawNamed) { | 1550 if (!sawNamed) { |
1555 sb.write("{"); | 1551 sb.append("{"); |
1556 sawNamed = true; | 1552 sawNamed = true; |
1557 } | 1553 } |
1558 } | 1554 } |
1559 if (parameterKind == ParameterKind.POSITIONAL) { | 1555 if (parameterKind == ParameterKind.POSITIONAL) { |
1560 if (!sawPositional) { | 1556 if (!sawPositional) { |
1561 sb.write("["); | 1557 sb.append("["); |
1562 sawPositional = true; | 1558 sawPositional = true; |
1563 } | 1559 } |
1564 } | 1560 } |
1565 // parameter | 1561 // parameter |
1566 _appendParameterSource(sb, parameter.type, parameter.name); | 1562 _appendParameterSource(sb, parameter.type, parameter.name); |
1567 // default value | 1563 // default value |
1568 if (defaultValueMap != null) { | 1564 if (defaultValueMap != null) { |
1569 String defaultSource = defaultValueMap[parameter]; | 1565 String defaultSource = defaultValueMap[parameter]; |
1570 if (defaultSource != null) { | 1566 if (defaultSource != null) { |
1571 if (sawPositional) { | 1567 if (sawPositional) { |
1572 sb.write(" = "); | 1568 sb.append(" = "); |
1573 } else { | 1569 } else { |
1574 sb.write(": "); | 1570 sb.append(": "); |
1575 } | 1571 } |
1576 sb.write(defaultSource); | 1572 sb.append(defaultSource); |
1577 } | 1573 } |
1578 } | 1574 } |
1579 } | 1575 } |
1580 // close parameters | 1576 // close parameters |
1581 if (sawNamed) { | 1577 if (sawNamed) { |
1582 sb.write("}"); | 1578 sb.append("}"); |
1583 } | 1579 } |
1584 if (sawPositional) { | 1580 if (sawPositional) { |
1585 sb.write("]"); | 1581 sb.append("]"); |
1586 } | 1582 } |
1587 sb.write(")"); | 1583 sb.append(")"); |
1588 } | 1584 } |
1589 | 1585 |
1590 // void _addLinkedPositionProposal(String group, | 1586 void _appendType(SourceBuilder sb, DartType type, [String groupId]) { |
1591 // LinkedPositionProposal proposal) { | 1587 if (type != null && !type.isDynamic) { |
1592 // List<LinkedPositionProposal> nodeProposals = linkedPositionProposals[group
]; | 1588 String typeSource = utils.getTypeSource(type); |
1593 // if (nodeProposals == null) { | 1589 if (groupId != null) { |
1594 // nodeProposals = <LinkedPositionProposal>[]; | 1590 sb.startPosition(groupId); |
1595 // linkedPositionProposals[group] = nodeProposals; | 1591 sb.append(typeSource); |
1596 // } | 1592 sb.endPosition(); |
1597 // nodeProposals.add(proposal); | 1593 } else { |
1598 // } | 1594 sb.append(typeSource); |
| 1595 } |
| 1596 sb.append(' '); |
| 1597 } |
| 1598 } |
1599 | 1599 |
1600 /** | 1600 /** |
1601 * @return the string to display as the name of the given constructor in a pro
posal name. | 1601 * @return the string to display as the name of the given constructor in a pro
posal name. |
1602 */ | 1602 */ |
1603 String _getConstructorProposalName(ConstructorElement constructor) { | 1603 String _getConstructorProposalName(ConstructorElement constructor) { |
1604 StringBuffer proposalNameBuffer = new StringBuffer(); | 1604 SourceBuilder proposalNameBuffer = new SourceBuilder.buffer(); |
1605 proposalNameBuffer.write("super"); | 1605 proposalNameBuffer.append("super"); |
1606 // may be named | 1606 // may be named |
1607 String constructorName = constructor.displayName; | 1607 String constructorName = constructor.displayName; |
1608 if (!constructorName.isEmpty) { | 1608 if (!constructorName.isEmpty) { |
1609 proposalNameBuffer.write("."); | 1609 proposalNameBuffer.append("."); |
1610 proposalNameBuffer.write(constructorName); | 1610 proposalNameBuffer.append(constructorName); |
1611 } | 1611 } |
1612 // parameters | 1612 // parameters |
1613 _appendParameters(proposalNameBuffer, constructor.parameters, null); | 1613 _appendParameters(proposalNameBuffer, constructor.parameters, null); |
1614 // done | 1614 // done |
1615 return proposalNameBuffer.toString(); | 1615 return proposalNameBuffer.toString(); |
1616 } | 1616 } |
1617 | 1617 |
1618 /** | 1618 /** |
| 1619 * Returns the [Type] with given name from the `dart:core` library. |
| 1620 */ |
| 1621 DartType _getCoreType(String name) { |
| 1622 List<LibraryElement> libraries = unitLibraryElement.importedLibraries; |
| 1623 for (LibraryElement library in libraries) { |
| 1624 if (library.isDartCore) { |
| 1625 ClassElement classElement = library.getType(name); |
| 1626 if (classElement != null) { |
| 1627 return classElement.type; |
| 1628 } |
| 1629 return null; |
| 1630 } |
| 1631 } |
| 1632 return null; |
| 1633 } |
| 1634 |
| 1635 Map<ParameterElement, String> |
| 1636 _getDefaultValueMap(List<ParameterElement> parameters) { |
| 1637 Map<ParameterElement, String> defaultSourceMap = {}; |
| 1638 Map<Source, String> sourceContentMap = {}; |
| 1639 for (ParameterElement parameter in parameters) { |
| 1640 SourceRange valueRange = parameter.defaultValueRange; |
| 1641 if (valueRange != null) { |
| 1642 Source source = parameter.source; |
| 1643 String sourceContent = sourceContentMap[source]; |
| 1644 if (sourceContent == null) { |
| 1645 sourceContent = getSourceContent(parameter.context, source); |
| 1646 sourceContentMap[source] = sourceContent; |
| 1647 } |
| 1648 String valueSource = |
| 1649 sourceContent.substring(valueRange.offset, valueRange.end); |
| 1650 defaultSourceMap[parameter] = valueSource; |
| 1651 } |
| 1652 } |
| 1653 return defaultSourceMap; |
| 1654 } |
| 1655 |
| 1656 /** |
| 1657 * Returns `true` if [node] is in static context. |
| 1658 */ |
| 1659 bool _inStaticContext() { |
| 1660 // constructor initializer cannot reference "this" |
| 1661 if (node.getAncestor((node) => node is ConstructorInitializer) != null) { |
| 1662 return true; |
| 1663 } |
| 1664 // field initializer cannot reference "this" |
| 1665 if (node.getAncestor((node) => node is FieldDeclaration) != null) { |
| 1666 return true; |
| 1667 } |
| 1668 // static method |
| 1669 MethodDeclaration method = node.getAncestor((node) { |
| 1670 return node is MethodDeclaration; |
| 1671 }); |
| 1672 return method != null && method.isStatic; |
| 1673 } |
| 1674 |
| 1675 /** |
| 1676 * Returns a possible return [Type], may be `null` if cannot be inferred. |
| 1677 */ |
| 1678 DartType _inferReturnType(MethodInvocation invocation) { |
| 1679 AstNode parent = invocation.parent; |
| 1680 // myFunction(); |
| 1681 if (parent is ExpressionStatement) { |
| 1682 return VoidTypeImpl.instance; |
| 1683 } |
| 1684 // return myFunction(); |
| 1685 if (parent is ReturnStatement) { |
| 1686 ExecutableElement executable = getEnclosingExecutableElement(invocation); |
| 1687 return executable != null ? executable.returnType : null; |
| 1688 } |
| 1689 // int v = myFunction(); |
| 1690 if (parent is VariableDeclaration) { |
| 1691 VariableDeclaration variableDeclaration = parent; |
| 1692 if (identical(variableDeclaration.initializer, invocation)) { |
| 1693 VariableElement variableElement = variableDeclaration.element; |
| 1694 if (variableElement != null) { |
| 1695 return variableElement.type; |
| 1696 } |
| 1697 } |
| 1698 } |
| 1699 // v = myFunction(); |
| 1700 if (parent is AssignmentExpression) { |
| 1701 AssignmentExpression assignment = parent; |
| 1702 if (identical(assignment.rightHandSide, invocation)) { |
| 1703 if (assignment.operator.type == TokenType.EQ) { |
| 1704 // v = myFunction(); |
| 1705 Expression lhs = assignment.leftHandSide; |
| 1706 if (lhs != null) { |
| 1707 return lhs.bestType; |
| 1708 } |
| 1709 } else { |
| 1710 // v += myFunction(); |
| 1711 MethodElement method = assignment.bestElement; |
| 1712 if (method != null) { |
| 1713 List<ParameterElement> parameters = method.parameters; |
| 1714 if (parameters.length == 1) { |
| 1715 return parameters[0].type; |
| 1716 } |
| 1717 } |
| 1718 } |
| 1719 } |
| 1720 } |
| 1721 // v + myFunction(); |
| 1722 if (parent is BinaryExpression) { |
| 1723 BinaryExpression binary = parent; |
| 1724 MethodElement method = binary.bestElement; |
| 1725 if (method != null) { |
| 1726 if (identical(binary.rightOperand, invocation)) { |
| 1727 List<ParameterElement> parameters = method.parameters; |
| 1728 return parameters.length == 1 ? parameters[0].type : null; |
| 1729 } |
| 1730 } |
| 1731 } |
| 1732 // foo( myFunction() ); |
| 1733 if (parent is ArgumentList) { |
| 1734 ParameterElement parameter = invocation.bestParameterElement; |
| 1735 return parameter != null ? parameter.type : null; |
| 1736 } |
| 1737 // bool |
| 1738 { |
| 1739 // assert( myFunction() ); |
| 1740 if (parent is AssertStatement) { |
| 1741 AssertStatement statement = parent; |
| 1742 if (identical(statement.condition, invocation)) { |
| 1743 return coreTypeBool; |
| 1744 } |
| 1745 } |
| 1746 // if ( myFunction() ) {} |
| 1747 if (parent is IfStatement) { |
| 1748 IfStatement statement = parent; |
| 1749 if (identical(statement.condition, invocation)) { |
| 1750 return coreTypeBool; |
| 1751 } |
| 1752 } |
| 1753 // while ( myFunction() ) {} |
| 1754 if (parent is WhileStatement) { |
| 1755 WhileStatement statement = parent; |
| 1756 if (identical(statement.condition, invocation)) { |
| 1757 return coreTypeBool; |
| 1758 } |
| 1759 } |
| 1760 // do {} while ( myFunction() ); |
| 1761 if (parent is DoStatement) { |
| 1762 DoStatement statement = parent; |
| 1763 if (identical(statement.condition, invocation)) { |
| 1764 return coreTypeBool; |
| 1765 } |
| 1766 } |
| 1767 // !myFunction() |
| 1768 if (parent is PrefixExpression) { |
| 1769 PrefixExpression prefixExpression = parent; |
| 1770 if (prefixExpression.operator.type == TokenType.BANG) { |
| 1771 return coreTypeBool; |
| 1772 } |
| 1773 } |
| 1774 // binary expression '&&' or '||' |
| 1775 if (parent is BinaryExpression) { |
| 1776 BinaryExpression binaryExpression = parent; |
| 1777 TokenType operatorType = binaryExpression.operator.type; |
| 1778 if (operatorType == TokenType.AMPERSAND_AMPERSAND || |
| 1779 operatorType == TokenType.BAR_BAR) { |
| 1780 return coreTypeBool; |
| 1781 } |
| 1782 } |
| 1783 } |
| 1784 // we don't know |
| 1785 return null; |
| 1786 } |
| 1787 |
| 1788 // void _addLinkedPositionProposal(String group, |
| 1789 // LinkedPositionProposal proposal) { |
| 1790 // List<LinkedPositionProposal> nodeProposals = linkedPositionProposals[group
]; |
| 1791 // if (nodeProposals == null) { |
| 1792 // nodeProposals = <LinkedPositionProposal>[]; |
| 1793 // linkedPositionProposals[group] = nodeProposals; |
| 1794 // } |
| 1795 // nodeProposals.add(proposal); |
| 1796 // } |
| 1797 |
| 1798 // /** |
| 1799 // * Returns `true` if the given [ClassMember] is a part of a static method or |
| 1800 // * a field initializer. |
| 1801 // */ |
| 1802 // bool _inStaticMemberContext2(ClassMember member) { |
| 1803 // if (member is MethodDeclaration) { |
| 1804 // return member.isStatic; |
| 1805 // } |
| 1806 // // field initializer cannot reference "this" |
| 1807 // if (member is FieldDeclaration) { |
| 1808 // return true; |
| 1809 // } |
| 1810 // return false; |
| 1811 // } |
| 1812 |
| 1813 /** |
1619 * Inserts the given [SourceBuilder] at its offset. | 1814 * Inserts the given [SourceBuilder] at its offset. |
1620 */ | 1815 */ |
1621 void _insertBuilder(SourceBuilder builder) { | 1816 void _insertBuilder(SourceBuilder builder) { |
1622 String text = builder.toString(); | 1817 String text = builder.toString(); |
1623 _addInsertEdit(builder.offset, text); | 1818 _addInsertEdit(builder.offset, text); |
1624 // add linked positions | 1819 // add linked positions |
1625 builder.linkedPositionGroups.forEach((LinkedPositionGroup group) { | 1820 builder.linkedPositionGroups.forEach((LinkedPositionGroup group) { |
1626 group.positions.forEach((Position position) { | 1821 group.positions.forEach((Position position) { |
1627 _addLinkedPosition2(group.id, position); | 1822 _addLinkedPosition2(group.id, position); |
1628 }); | 1823 }); |
1629 }); | 1824 }); |
1630 } | 1825 } |
1631 | 1826 |
1632 QuickFixProcessorImpl_NewConstructorLocation | 1827 _ConstructorLocation |
1633 _prepareNewConstructorLocation(ClassDeclaration classDeclaration, String e
ol) { | 1828 _prepareNewConstructorLocation(ClassDeclaration classDeclaration) { |
1634 List<ClassMember> members = classDeclaration.members; | 1829 List<ClassMember> members = classDeclaration.members; |
1635 // find the last field/constructor | 1830 // find the last field/constructor |
1636 ClassMember lastFieldOrConstructor = null; | 1831 ClassMember lastFieldOrConstructor = null; |
1637 for (ClassMember member in members) { | 1832 for (ClassMember member in members) { |
1638 if (member is FieldDeclaration || member is ConstructorDeclaration) { | 1833 if (member is FieldDeclaration || member is ConstructorDeclaration) { |
1639 lastFieldOrConstructor = member; | 1834 lastFieldOrConstructor = member; |
1640 } else { | 1835 } else { |
1641 break; | 1836 break; |
1642 } | 1837 } |
1643 } | 1838 } |
1644 // after the field/constructor | 1839 // after the field/constructor |
1645 if (lastFieldOrConstructor != null) { | 1840 if (lastFieldOrConstructor != null) { |
1646 return new QuickFixProcessorImpl_NewConstructorLocation( | 1841 return new _ConstructorLocation( |
1647 "${eol}${eol}", | 1842 "${eol}${eol}", |
1648 lastFieldOrConstructor.end, | 1843 lastFieldOrConstructor.end, |
1649 ""); | 1844 ""); |
1650 } | 1845 } |
1651 // at the beginning of the class | 1846 // at the beginning of the class |
1652 String suffix = members.isEmpty ? "" : eol; | 1847 String suffix = members.isEmpty ? "" : eol; |
1653 return new QuickFixProcessorImpl_NewConstructorLocation( | 1848 return new _ConstructorLocation( |
1654 eol, | 1849 eol, |
1655 classDeclaration.leftBracket.end, | 1850 classDeclaration.leftBracket.end, |
1656 suffix); | 1851 suffix); |
1657 } | 1852 } |
1658 | 1853 |
1659 /** | 1854 /** |
1660 * Removes any [ParenthesizedExpression] enclosing [expr]. | 1855 * Removes any [ParenthesizedExpression] enclosing [expr]. |
1661 * | 1856 * |
1662 * [exprPrecedence] - the effective precedence of [expr]. | 1857 * [exprPrecedence] - the effective precedence of [expr]. |
1663 */ | 1858 */ |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1721 return false; | 1916 return false; |
1722 } | 1917 } |
1723 } | 1918 } |
1724 | 1919 |
1725 | 1920 |
1726 /** | 1921 /** |
1727 * Describes the location for a newly created [ConstructorDeclaration]. | 1922 * Describes the location for a newly created [ConstructorDeclaration]. |
1728 * | 1923 * |
1729 * TODO(scheglov) rename | 1924 * TODO(scheglov) rename |
1730 */ | 1925 */ |
1731 class QuickFixProcessorImpl_NewConstructorLocation { | 1926 class _ConstructorLocation { |
1732 final String _prefix; | 1927 final String _prefix; |
1733 final int _offset; | 1928 final int _offset; |
1734 final String _suffix; | 1929 final String _suffix; |
1735 | 1930 |
1736 QuickFixProcessorImpl_NewConstructorLocation(this._prefix, this._offset, | 1931 _ConstructorLocation(this._prefix, this._offset, this._suffix); |
1737 this._suffix); | |
1738 } | 1932 } |
OLD | NEW |