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 import 'dart:async'; | 5 import 'dart:async'; |
6 import 'dart:collection'; | 6 import 'dart:collection'; |
7 import 'dart:core'; | 7 import 'dart:core'; |
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/src/protocol_server.dart' | |
12 show doSourceChange_addElementEdit, doSourceChange_addSourceEdit; | |
13 import 'package:analysis_server/src/services/completion/dart/utilities.dart'; | 11 import 'package:analysis_server/src/services/completion/dart/utilities.dart'; |
14 import 'package:analysis_server/src/services/correction/fix.dart'; | 12 import 'package:analysis_server/src/services/correction/fix.dart'; |
15 import 'package:analysis_server/src/services/correction/flutter_util.dart'; | 13 import 'package:analysis_server/src/services/correction/flutter_util.dart'; |
16 import 'package:analysis_server/src/services/correction/levenshtein.dart'; | 14 import 'package:analysis_server/src/services/correction/levenshtein.dart'; |
17 import 'package:analysis_server/src/services/correction/name_suggestion.dart'; | |
18 import 'package:analysis_server/src/services/correction/namespace.dart'; | 15 import 'package:analysis_server/src/services/correction/namespace.dart'; |
19 import 'package:analysis_server/src/services/correction/source_buffer.dart'; | |
20 import 'package:analysis_server/src/services/correction/strings.dart'; | 16 import 'package:analysis_server/src/services/correction/strings.dart'; |
21 import 'package:analysis_server/src/services/correction/util.dart'; | 17 import 'package:analysis_server/src/services/correction/util.dart'; |
22 import 'package:analysis_server/src/services/search/hierarchy.dart'; | 18 import 'package:analysis_server/src/services/search/hierarchy.dart'; |
23 import 'package:analyzer/dart/ast/ast.dart'; | 19 import 'package:analyzer/dart/ast/ast.dart'; |
24 import 'package:analyzer/dart/ast/standard_resolution_map.dart'; | 20 import 'package:analyzer/dart/ast/standard_resolution_map.dart'; |
25 import 'package:analyzer/dart/ast/token.dart'; | 21 import 'package:analyzer/dart/ast/token.dart'; |
26 import 'package:analyzer/dart/element/element.dart'; | 22 import 'package:analyzer/dart/element/element.dart'; |
27 import 'package:analyzer/dart/element/type.dart'; | 23 import 'package:analyzer/dart/element/type.dart'; |
28 import 'package:analyzer/error/error.dart'; | 24 import 'package:analyzer/error/error.dart'; |
29 import 'package:analyzer/file_system/file_system.dart'; | 25 import 'package:analyzer/file_system/file_system.dart'; |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
111 String file; | 107 String file; |
112 int fileStamp; | 108 int fileStamp; |
113 CompilationUnitElement unitElement; | 109 CompilationUnitElement unitElement; |
114 Source unitSource; | 110 Source unitSource; |
115 LibraryElement unitLibraryElement; | 111 LibraryElement unitLibraryElement; |
116 File unitLibraryFile; | 112 File unitLibraryFile; |
117 Folder unitLibraryFolder; | 113 Folder unitLibraryFolder; |
118 | 114 |
119 final List<Fix> fixes = <Fix>[]; | 115 final List<Fix> fixes = <Fix>[]; |
120 | 116 |
121 SourceChange change = new SourceChange('<message>'); | |
122 final LinkedHashMap<String, LinkedEditGroup> linkedPositionGroups = | |
123 new LinkedHashMap<String, LinkedEditGroup>(); | |
124 Position exitPosition = null; | |
125 Set<Source> librariesToImport = new Set<Source>(); | |
126 | |
127 CorrectionUtils utils; | 117 CorrectionUtils utils; |
128 int errorOffset; | 118 int errorOffset; |
129 int errorLength; | 119 int errorLength; |
130 int errorEnd; | 120 int errorEnd; |
131 SourceRange errorRange; | 121 SourceRange errorRange; |
132 AstNode node; | 122 AstNode node; |
133 AstNode coveredNode; | 123 AstNode coveredNode; |
134 | 124 |
135 TypeProvider _typeProvider; | 125 TypeProvider _typeProvider; |
136 TypeSystem _typeSystem; | 126 TypeSystem _typeSystem; |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
201 node = new NodeLocator2(errorOffset).searchWithin(unit); | 191 node = new NodeLocator2(errorOffset).searchWithin(unit); |
202 coveredNode = | 192 coveredNode = |
203 new NodeLocator2(errorOffset, errorEnd - 1).searchWithin(unit); | 193 new NodeLocator2(errorOffset, errorEnd - 1).searchWithin(unit); |
204 // analyze ErrorCode | 194 // analyze ErrorCode |
205 ErrorCode errorCode = error.errorCode; | 195 ErrorCode errorCode = error.errorCode; |
206 if (errorCode == StaticWarningCode.UNDEFINED_CLASS_BOOLEAN) { | 196 if (errorCode == StaticWarningCode.UNDEFINED_CLASS_BOOLEAN) { |
207 await _addFix_boolInsteadOfBoolean(); | 197 await _addFix_boolInsteadOfBoolean(); |
208 } | 198 } |
209 if (errorCode == | 199 if (errorCode == |
210 CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE) { | 200 CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE) { |
211 _addFix_replaceWithConstInstanceCreation(); | 201 await _addFix_replaceWithConstInstanceCreation(); |
212 } | 202 } |
213 if (errorCode == CompileTimeErrorCode.ASYNC_FOR_IN_WRONG_CONTEXT || | 203 if (errorCode == CompileTimeErrorCode.ASYNC_FOR_IN_WRONG_CONTEXT || |
214 errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER_AWAIT) { | 204 errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER_AWAIT) { |
215 await _addFix_addAsync(); | 205 await _addFix_addAsync(); |
216 } | 206 } |
217 if (errorCode == CompileTimeErrorCode.INVALID_ANNOTATION) { | 207 if (errorCode == CompileTimeErrorCode.INVALID_ANNOTATION) { |
218 if (node is Annotation) { | 208 if (node is Annotation) { |
219 Annotation annotation = node; | 209 Annotation annotation = node; |
220 Identifier name = annotation.name; | 210 Identifier name = annotation.name; |
221 if (name != null && name.staticElement == null) { | 211 if (name != null && name.staticElement == null) { |
222 node = name; | 212 node = name; |
223 if (annotation.arguments == null) { | 213 if (annotation.arguments == null) { |
224 await _addFix_importLibrary_withTopLevelVariable(); | 214 await _addFix_importLibrary_withTopLevelVariable(); |
225 } else { | 215 } else { |
226 await _addFix_importLibrary_withType(); | 216 await _addFix_importLibrary_withType(); |
227 await _addFix_createClass(); | 217 await _addFix_createClass(); |
228 _addFix_undefinedClass_useSimilar(); | 218 await _addFix_undefinedClass_useSimilar(); |
229 } | 219 } |
230 } | 220 } |
231 } | 221 } |
232 } | 222 } |
233 if (errorCode == | 223 if (errorCode == |
234 CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT) { | 224 CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT) { |
235 await _addFix_createConstructorSuperExplicit(); | 225 await _addFix_createConstructorSuperExplicit(); |
236 } | 226 } |
237 if (errorCode == | 227 if (errorCode == |
238 CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT) { | 228 CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT) { |
239 await _addFix_createConstructorSuperImplicit(); | 229 await _addFix_createConstructorSuperImplicit(); |
240 } | 230 } |
241 if (errorCode == | 231 if (errorCode == |
242 CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT) { | 232 CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT) { |
243 await _addFix_createConstructorSuperExplicit(); | 233 await _addFix_createConstructorSuperExplicit(); |
244 } | 234 } |
245 if (errorCode == CompileTimeErrorCode.URI_DOES_NOT_EXIST) { | 235 if (errorCode == CompileTimeErrorCode.URI_DOES_NOT_EXIST) { |
246 _addFix_createImportUri(); | 236 await _addFix_createImportUri(); |
247 _addFix_createPartUri(); | 237 await _addFix_createPartUri(); |
248 } | 238 } |
249 if (errorCode == HintCode.CAN_BE_NULL_AFTER_NULL_AWARE) { | 239 if (errorCode == HintCode.CAN_BE_NULL_AFTER_NULL_AWARE) { |
250 await _addFix_canBeNullAfterNullAware(); | 240 await _addFix_canBeNullAfterNullAware(); |
251 } | 241 } |
252 if (errorCode == HintCode.DEAD_CODE) { | 242 if (errorCode == HintCode.DEAD_CODE) { |
253 _addFix_removeDeadCode(); | 243 await _addFix_removeDeadCode(); |
254 } | 244 } |
255 if (errorCode == HintCode.DIVISION_OPTIMIZATION) { | 245 if (errorCode == HintCode.DIVISION_OPTIMIZATION) { |
256 _addFix_useEffectiveIntegerDivision(); | 246 await _addFix_useEffectiveIntegerDivision(); |
257 } | 247 } |
258 if (errorCode == HintCode.TYPE_CHECK_IS_NOT_NULL) { | 248 if (errorCode == HintCode.TYPE_CHECK_IS_NOT_NULL) { |
259 await _addFix_isNotNull(); | 249 await _addFix_isNotNull(); |
260 } | 250 } |
261 if (errorCode == HintCode.TYPE_CHECK_IS_NULL) { | 251 if (errorCode == HintCode.TYPE_CHECK_IS_NULL) { |
262 await _addFix_isNull(); | 252 await _addFix_isNull(); |
263 } | 253 } |
264 if (errorCode == HintCode.UNDEFINED_GETTER) { | 254 if (errorCode == HintCode.UNDEFINED_GETTER) { |
265 _addFix_undefinedClassAccessor_useSimilar(); | 255 await _addFix_undefinedClassAccessor_useSimilar(); |
266 await _addFix_createField(); | 256 await _addFix_createField(); |
267 await _addFix_createGetter(); | 257 await _addFix_createGetter(); |
268 } | 258 } |
269 if (errorCode == HintCode.UNDEFINED_SETTER) { | 259 if (errorCode == HintCode.UNDEFINED_SETTER) { |
270 _addFix_undefinedClassAccessor_useSimilar(); | 260 await _addFix_undefinedClassAccessor_useSimilar(); |
271 await _addFix_createField(); | 261 await _addFix_createField(); |
272 } | 262 } |
273 if (errorCode == HintCode.UNNECESSARY_CAST) { | 263 if (errorCode == HintCode.UNNECESSARY_CAST) { |
274 _addFix_removeUnnecessaryCast(); | 264 await _addFix_removeUnnecessaryCast(); |
275 } | 265 } |
276 if (errorCode == HintCode.UNUSED_CATCH_CLAUSE) { | 266 if (errorCode == HintCode.UNUSED_CATCH_CLAUSE) { |
277 _addFix_removeUnusedCatchClause(); | 267 await _addFix_removeUnusedCatchClause(); |
278 } | 268 } |
279 if (errorCode == HintCode.UNUSED_CATCH_STACK) { | 269 if (errorCode == HintCode.UNUSED_CATCH_STACK) { |
280 _addFix_removeUnusedCatchStack(); | 270 await _addFix_removeUnusedCatchStack(); |
281 } | 271 } |
282 if (errorCode == HintCode.UNUSED_IMPORT) { | 272 if (errorCode == HintCode.UNUSED_IMPORT) { |
283 _addFix_removeUnusedImport(); | 273 await _addFix_removeUnusedImport(); |
284 } | 274 } |
285 if (errorCode == ParserErrorCode.EXPECTED_TOKEN) { | 275 if (errorCode == ParserErrorCode.EXPECTED_TOKEN) { |
286 await _addFix_insertSemicolon(); | 276 await _addFix_insertSemicolon(); |
287 } | 277 } |
288 if (errorCode == ParserErrorCode.GETTER_WITH_PARAMETERS) { | 278 if (errorCode == ParserErrorCode.GETTER_WITH_PARAMETERS) { |
289 _addFix_removeParameters_inGetterDeclaration(); | 279 await _addFix_removeParameters_inGetterDeclaration(); |
290 } | 280 } |
291 if (errorCode == ParserErrorCode.VAR_AS_TYPE_NAME) { | 281 if (errorCode == ParserErrorCode.VAR_AS_TYPE_NAME) { |
292 _addFix_replaceVarWithDynamic(); | 282 await _addFix_replaceVarWithDynamic(); |
293 } | 283 } |
294 if (errorCode == StaticWarningCode.ASSIGNMENT_TO_FINAL) { | 284 if (errorCode == StaticWarningCode.ASSIGNMENT_TO_FINAL) { |
295 await _addFix_makeFieldNotFinal(); | 285 await _addFix_makeFieldNotFinal(); |
296 } | 286 } |
297 if (errorCode == StaticWarningCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER) { | 287 if (errorCode == StaticWarningCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER) { |
298 await _addFix_makeEnclosingClassAbstract(); | 288 await _addFix_makeEnclosingClassAbstract(); |
299 } | 289 } |
300 if (errorCode == StaticWarningCode.EXTRA_POSITIONAL_ARGUMENTS || | 290 if (errorCode == StaticWarningCode.EXTRA_POSITIONAL_ARGUMENTS || |
301 errorCode == | 291 errorCode == |
302 StaticWarningCode.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED) { | 292 StaticWarningCode.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED) { |
(...skipping 28 matching lines...) Expand all Loading... | |
331 await _addFix_createNoSuchMethod(); | 321 await _addFix_createNoSuchMethod(); |
332 // implement methods | 322 // implement methods |
333 await _addFix_createMissingOverrides(); | 323 await _addFix_createMissingOverrides(); |
334 } | 324 } |
335 if (errorCode == CompileTimeErrorCode.UNDEFINED_CLASS || | 325 if (errorCode == CompileTimeErrorCode.UNDEFINED_CLASS || |
336 errorCode == StaticWarningCode.CAST_TO_NON_TYPE || | 326 errorCode == StaticWarningCode.CAST_TO_NON_TYPE || |
337 errorCode == StaticWarningCode.TYPE_TEST_WITH_UNDEFINED_NAME || | 327 errorCode == StaticWarningCode.TYPE_TEST_WITH_UNDEFINED_NAME || |
338 errorCode == StaticWarningCode.UNDEFINED_CLASS) { | 328 errorCode == StaticWarningCode.UNDEFINED_CLASS) { |
339 await _addFix_importLibrary_withType(); | 329 await _addFix_importLibrary_withType(); |
340 await _addFix_createClass(); | 330 await _addFix_createClass(); |
341 _addFix_undefinedClass_useSimilar(); | 331 await _addFix_undefinedClass_useSimilar(); |
342 } | 332 } |
343 if (errorCode == StaticWarningCode.FINAL_NOT_INITIALIZED) { | 333 if (errorCode == StaticWarningCode.FINAL_NOT_INITIALIZED) { |
344 await _addFix_createConstructor_forUninitializedFinalFields(); | 334 await _addFix_createConstructor_forUninitializedFinalFields(); |
345 } | 335 } |
346 if (errorCode == StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1 || | 336 if (errorCode == StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1 || |
347 errorCode == StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_2 || | 337 errorCode == StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_2 || |
348 errorCode == | 338 errorCode == |
349 StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_3_PLUS) { | 339 StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_3_PLUS) { |
350 _addFix_updateConstructor_forUninitializedFinalFields(); | 340 await _addFix_updateConstructor_forUninitializedFinalFields(); |
351 } | 341 } |
352 if (errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER) { | 342 if (errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER) { |
353 _addFix_undefinedClassAccessor_useSimilar(); | 343 await _addFix_undefinedClassAccessor_useSimilar(); |
354 await _addFix_createClass(); | 344 await _addFix_createClass(); |
355 await _addFix_createField(); | 345 await _addFix_createField(); |
356 await _addFix_createGetter(); | 346 await _addFix_createGetter(); |
357 _addFix_createFunction_forFunctionType(); | 347 await _addFix_createFunction_forFunctionType(); |
358 await _addFix_importLibrary_withType(); | 348 await _addFix_importLibrary_withType(); |
359 await _addFix_importLibrary_withTopLevelVariable(); | 349 await _addFix_importLibrary_withTopLevelVariable(); |
360 await _addFix_createLocalVariable(); | 350 await _addFix_createLocalVariable(); |
361 } | 351 } |
362 if (errorCode == StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE) { | 352 if (errorCode == StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE) { |
363 await _addFix_illegalAsyncReturnType(); | 353 await _addFix_illegalAsyncReturnType(); |
364 } | 354 } |
365 if (errorCode == StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER) { | 355 if (errorCode == StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER) { |
366 _addFix_useStaticAccess_method(); | 356 await _addFix_useStaticAccess_method(); |
367 _addFix_useStaticAccess_property(); | 357 await _addFix_useStaticAccess_property(); |
368 } | 358 } |
369 if (errorCode == StaticTypeWarningCode.INVALID_ASSIGNMENT) { | 359 if (errorCode == StaticTypeWarningCode.INVALID_ASSIGNMENT) { |
370 await _addFix_changeTypeAnnotation(); | 360 await _addFix_changeTypeAnnotation(); |
371 } | 361 } |
372 if (errorCode == StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION) { | 362 if (errorCode == StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION) { |
373 _addFix_removeParentheses_inGetterInvocation(); | 363 await _addFix_removeParentheses_inGetterInvocation(); |
374 } | 364 } |
375 if (errorCode == StaticTypeWarningCode.NON_BOOL_CONDITION) { | 365 if (errorCode == StaticTypeWarningCode.NON_BOOL_CONDITION) { |
376 await _addFix_nonBoolCondition_addNotNull(); | 366 await _addFix_nonBoolCondition_addNotNull(); |
377 } | 367 } |
378 if (errorCode == StaticTypeWarningCode.NON_TYPE_AS_TYPE_ARGUMENT) { | 368 if (errorCode == StaticTypeWarningCode.NON_TYPE_AS_TYPE_ARGUMENT) { |
379 await _addFix_importLibrary_withType(); | 369 await _addFix_importLibrary_withType(); |
380 await _addFix_createClass(); | 370 await _addFix_createClass(); |
381 } | 371 } |
382 if (errorCode == StaticTypeWarningCode.UNDEFINED_FUNCTION) { | 372 if (errorCode == StaticTypeWarningCode.UNDEFINED_FUNCTION) { |
383 await _addFix_importLibrary_withFunction(); | 373 await _addFix_importLibrary_withFunction(); |
384 _addFix_undefinedFunction_useSimilar(); | 374 await _addFix_undefinedFunction_useSimilar(); |
385 _addFix_undefinedFunction_create(); | 375 await _addFix_undefinedFunction_create(); |
386 } | 376 } |
387 if (errorCode == StaticTypeWarningCode.UNDEFINED_GETTER) { | 377 if (errorCode == StaticTypeWarningCode.UNDEFINED_GETTER) { |
388 _addFix_undefinedClassAccessor_useSimilar(); | 378 await _addFix_undefinedClassAccessor_useSimilar(); |
389 await _addFix_createField(); | 379 await _addFix_createField(); |
390 await _addFix_createGetter(); | 380 await _addFix_createGetter(); |
391 _addFix_createFunction_forFunctionType(); | 381 await _addFix_createFunction_forFunctionType(); |
392 } | 382 } |
393 if (errorCode == HintCode.UNDEFINED_METHOD || | 383 if (errorCode == HintCode.UNDEFINED_METHOD || |
394 errorCode == StaticTypeWarningCode.UNDEFINED_METHOD) { | 384 errorCode == StaticTypeWarningCode.UNDEFINED_METHOD) { |
395 await _addFix_importLibrary_withFunction(); | 385 await _addFix_importLibrary_withFunction(); |
396 _addFix_undefinedMethod_useSimilar(); | 386 await _addFix_undefinedMethod_useSimilar(); |
397 _addFix_undefinedMethod_create(); | 387 await _addFix_undefinedMethod_create(); |
398 _addFix_undefinedFunction_create(); | 388 await _addFix_undefinedFunction_create(); |
399 } | 389 } |
400 if (errorCode == StaticTypeWarningCode.UNDEFINED_SETTER) { | 390 if (errorCode == StaticTypeWarningCode.UNDEFINED_SETTER) { |
401 _addFix_undefinedClassAccessor_useSimilar(); | 391 await _addFix_undefinedClassAccessor_useSimilar(); |
402 await _addFix_createField(); | 392 await _addFix_createField(); |
403 } | 393 } |
404 if (errorCode == CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER || | 394 if (errorCode == CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER || |
405 errorCode == StaticWarningCode.UNDEFINED_NAMED_PARAMETER) { | 395 errorCode == StaticWarningCode.UNDEFINED_NAMED_PARAMETER) { |
406 _addFix_convertFlutterChild(); | 396 await _addFix_convertFlutterChild(); |
407 _addFix_convertFlutterChildren(); | 397 await _addFix_convertFlutterChildren(); |
408 } | 398 } |
409 // lints | 399 // lints |
410 if (errorCode is LintCode) { | 400 if (errorCode is LintCode) { |
411 if (errorCode.name == LintNames.annotate_overrides) { | 401 if (errorCode.name == LintNames.annotate_overrides) { |
412 _addLintFixAddOverrideAnnotation(); | 402 await _addFix_addOverrideAnnotation(); |
413 } | 403 } |
414 if (errorCode.name == LintNames.avoid_annotating_with_dynamic) { | 404 if (errorCode.name == LintNames.avoid_annotating_with_dynamic) { |
415 _addFix_removeTypeName(); | 405 await _addFix_removeTypeName(); |
416 } | 406 } |
417 if (errorCode.name == LintNames.avoid_init_to_null) { | 407 if (errorCode.name == LintNames.avoid_init_to_null) { |
418 _addFix_removeInitializer(); | 408 await _addFix_removeInitializer(); |
419 } | 409 } |
420 if (errorCode.name == LintNames.avoid_return_types_on_setters) { | 410 if (errorCode.name == LintNames.avoid_return_types_on_setters) { |
421 _addFix_removeTypeName(); | 411 await _addFix_removeTypeName(); |
422 } | 412 } |
423 if (errorCode.name == LintNames.avoid_types_on_closure_parameters) { | 413 if (errorCode.name == LintNames.avoid_types_on_closure_parameters) { |
424 _addFix_replaceWithIdentifier(); | 414 await _addFix_replaceWithIdentifier(); |
425 } | 415 } |
426 if (errorCode.name == LintNames.await_only_futures) { | 416 if (errorCode.name == LintNames.await_only_futures) { |
427 _addFix_removeAwait(); | 417 await _addFix_removeAwait(); |
428 } | 418 } |
429 if (errorCode.name == LintNames.empty_statements) { | 419 if (errorCode.name == LintNames.empty_statements) { |
430 _addFix_removeEmptyStatement(); | 420 await _addFix_removeEmptyStatement(); |
431 } | 421 } |
432 if (errorCode.name == LintNames.prefer_collection_literals) { | 422 if (errorCode.name == LintNames.prefer_collection_literals) { |
433 _addFix_replaceWithLiteral(); | 423 await _addFix_replaceWithLiteral(); |
434 } | 424 } |
435 if (errorCode.name == LintNames.prefer_conditional_assignment) { | 425 if (errorCode.name == LintNames.prefer_conditional_assignment) { |
436 _addFix_replaceWithConditionalAssignment(); | 426 await _addFix_replaceWithConditionalAssignment(); |
437 } | 427 } |
438 if (errorCode.name == LintNames.unnecessary_brace_in_string_interp) { | 428 if (errorCode.name == LintNames.unnecessary_brace_in_string_interp) { |
439 _addLintRemoveInterpolationBraces(); | 429 await _addFix_removeInterpolationBraces(); |
440 } | 430 } |
441 if (errorCode.name == LintNames.unnecessary_lambdas) { | 431 if (errorCode.name == LintNames.unnecessary_lambdas) { |
442 _addFix_replaceWithTearOff(); | 432 await _addFix_replaceWithTearOff(); |
443 } | 433 } |
444 if (errorCode.name == LintNames.unnecessary_override) { | 434 if (errorCode.name == LintNames.unnecessary_override) { |
445 _addFix_removeMethodDeclaration(); | 435 await _addFix_removeMethodDeclaration(); |
446 } | 436 } |
447 if (errorCode.name == LintNames.unnecessary_this) { | 437 if (errorCode.name == LintNames.unnecessary_this) { |
448 _addFix_removeThisExpression(); | 438 await _addFix_removeThisExpression(); |
449 } | 439 } |
450 } | 440 } |
451 // done | 441 // done |
452 return fixes; | 442 return fixes; |
453 } | 443 } |
454 | 444 |
455 /** | 445 /** |
456 * Adds a new [SourceEdit] to [change]. | |
457 */ | |
458 void _addEdit(Element target, SourceEdit edit) { | |
459 if (target == null) { | |
460 target = unitElement; | |
461 } | |
462 Source source = target.source; | |
463 if (source.isInSystemLibrary) { | |
464 return; | |
465 } | |
466 doSourceChange_addElementEdit(change, target, edit); | |
467 } | |
468 | |
469 void _addFix(FixKind kind, List args, {bool importsOnly: false}) { | |
470 if (change.edits.isEmpty && !importsOnly) { | |
471 return; | |
472 } | |
473 // configure Change | |
474 change.message = formatList(kind.message, args); | |
475 linkedPositionGroups.values | |
476 .forEach((group) => change.addLinkedEditGroup(group)); | |
477 change.selection = exitPosition; | |
478 // add imports | |
479 addLibraryImports(change, unitLibraryElement, librariesToImport); | |
480 // add Fix | |
481 Fix fix = new Fix(kind, change); | |
482 fixes.add(fix); | |
483 // clear | |
484 change = new SourceChange('<message>'); | |
485 linkedPositionGroups.clear(); | |
486 exitPosition = null; | |
487 librariesToImport.clear(); | |
488 } | |
489 | |
490 /** | |
491 * Returns `true` if the `async` proposal was added. | 446 * Returns `true` if the `async` proposal was added. |
492 */ | 447 */ |
493 Future<Null> _addFix_addAsync() async { | 448 Future<Null> _addFix_addAsync() async { |
494 FunctionBody body = node.getAncestor((n) => n is FunctionBody); | 449 FunctionBody body = node.getAncestor((n) => n is FunctionBody); |
495 if (body != null && body.keyword == null) { | 450 if (body != null && body.keyword == null) { |
496 TypeProvider typeProvider = await this.typeProvider; | 451 TypeProvider typeProvider = await this.typeProvider; |
497 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); | 452 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
498 await changeBuilder.addFileEdit(file, fileStamp, | 453 await changeBuilder.addFileEdit(file, fileStamp, |
499 (DartFileEditBuilder builder) { | 454 (DartFileEditBuilder builder) { |
500 builder.convertFunctionFromSyncToAsync(body, typeProvider); | 455 builder.convertFunctionFromSyncToAsync(body, typeProvider); |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
672 builder.write(','); | 627 builder.write(','); |
673 } | 628 } |
674 }); | 629 }); |
675 }); | 630 }); |
676 _addFixFromBuilder( | 631 _addFixFromBuilder( |
677 changeBuilder, DartFixKind.ADD_MISSING_REQUIRED_ARGUMENT, | 632 changeBuilder, DartFixKind.ADD_MISSING_REQUIRED_ARGUMENT, |
678 args: [paramName]); | 633 args: [paramName]); |
679 } | 634 } |
680 } | 635 } |
681 | 636 |
637 Future<Null> _addFix_addOverrideAnnotation() async { | |
638 ClassMember member = node.getAncestor((n) => n is ClassMember); | |
639 if (member == null) { | |
640 return; | |
641 } | |
642 | |
643 //TODO(pq): migrate annotation edit building to change_builder | |
644 | |
645 // Handle doc comments. | |
646 Token token = member.beginToken; | |
647 if (token is CommentToken) { | |
648 token = (token as CommentToken).parent; | |
649 } | |
650 | |
651 Position exitPosition = new Position(file, token.offset - 1); | |
652 String indent = utils.getIndent(1); | |
653 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); | |
654 await changeBuilder.addFileEdit(file, fileStamp, | |
scheglov
2017/06/07 21:27:32
1. This code: new DartChangeBuilder(), then "addFi
| |
655 (DartFileEditBuilder builder) { | |
scheglov
2017/06/07 21:27:32
3. Consider removing DartFileEditBuilder annotatio
| |
656 builder.addSimpleReplacement( | |
657 range.startLength(token, 0), '@override$eol$indent'); | |
658 }); | |
659 changeBuilder.setSelection(exitPosition); | |
660 _addFixFromBuilder(changeBuilder, DartFixKind.LINT_ADD_OVERRIDE); | |
661 } | |
662 | |
682 Future<Null> _addFix_boolInsteadOfBoolean() async { | 663 Future<Null> _addFix_boolInsteadOfBoolean() async { |
683 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); | 664 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
684 await changeBuilder.addFileEdit(file, fileStamp, | 665 await changeBuilder.addFileEdit(file, fileStamp, |
685 (DartFileEditBuilder builder) { | 666 (DartFileEditBuilder builder) { |
686 builder.addSimpleReplacement(range.error(error), 'bool'); | 667 builder.addSimpleReplacement(range.error(error), 'bool'); |
687 }); | 668 }); |
688 _addFixFromBuilder(changeBuilder, DartFixKind.REPLACE_BOOLEAN_WITH_BOOL); | 669 _addFixFromBuilder(changeBuilder, DartFixKind.REPLACE_BOOLEAN_WITH_BOOL); |
689 } | 670 } |
690 | 671 |
691 Future<Null> _addFix_canBeNullAfterNullAware() async { | 672 Future<Null> _addFix_canBeNullAfterNullAware() async { |
(...skipping 24 matching lines...) Expand all Loading... | |
716 if (declaration is VariableDeclaration && | 697 if (declaration is VariableDeclaration && |
717 declaration.initializer == coveredNode) { | 698 declaration.initializer == coveredNode) { |
718 AstNode variableList = declaration.parent; | 699 AstNode variableList = declaration.parent; |
719 if (variableList is VariableDeclarationList && | 700 if (variableList is VariableDeclarationList && |
720 variableList.variables.length == 1) { | 701 variableList.variables.length == 1) { |
721 TypeAnnotation typeNode = variableList.type; | 702 TypeAnnotation typeNode = variableList.type; |
722 if (typeNode != null) { | 703 if (typeNode != null) { |
723 Expression initializer = coveredNode; | 704 Expression initializer = coveredNode; |
724 DartType newType = initializer.bestType; | 705 DartType newType = initializer.bestType; |
725 if (newType is InterfaceType || newType is FunctionType) { | 706 if (newType is InterfaceType || newType is FunctionType) { |
726 String newTypeSource = | |
727 utils.getTypeSource(newType, librariesToImport); | |
728 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); | 707 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
729 await changeBuilder.addFileEdit(file, fileStamp, | 708 await changeBuilder.addFileEdit(file, fileStamp, |
730 (DartFileEditBuilder builder) { | 709 (DartFileEditBuilder builder) { |
731 builder.addSimpleReplacement(range.node(typeNode), newTypeSource); | 710 builder.addReplacement(range.node(typeNode), |
711 (DartEditBuilder builder) { | |
712 builder.writeType(newType); | |
713 }); | |
732 }); | 714 }); |
733 _addFixFromBuilder( | 715 _addFixFromBuilder( |
734 changeBuilder, DartFixKind.CHANGE_TYPE_ANNOTATION, | 716 changeBuilder, DartFixKind.CHANGE_TYPE_ANNOTATION, args: [ |
735 args: [resolutionMap.typeForTypeName(typeNode), newTypeSource]); | 717 resolutionMap.typeForTypeName(typeNode), |
718 newType.displayName | |
719 ]); | |
736 } | 720 } |
737 } | 721 } |
738 } | 722 } |
739 } | 723 } |
740 } | 724 } |
741 | 725 |
742 void _addFix_convertFlutterChild() { | 726 Future<Null> _addFix_convertFlutterChild() async { |
743 NamedExpression namedExp = findFlutterNamedExpression(node, 'child'); | 727 NamedExpression namedExp = findFlutterNamedExpression(node, 'child'); |
744 if (namedExp == null) { | 728 if (namedExp == null) { |
745 return; | 729 return; |
746 } | 730 } |
747 InstanceCreationExpression childArg = getChildWidget(namedExp, false); | 731 InstanceCreationExpression childArg = getChildWidget(namedExp, false); |
748 if (childArg != null) { | 732 if (childArg != null) { |
749 convertFlutterChildToChildren( | 733 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
750 childArg, | 734 await changeBuilder.addFileEdit(file, fileStamp, |
751 namedExp, | 735 (DartFileEditBuilder builder) { |
752 eol, | 736 convertFlutterChildToChildren2( |
753 utils.getNodeText, | 737 builder, |
754 utils.getLinePrefix, | 738 childArg, |
755 utils.getIndent, | 739 namedExp, |
756 utils.getText, | 740 eol, |
757 _addInsertEdit, | 741 utils.getNodeText, |
758 _addRemoveEdit, | 742 utils.getLinePrefix, |
759 _addReplaceEdit, | 743 utils.getIndent, |
760 range.node); | 744 utils.getText, |
761 _addFix(DartFixKind.CONVERT_FLUTTER_CHILD, []); | 745 range.node); |
746 }); | |
747 _addFixFromBuilder(changeBuilder, DartFixKind.CONVERT_FLUTTER_CHILD); | |
762 return; | 748 return; |
763 } | 749 } |
764 ListLiteral listArg = getChildList(namedExp); | 750 ListLiteral listArg = getChildList(namedExp); |
765 if (listArg != null) { | 751 if (listArg != null) { |
766 _addInsertEdit(namedExp.offset + 'child'.length, 'ren'); | 752 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
767 if (listArg.typeArguments == null) { | 753 await changeBuilder.addFileEdit(file, fileStamp, |
768 _addInsertEdit(listArg.offset, '<Widget>'); | 754 (DartFileEditBuilder builder) { |
769 } | 755 builder.addSimpleInsertion(namedExp.offset + 'child'.length, 'ren'); |
770 _addFix(DartFixKind.CONVERT_FLUTTER_CHILD, []); | 756 if (listArg.typeArguments == null) { |
757 builder.addSimpleInsertion(listArg.offset, '<Widget>'); | |
758 } | |
759 }); | |
760 _addFixFromBuilder(changeBuilder, DartFixKind.CONVERT_FLUTTER_CHILD); | |
771 } | 761 } |
772 } | 762 } |
773 | 763 |
774 void _addFix_convertFlutterChildren() { | 764 Future<Null> _addFix_convertFlutterChildren() async { |
775 // TODO(messick) Implement _addFix_convertFlutterChildren() | 765 // TODO(messick) Implement _addFix_convertFlutterChildren() |
776 } | 766 } |
777 | 767 |
778 Future<Null> _addFix_createClass() async { | 768 Future<Null> _addFix_createClass() async { |
779 Element prefixElement = null; | 769 Element prefixElement = null; |
780 String name = null; | 770 String name = null; |
781 SimpleIdentifier nameNode; | 771 SimpleIdentifier nameNode; |
782 if (node is SimpleIdentifier) { | 772 if (node is SimpleIdentifier) { |
783 AstNode parent = node.parent; | 773 AstNode parent = node.parent; |
784 if (parent is PrefixedIdentifier) { | 774 if (parent is PrefixedIdentifier) { |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1032 String proposalName = _getConstructorProposalName(superConstructor); | 1022 String proposalName = _getConstructorProposalName(superConstructor); |
1033 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); | 1023 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1034 await changeBuilder.addFileEdit(file, fileStamp, | 1024 await changeBuilder.addFileEdit(file, fileStamp, |
1035 (DartFileEditBuilder builder) { | 1025 (DartFileEditBuilder builder) { |
1036 builder.addInsertion(insertOffset, (DartEditBuilder builder) { | 1026 builder.addInsertion(insertOffset, (DartEditBuilder builder) { |
1037 builder.write(prefix); | 1027 builder.write(prefix); |
1038 // add super constructor name | 1028 // add super constructor name |
1039 builder.write('super'); | 1029 builder.write('super'); |
1040 if (!isEmpty(constructorName)) { | 1030 if (!isEmpty(constructorName)) { |
1041 builder.write('.'); | 1031 builder.write('.'); |
1042 builder.write(constructorName); | 1032 builder.addSimpleLinkedEdit('NAME', constructorName); |
1043 } | 1033 } |
1044 // add arguments | 1034 // add arguments |
1045 builder.write('('); | 1035 builder.write('('); |
1046 bool firstParameter = true; | 1036 bool firstParameter = true; |
1047 for (ParameterElement parameter in superConstructor.parameters) { | 1037 for (ParameterElement parameter in superConstructor.parameters) { |
1048 // skip non-required parameters | 1038 // skip non-required parameters |
1049 if (parameter.parameterKind != ParameterKind.REQUIRED) { | 1039 if (parameter.parameterKind != ParameterKind.REQUIRED) { |
1050 break; | 1040 break; |
1051 } | 1041 } |
1052 // comma | 1042 // comma |
(...skipping 22 matching lines...) Expand all Loading... | |
1075 String targetClassName = targetClassElement.name; | 1065 String targetClassName = targetClassElement.name; |
1076 // add proposals for all super constructors | 1066 // add proposals for all super constructors |
1077 for (ConstructorElement superConstructor in superType.constructors) { | 1067 for (ConstructorElement superConstructor in superType.constructors) { |
1078 superConstructor = ConstructorMember.from(superConstructor, superType); | 1068 superConstructor = ConstructorMember.from(superConstructor, superType); |
1079 String constructorName = superConstructor.name; | 1069 String constructorName = superConstructor.name; |
1080 // skip private | 1070 // skip private |
1081 if (Identifier.isPrivateName(constructorName)) { | 1071 if (Identifier.isPrivateName(constructorName)) { |
1082 continue; | 1072 continue; |
1083 } | 1073 } |
1084 // prepare parameters and arguments | 1074 // prepare parameters and arguments |
1085 SourceBuilder parametersBuffer = new SourceBuilder.buffer(); | 1075 Iterable<ParameterElement> requiredParameters = |
1086 SourceBuilder argumentsBuffer = new SourceBuilder.buffer(); | 1076 superConstructor.parameters.where( |
1087 bool firstParameter = true; | 1077 (parameter) => parameter.parameterKind == ParameterKind.REQUIRED); |
1088 for (ParameterElement parameter in superConstructor.parameters) { | |
1089 // skip non-required parameters | |
1090 if (parameter.parameterKind != ParameterKind.REQUIRED) { | |
1091 break; | |
1092 } | |
1093 // comma | |
1094 if (firstParameter) { | |
1095 firstParameter = false; | |
1096 } else { | |
1097 parametersBuffer.append(', '); | |
1098 argumentsBuffer.append(', '); | |
1099 } | |
1100 // name | |
1101 String parameterName = parameter.displayName; | |
1102 if (parameterName.length > 1 && parameterName.startsWith('_')) { | |
1103 parameterName = parameterName.substring(1); | |
1104 } | |
1105 // parameter & argument | |
1106 _appendParameterSource(parametersBuffer, parameter.type, parameterName); | |
1107 argumentsBuffer.append(parameterName); | |
1108 } | |
1109 // add proposal | 1078 // add proposal |
1110 ClassMemberLocation targetLocation = | 1079 ClassMemberLocation targetLocation = |
1111 utils.prepareNewConstructorLocation(targetClassNode); | 1080 utils.prepareNewConstructorLocation(targetClassNode); |
1112 String proposalName = _getConstructorProposalName(superConstructor); | 1081 String proposalName = _getConstructorProposalName(superConstructor); |
1113 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); | 1082 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1114 await changeBuilder.addFileEdit(file, fileStamp, | 1083 await changeBuilder.addFileEdit(file, fileStamp, |
1115 (DartFileEditBuilder builder) { | 1084 (DartFileEditBuilder builder) { |
1116 builder.addInsertion(targetLocation.offset, (DartEditBuilder builder) { | 1085 builder.addInsertion(targetLocation.offset, (DartEditBuilder builder) { |
1086 void writeParameters(bool includeType) { | |
1087 bool firstParameter = true; | |
1088 for (ParameterElement parameter in requiredParameters) { | |
1089 if (firstParameter) { | |
1090 firstParameter = false; | |
1091 } else { | |
1092 builder.write(', '); | |
1093 } | |
1094 String parameterName = parameter.displayName; | |
1095 if (parameterName.length > 1 && parameterName.startsWith('_')) { | |
1096 parameterName = parameterName.substring(1); | |
1097 } | |
1098 if (includeType && builder.writeType(parameter.type)) { | |
1099 builder.write(' '); | |
1100 } | |
1101 builder.write(parameterName); | |
1102 } | |
1103 } | |
1104 | |
1117 builder.write(targetLocation.prefix); | 1105 builder.write(targetLocation.prefix); |
1118 builder.write(targetClassName); | 1106 builder.write(targetClassName); |
1119 if (!constructorName.isEmpty) { | 1107 if (!constructorName.isEmpty) { |
1120 builder.addSimpleLinkedEdit('NAME', '.$constructorName'); | 1108 builder.write('.'); |
1109 builder.addSimpleLinkedEdit('NAME', constructorName); | |
1121 } | 1110 } |
1122 builder.write('('); | 1111 builder.write('('); |
1123 builder.write(parametersBuffer.toString()); | 1112 writeParameters(true); |
1124 builder.write(') : super'); | 1113 builder.write(') : super'); |
1125 if (!constructorName.isEmpty) { | 1114 if (!constructorName.isEmpty) { |
1126 builder.write('.'); | 1115 builder.write('.'); |
1127 builder.write(constructorName); | 1116 builder.addSimpleLinkedEdit('NAME', constructorName); |
1128 } | 1117 } |
1129 builder.write('('); | 1118 builder.write('('); |
1130 builder.write(argumentsBuffer.toString()); | 1119 writeParameters(false); |
1131 builder.write(');'); | 1120 builder.write(');'); |
1132 builder.write(targetLocation.suffix); | 1121 builder.write(targetLocation.suffix); |
1133 }); | 1122 }); |
1134 builder.importLibraries(librariesToImport); | |
1135 }); | 1123 }); |
1136 _addFixFromBuilder(changeBuilder, DartFixKind.CREATE_CONSTRUCTOR_SUPER, | 1124 _addFixFromBuilder(changeBuilder, DartFixKind.CREATE_CONSTRUCTOR_SUPER, |
1137 args: [proposalName]); | 1125 args: [proposalName]); |
1138 } | 1126 } |
1139 } | 1127 } |
1140 | 1128 |
1141 Future<Null> _addFix_createField() async { | 1129 Future<Null> _addFix_createField() async { |
1142 if (node is! SimpleIdentifier) { | 1130 if (node is! SimpleIdentifier) { |
1143 return; | 1131 return; |
1144 } | 1132 } |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1207 isStatic: staticModifier, | 1195 isStatic: staticModifier, |
1208 nameGroupName: 'NAME', | 1196 nameGroupName: 'NAME', |
1209 type: fieldType, | 1197 type: fieldType, |
1210 typeGroupName: 'TYPE'); | 1198 typeGroupName: 'TYPE'); |
1211 builder.write(targetLocation.suffix); | 1199 builder.write(targetLocation.suffix); |
1212 }); | 1200 }); |
1213 }); | 1201 }); |
1214 _addFixFromBuilder(changeBuilder, DartFixKind.CREATE_FIELD, args: [name]); | 1202 _addFixFromBuilder(changeBuilder, DartFixKind.CREATE_FIELD, args: [name]); |
1215 } | 1203 } |
1216 | 1204 |
1217 void _addFix_createFunction_forFunctionType() { | 1205 Future<Null> _addFix_createFunction_forFunctionType() async { |
1218 if (node is SimpleIdentifier) { | 1206 if (node is SimpleIdentifier) { |
1219 SimpleIdentifier nameNode = node as SimpleIdentifier; | 1207 SimpleIdentifier nameNode = node as SimpleIdentifier; |
1220 // prepare argument expression (to get parameter) | 1208 // prepare argument expression (to get parameter) |
1221 ClassElement targetElement; | 1209 ClassElement targetElement; |
1222 Expression argument; | 1210 Expression argument; |
1223 { | 1211 { |
1224 Expression target = getQualifiedPropertyTarget(node); | 1212 Expression target = getQualifiedPropertyTarget(node); |
1225 if (target != null) { | 1213 if (target != null) { |
1226 DartType targetType = target.bestType; | 1214 DartType targetType = target.bestType; |
1227 if (targetType != null && targetType.element is ClassElement) { | 1215 if (targetType != null && targetType.element is ClassElement) { |
(...skipping 20 matching lines...) Expand all Loading... | |
1248 if (parameterType is InterfaceType && parameterType.isDartCoreFunction) { | 1236 if (parameterType is InterfaceType && parameterType.isDartCoreFunction) { |
1249 ExecutableElement element = new MethodElementImpl('', -1); | 1237 ExecutableElement element = new MethodElementImpl('', -1); |
1250 parameterType = new FunctionTypeImpl(element); | 1238 parameterType = new FunctionTypeImpl(element); |
1251 } | 1239 } |
1252 if (parameterType is! FunctionType) { | 1240 if (parameterType is! FunctionType) { |
1253 return; | 1241 return; |
1254 } | 1242 } |
1255 FunctionType functionType = parameterType as FunctionType; | 1243 FunctionType functionType = parameterType as FunctionType; |
1256 // add proposal | 1244 // add proposal |
1257 if (targetElement != null) { | 1245 if (targetElement != null) { |
1258 _addProposal_createFunction_method(targetElement, functionType); | 1246 await _addProposal_createFunction_method(targetElement, functionType); |
1259 } else { | 1247 } else { |
1260 _addProposal_createFunction_function(functionType); | 1248 await _addProposal_createFunction_function(functionType); |
1261 } | 1249 } |
1262 } | 1250 } |
1263 } | 1251 } |
1264 | 1252 |
1265 Future<Null> _addFix_createGetter() async { | 1253 Future<Null> _addFix_createGetter() async { |
1266 if (node is! SimpleIdentifier) { | 1254 if (node is! SimpleIdentifier) { |
1267 return; | 1255 return; |
1268 } | 1256 } |
1269 SimpleIdentifier nameNode = node; | 1257 SimpleIdentifier nameNode = node; |
1270 String name = nameNode.name; | 1258 String name = nameNode.name; |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1331 isStatic: staticModifier, | 1319 isStatic: staticModifier, |
1332 nameGroupName: 'NAME', | 1320 nameGroupName: 'NAME', |
1333 returnType: fieldType, | 1321 returnType: fieldType, |
1334 returnTypeGroupName: 'TYPE'); | 1322 returnTypeGroupName: 'TYPE'); |
1335 builder.write(targetLocation.suffix); | 1323 builder.write(targetLocation.suffix); |
1336 }); | 1324 }); |
1337 }); | 1325 }); |
1338 _addFixFromBuilder(changeBuilder, DartFixKind.CREATE_GETTER, args: [name]); | 1326 _addFixFromBuilder(changeBuilder, DartFixKind.CREATE_GETTER, args: [name]); |
1339 } | 1327 } |
1340 | 1328 |
1341 void _addFix_createImportUri() { | 1329 Future<Null> _addFix_createImportUri() async { |
1342 // TODO(brianwilkerson) Generalize this to allow other valid string literals . | 1330 // TODO(brianwilkerson) Generalize this to allow other valid string literals . |
1343 // TODO(brianwilkerson) Support the case where the node's parent is a Config uration. | 1331 // TODO(brianwilkerson) Support the case where the node's parent is a Config uration. |
1344 if (node is SimpleStringLiteral && node.parent is ImportDirective) { | 1332 if (node is SimpleStringLiteral && node.parent is ImportDirective) { |
1345 ImportDirective importDirective = node.parent; | 1333 ImportDirective importDirective = node.parent; |
1346 Source source = importDirective.uriSource; | 1334 Source source = importDirective.uriSource; |
1347 if (source != null) { | 1335 if (source != null) { |
1348 String file = source.fullName; | 1336 String file = source.fullName; |
1349 if (isAbsolute(file) && AnalysisEngine.isDartFileName(file)) { | 1337 if (isAbsolute(file) && AnalysisEngine.isDartFileName(file)) { |
1350 String libName = _computeLibraryName(file); | 1338 String libName = _computeLibraryName(file); |
1351 SourceEdit edit = new SourceEdit(0, 0, 'library $libName;$eol$eol'); | 1339 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1352 doSourceChange_addSourceEdit(change, source, edit, isNewFile: true); | 1340 await changeBuilder.addFileEdit(source.fullName, -1, |
1353 _addFix(DartFixKind.CREATE_FILE, [source.shortName]); | 1341 (DartFileEditBuilder builder) { |
1342 builder.addSimpleInsertion(0, 'library $libName;$eol$eol'); | |
1343 }); | |
1344 _addFixFromBuilder(changeBuilder, DartFixKind.CREATE_FILE, | |
1345 args: [source.shortName]); | |
1354 } | 1346 } |
1355 } | 1347 } |
1356 } | 1348 } |
1357 } | 1349 } |
1358 | 1350 |
1359 Future<Null> _addFix_createLocalVariable() async { | 1351 Future<Null> _addFix_createLocalVariable() async { |
1360 if (node is! SimpleIdentifier) { | 1352 if (node is! SimpleIdentifier) { |
1361 return; | 1353 return; |
1362 } | 1354 } |
1363 SimpleIdentifier nameNode = node; | 1355 SimpleIdentifier nameNode = node; |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1568 // append method | 1560 // append method |
1569 builder.write(prefix); | 1561 builder.write(prefix); |
1570 builder.write( | 1562 builder.write( |
1571 'noSuchMethod(Invocation invocation) => super.noSuchMethod(invocatio n);'); | 1563 'noSuchMethod(Invocation invocation) => super.noSuchMethod(invocatio n);'); |
1572 builder.write(eol); | 1564 builder.write(eol); |
1573 }); | 1565 }); |
1574 }); | 1566 }); |
1575 _addFixFromBuilder(changeBuilder, DartFixKind.CREATE_NO_SUCH_METHOD); | 1567 _addFixFromBuilder(changeBuilder, DartFixKind.CREATE_NO_SUCH_METHOD); |
1576 } | 1568 } |
1577 | 1569 |
1578 void _addFix_createPartUri() { | 1570 Future<Null> _addFix_createPartUri() async { |
1579 // TODO(brianwilkerson) Generalize this to allow other valid string literals . | 1571 // TODO(brianwilkerson) Generalize this to allow other valid string literals . |
1580 if (node is SimpleStringLiteral && node.parent is PartDirective) { | 1572 if (node is SimpleStringLiteral && node.parent is PartDirective) { |
1581 PartDirective partDirective = node.parent; | 1573 PartDirective partDirective = node.parent; |
1582 Source source = partDirective.uriSource; | 1574 Source source = partDirective.uriSource; |
1583 if (source != null) { | 1575 if (source != null) { |
1584 String libName = unitLibraryElement.name; | 1576 String libName = unitLibraryElement.name; |
1585 SourceEdit edit = new SourceEdit(0, 0, 'part of $libName;$eol$eol'); | 1577 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1586 doSourceChange_addSourceEdit(change, source, edit, isNewFile: true); | 1578 await changeBuilder.addFileEdit(source.fullName, -1, |
1587 _addFix(DartFixKind.CREATE_FILE, [source.shortName]); | 1579 (DartFileEditBuilder builder) { |
1580 // TODO(brianwilkerson) Consider using the URI rather than name | |
1581 builder.addSimpleInsertion(0, 'part of $libName;$eol$eol'); | |
1582 }); | |
1583 _addFixFromBuilder(changeBuilder, DartFixKind.CREATE_FILE, | |
1584 args: [source.shortName]); | |
1588 } | 1585 } |
1589 } | 1586 } |
1590 } | 1587 } |
1591 | 1588 |
1592 Future<Null> _addFix_illegalAsyncReturnType() async { | 1589 Future<Null> _addFix_illegalAsyncReturnType() async { |
1593 // prepare the existing type | 1590 // prepare the existing type |
1594 TypeAnnotation typeName = node.getAncestor((n) => n is TypeAnnotation); | 1591 TypeAnnotation typeName = node.getAncestor((n) => n is TypeAnnotation); |
1595 TypeProvider typeProvider = this.typeProvider; | 1592 TypeProvider typeProvider = this.typeProvider; |
1596 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); | 1593 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1597 await changeBuilder.addFileEdit(file, fileStamp, | 1594 await changeBuilder.addFileEdit(file, fileStamp, |
1598 (DartFileEditBuilder builder) { | 1595 (DartFileEditBuilder builder) { |
1599 builder.replaceTypeWithFuture(typeName, typeProvider); | 1596 builder.replaceTypeWithFuture(typeName, typeProvider); |
1600 }); | 1597 }); |
1601 _addFixFromBuilder(changeBuilder, DartFixKind.REPLACE_RETURN_TYPE_FUTURE); | 1598 _addFixFromBuilder(changeBuilder, DartFixKind.REPLACE_RETURN_TYPE_FUTURE); |
1602 } | 1599 } |
1603 | 1600 |
1604 void _addFix_importLibrary(FixKind kind, Source library) { | 1601 Future<Null> _addFix_importLibrary(FixKind kind, Source library) async { |
1605 librariesToImport.add(library); | |
1606 String libraryUri = getLibrarySourceUri(unitLibraryElement, library); | 1602 String libraryUri = getLibrarySourceUri(unitLibraryElement, library); |
1607 _addFix(kind, [libraryUri], importsOnly: true); | 1603 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1604 await changeBuilder.addFileEdit(file, fileStamp, | |
1605 (DartFileEditBuilder builder) { | |
1606 builder.importLibraries([library]); | |
1607 }); | |
1608 _addFixFromBuilder(changeBuilder, kind, args: [libraryUri]); | |
1608 } | 1609 } |
1609 | 1610 |
1610 Future<Null> _addFix_importLibrary_withElement(String name, | 1611 Future<Null> _addFix_importLibrary_withElement(String name, |
1611 List<ElementKind> elementKinds, TopLevelDeclarationKind kind2) async { | 1612 List<ElementKind> elementKinds, TopLevelDeclarationKind kind2) async { |
1612 // ignore if private | 1613 // ignore if private |
1613 if (name.startsWith('_')) { | 1614 if (name.startsWith('_')) { |
1614 return; | 1615 return; |
1615 } | 1616 } |
1616 // may be there is an existing import, | 1617 // may be there is an existing import, |
1617 // but it is with prefix and we don't use this prefix | 1618 // but it is with prefix and we don't use this prefix |
1618 Set<Source> alreadyImportedWithPrefix = new Set<Source>(); | 1619 Set<Source> alreadyImportedWithPrefix = new Set<Source>(); |
1619 for (ImportElement imp in unitLibraryElement.imports) { | 1620 for (ImportElement imp in unitLibraryElement.imports) { |
1620 // prepare element | 1621 // prepare element |
1621 LibraryElement libraryElement = imp.importedLibrary; | 1622 LibraryElement libraryElement = imp.importedLibrary; |
1622 Element element = getExportedElement(libraryElement, name); | 1623 Element element = getExportedElement(libraryElement, name); |
1623 if (element == null) { | 1624 if (element == null) { |
1624 continue; | 1625 continue; |
1625 } | 1626 } |
1626 if (element is PropertyAccessorElement) { | 1627 if (element is PropertyAccessorElement) { |
1627 element = (element as PropertyAccessorElement).variable; | 1628 element = (element as PropertyAccessorElement).variable; |
1628 } | 1629 } |
1629 if (!elementKinds.contains(element.kind)) { | 1630 if (!elementKinds.contains(element.kind)) { |
1630 continue; | 1631 continue; |
1631 } | 1632 } |
1632 // may be apply prefix | 1633 // may be apply prefix |
1633 PrefixElement prefix = imp.prefix; | 1634 PrefixElement prefix = imp.prefix; |
1634 if (prefix != null) { | 1635 if (prefix != null) { |
1635 _addReplaceEdit(range.startLength(node, 0), '${prefix.displayName}.'); | 1636 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1636 _addFix(DartFixKind.IMPORT_LIBRARY_PREFIX, | 1637 await changeBuilder.addFileEdit(file, fileStamp, |
1637 [libraryElement.displayName, prefix.displayName]); | 1638 (DartFileEditBuilder builder) { |
1639 builder.addSimpleReplacement( | |
1640 range.startLength(node, 0), '${prefix.displayName}.'); | |
1641 }); | |
1642 _addFixFromBuilder(changeBuilder, DartFixKind.IMPORT_LIBRARY_PREFIX, | |
1643 args: [libraryElement.displayName, prefix.displayName]); | |
1638 continue; | 1644 continue; |
1639 } | 1645 } |
1640 // may be update "show" directive | 1646 // may be update "show" directive |
1641 List<NamespaceCombinator> combinators = imp.combinators; | 1647 List<NamespaceCombinator> combinators = imp.combinators; |
1642 if (combinators.length == 1 && combinators[0] is ShowElementCombinator) { | 1648 if (combinators.length == 1 && combinators[0] is ShowElementCombinator) { |
1643 ShowElementCombinator showCombinator = | 1649 ShowElementCombinator showCombinator = |
1644 combinators[0] as ShowElementCombinator; | 1650 combinators[0] as ShowElementCombinator; |
1645 // prepare new set of names to show | 1651 // prepare new set of names to show |
1646 Set<String> showNames = new SplayTreeSet<String>(); | 1652 Set<String> showNames = new SplayTreeSet<String>(); |
1647 showNames.addAll(showCombinator.shownNames); | 1653 showNames.addAll(showCombinator.shownNames); |
1648 showNames.add(name); | 1654 showNames.add(name); |
1649 // prepare library name - unit name or 'dart:name' for SDK library | 1655 // prepare library name - unit name or 'dart:name' for SDK library |
1650 String libraryName = libraryElement.definingCompilationUnit.displayName; | 1656 String libraryName = libraryElement.definingCompilationUnit.displayName; |
1651 if (libraryElement.isInSdk) { | 1657 if (libraryElement.isInSdk) { |
1652 libraryName = imp.uri; | 1658 libraryName = imp.uri; |
1653 } | 1659 } |
1654 // don't add this library again | 1660 // don't add this library again |
1655 alreadyImportedWithPrefix.add(libraryElement.source); | 1661 alreadyImportedWithPrefix.add(libraryElement.source); |
1656 // update library | 1662 // update library |
1657 String newShowCode = 'show ${showNames.join(', ')}'; | 1663 String newShowCode = 'show ${showNames.join(', ')}'; |
1658 int offset = showCombinator.offset; | 1664 int offset = showCombinator.offset; |
1659 int length = showCombinator.end - offset; | 1665 int length = showCombinator.end - offset; |
1660 _addReplaceEdit( | 1666 String libraryFile = unitLibraryElement.source.fullName; |
1661 new SourceRange(offset, length), newShowCode, unitLibraryElement); | 1667 int libraryStamp = unitLibraryElement.context |
1662 _addFix(DartFixKind.IMPORT_LIBRARY_SHOW, [libraryName]); | 1668 .getModificationStamp(unitLibraryElement.source); |
1669 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); | |
1670 await changeBuilder.addFileEdit(libraryFile, libraryStamp, | |
1671 (DartFileEditBuilder builder) { | |
1672 builder.addSimpleReplacement( | |
1673 new SourceRange(offset, length), newShowCode); | |
1674 }); | |
1675 _addFixFromBuilder(changeBuilder, DartFixKind.IMPORT_LIBRARY_SHOW, | |
1676 args: [libraryName]); | |
1663 } | 1677 } |
1664 } | 1678 } |
1665 // Find new top-level declarations. | 1679 // Find new top-level declarations. |
1666 { | 1680 { |
1667 List<TopLevelDeclarationInSource> declarations = | 1681 List<TopLevelDeclarationInSource> declarations = |
1668 await getTopLevelDeclarations(name); | 1682 await getTopLevelDeclarations(name); |
1669 for (TopLevelDeclarationInSource declaration in declarations) { | 1683 for (TopLevelDeclarationInSource declaration in declarations) { |
1670 // Check the kind. | 1684 // Check the kind. |
1671 if (declaration.declaration.kind != kind2) { | 1685 if (declaration.declaration.kind != kind2) { |
1672 continue; | 1686 continue; |
(...skipping 14 matching lines...) Expand all Loading... | |
1687 // Bad: non-API. | 1701 // Bad: non-API. |
1688 fixKind = DartFixKind.IMPORT_LIBRARY_PROJECT3; | 1702 fixKind = DartFixKind.IMPORT_LIBRARY_PROJECT3; |
1689 } else if (declaration.isExported) { | 1703 } else if (declaration.isExported) { |
1690 // Ugly: exports. | 1704 // Ugly: exports. |
1691 fixKind = DartFixKind.IMPORT_LIBRARY_PROJECT2; | 1705 fixKind = DartFixKind.IMPORT_LIBRARY_PROJECT2; |
1692 } else { | 1706 } else { |
1693 // Good: direct declaration. | 1707 // Good: direct declaration. |
1694 fixKind = DartFixKind.IMPORT_LIBRARY_PROJECT1; | 1708 fixKind = DartFixKind.IMPORT_LIBRARY_PROJECT1; |
1695 } | 1709 } |
1696 // Add the fix. | 1710 // Add the fix. |
1697 _addFix_importLibrary(fixKind, librarySource); | 1711 await _addFix_importLibrary(fixKind, librarySource); |
1698 } | 1712 } |
1699 } | 1713 } |
1700 } | 1714 } |
1701 | 1715 |
1702 Future<Null> _addFix_importLibrary_withFunction() async { | 1716 Future<Null> _addFix_importLibrary_withFunction() async { |
1703 if (node is SimpleIdentifier && node.parent is MethodInvocation) { | 1717 if (node is SimpleIdentifier && node.parent is MethodInvocation) { |
1704 MethodInvocation invocation = node.parent as MethodInvocation; | 1718 MethodInvocation invocation = node.parent as MethodInvocation; |
1705 if (invocation.realTarget == null && invocation.methodName == node) { | 1719 if (invocation.realTarget == null && invocation.methodName == node) { |
1706 String name = (node as SimpleIdentifier).name; | 1720 String name = (node as SimpleIdentifier).name; |
1707 await _addFix_importLibrary_withElement(name, | 1721 await _addFix_importLibrary_withElement(name, |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1839 | 1853 |
1840 Future<Null> _addFix_nonBoolCondition_addNotNull() async { | 1854 Future<Null> _addFix_nonBoolCondition_addNotNull() async { |
1841 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); | 1855 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1842 await changeBuilder.addFileEdit(file, fileStamp, | 1856 await changeBuilder.addFileEdit(file, fileStamp, |
1843 (DartFileEditBuilder builder) { | 1857 (DartFileEditBuilder builder) { |
1844 builder.addSimpleInsertion(error.offset + error.length, ' != null'); | 1858 builder.addSimpleInsertion(error.offset + error.length, ' != null'); |
1845 }); | 1859 }); |
1846 _addFixFromBuilder(changeBuilder, DartFixKind.ADD_NE_NULL); | 1860 _addFixFromBuilder(changeBuilder, DartFixKind.ADD_NE_NULL); |
1847 } | 1861 } |
1848 | 1862 |
1849 void _addFix_removeAwait() { | 1863 Future<Null> _addFix_removeAwait() async { |
1850 final awaitExpression = node; | 1864 final awaitExpression = node; |
1851 if (awaitExpression is AwaitExpression) { | 1865 if (awaitExpression is AwaitExpression) { |
1852 final awaitToken = awaitExpression.awaitKeyword; | 1866 final awaitToken = awaitExpression.awaitKeyword; |
1853 _addRemoveEdit(range.startStart(awaitToken, awaitToken.next)); | 1867 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1854 _addFix(DartFixKind.REMOVE_AWAIT, []); | 1868 await changeBuilder.addFileEdit(file, fileStamp, |
1869 (DartFileEditBuilder builder) { | |
1870 builder.addDeletion(range.startStart(awaitToken, awaitToken.next)); | |
1871 }); | |
1872 _addFixFromBuilder(changeBuilder, DartFixKind.REMOVE_AWAIT); | |
1855 } | 1873 } |
1856 } | 1874 } |
1857 | 1875 |
1858 void _addFix_removeDeadCode() { | 1876 Future<Null> _addFix_removeDeadCode() async { |
1859 AstNode coveringNode = this.coveredNode; | 1877 AstNode coveringNode = this.coveredNode; |
1860 if (coveringNode is Expression) { | 1878 if (coveringNode is Expression) { |
1861 AstNode parent = coveredNode.parent; | 1879 AstNode parent = coveredNode.parent; |
1862 if (parent is BinaryExpression) { | 1880 if (parent is BinaryExpression) { |
1863 if (parent.rightOperand == coveredNode) { | 1881 if (parent.rightOperand == coveredNode) { |
1864 _addRemoveEdit(range.endEnd(parent.leftOperand, coveredNode)); | 1882 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1865 _addFix(DartFixKind.REMOVE_DEAD_CODE, []); | 1883 await changeBuilder.addFileEdit(file, fileStamp, |
1884 (DartFileEditBuilder builder) { | |
1885 builder.addDeletion(range.endEnd(parent.leftOperand, coveredNode)); | |
1886 }); | |
1887 _addFixFromBuilder(changeBuilder, DartFixKind.REMOVE_DEAD_CODE); | |
1866 } | 1888 } |
1867 } | 1889 } |
1868 } else if (coveringNode is Block) { | 1890 } else if (coveringNode is Block) { |
1869 Block block = coveringNode; | 1891 Block block = coveringNode; |
1870 List<Statement> statementsToRemove = <Statement>[]; | 1892 List<Statement> statementsToRemove = <Statement>[]; |
1871 for (Statement statement in block.statements) { | 1893 for (Statement statement in block.statements) { |
1872 if (range.node(statement).intersects(errorRange)) { | 1894 if (range.node(statement).intersects(errorRange)) { |
1873 statementsToRemove.add(statement); | 1895 statementsToRemove.add(statement); |
1874 } | 1896 } |
1875 } | 1897 } |
1876 if (statementsToRemove.isNotEmpty) { | 1898 if (statementsToRemove.isNotEmpty) { |
1877 SourceRange rangeToRemove = | 1899 SourceRange rangeToRemove = |
1878 utils.getLinesRangeStatements(statementsToRemove); | 1900 utils.getLinesRangeStatements(statementsToRemove); |
1879 _addRemoveEdit(rangeToRemove); | 1901 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1880 _addFix(DartFixKind.REMOVE_DEAD_CODE, []); | 1902 await changeBuilder.addFileEdit(file, fileStamp, |
1903 (DartFileEditBuilder builder) { | |
1904 builder.addDeletion(rangeToRemove); | |
1905 }); | |
1906 _addFixFromBuilder(changeBuilder, DartFixKind.REMOVE_DEAD_CODE); | |
1881 } | 1907 } |
1882 } else if (coveringNode is Statement) { | 1908 } else if (coveringNode is Statement) { |
1883 SourceRange rangeToRemove = | 1909 SourceRange rangeToRemove = |
1884 utils.getLinesRangeStatements(<Statement>[coveringNode]); | 1910 utils.getLinesRangeStatements(<Statement>[coveringNode]); |
1885 _addRemoveEdit(rangeToRemove); | 1911 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1886 _addFix(DartFixKind.REMOVE_DEAD_CODE, []); | 1912 await changeBuilder.addFileEdit(file, fileStamp, |
1913 (DartFileEditBuilder builder) { | |
1914 builder.addDeletion(rangeToRemove); | |
1915 }); | |
1916 _addFixFromBuilder(changeBuilder, DartFixKind.REMOVE_DEAD_CODE); | |
1887 } | 1917 } |
1888 } | 1918 } |
1889 | 1919 |
1890 void _addFix_removeEmptyStatement() { | 1920 Future<Null> _addFix_removeEmptyStatement() async { |
1891 EmptyStatement emptyStatement = node; | 1921 EmptyStatement emptyStatement = node; |
1892 if (emptyStatement.parent is Block) { | 1922 if (emptyStatement.parent is Block) { |
1893 _addRemoveEdit(utils.getLinesRange(range.node(emptyStatement))); | 1923 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1894 _addFix(DartFixKind.REMOVE_EMPTY_STATEMENT, []); | 1924 await changeBuilder.addFileEdit(file, fileStamp, |
1925 (DartFileEditBuilder builder) { | |
1926 builder.addDeletion(utils.getLinesRange(range.node(emptyStatement))); | |
1927 }); | |
1928 _addFixFromBuilder(changeBuilder, DartFixKind.REMOVE_EMPTY_STATEMENT); | |
1895 } else { | 1929 } else { |
1896 _addReplaceEdit( | 1930 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1897 range.endEnd(emptyStatement.beginToken.previous, emptyStatement), | 1931 await changeBuilder.addFileEdit(file, fileStamp, |
1898 ' {}'); | 1932 (DartFileEditBuilder builder) { |
1899 _addFix(DartFixKind.REPLACE_WITH_BRACKETS, []); | 1933 builder.addSimpleReplacement( |
1934 range.endEnd(emptyStatement.beginToken.previous, emptyStatement), | |
1935 ' {}'); | |
1936 }); | |
1937 _addFixFromBuilder(changeBuilder, DartFixKind.REPLACE_WITH_BRACKETS); | |
1900 } | 1938 } |
1901 } | 1939 } |
1902 | 1940 |
1903 void _addFix_removeInitializer() { | 1941 Future<Null> _addFix_removeInitializer() async { |
1904 // Retrieve the linted node. | 1942 // Retrieve the linted node. |
1905 VariableDeclaration ancestor = | 1943 VariableDeclaration ancestor = |
1906 node.getAncestor((a) => a is VariableDeclaration); | 1944 node.getAncestor((a) => a is VariableDeclaration); |
1907 if (ancestor == null) { | 1945 if (ancestor == null) { |
1908 return; | 1946 return; |
1909 } | 1947 } |
1910 _addRemoveEdit(range.endEnd(ancestor.name, ancestor.initializer)); | 1948 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1911 _addFix(DartFixKind.REMOVE_INITIALIZER, []); | 1949 await changeBuilder.addFileEdit(file, fileStamp, |
1950 (DartFileEditBuilder builder) { | |
1951 builder.addDeletion(range.endEnd(ancestor.name, ancestor.initializer)); | |
1952 }); | |
1953 _addFixFromBuilder(changeBuilder, DartFixKind.REMOVE_INITIALIZER); | |
1912 } | 1954 } |
1913 | 1955 |
1914 void _addFix_removeMethodDeclaration() { | 1956 Future<Null> _addFix_removeInterpolationBraces() async { |
1957 AstNode node = this.node; | |
1958 if (node is InterpolationExpression) { | |
1959 Token right = node.rightBracket; | |
1960 if (node.expression != null && right != null) { | |
1961 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); | |
1962 await changeBuilder.addFileEdit(file, fileStamp, | |
1963 (DartFileEditBuilder builder) { | |
1964 builder.addSimpleReplacement( | |
1965 range.startStart(node, node.expression), r'$'); | |
1966 builder.addDeletion(range.token(right)); | |
1967 }); | |
1968 _addFixFromBuilder( | |
1969 changeBuilder, DartFixKind.LINT_REMOVE_INTERPOLATION_BRACES); | |
1970 } else {} | |
1971 } | |
1972 } | |
1973 | |
1974 Future<Null> _addFix_removeMethodDeclaration() async { | |
1915 MethodDeclaration declaration = | 1975 MethodDeclaration declaration = |
1916 node.getAncestor((node) => node is MethodDeclaration); | 1976 node.getAncestor((node) => node is MethodDeclaration); |
1917 if (declaration != null) { | 1977 if (declaration != null) { |
1918 _addRemoveEdit(utils.getLinesRange(range.node(declaration))); | 1978 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1919 _addFix(DartFixKind.REMOVE_METHOD_DECLARATION, []); | 1979 await changeBuilder.addFileEdit(file, fileStamp, |
1980 (DartFileEditBuilder builder) { | |
1981 builder.addDeletion(utils.getLinesRange(range.node(declaration))); | |
1982 }); | |
1983 _addFixFromBuilder(changeBuilder, DartFixKind.REMOVE_METHOD_DECLARATION); | |
1920 } | 1984 } |
1921 } | 1985 } |
1922 | 1986 |
1923 void _addFix_removeParameters_inGetterDeclaration() { | 1987 Future<Null> _addFix_removeParameters_inGetterDeclaration() async { |
1924 if (node is MethodDeclaration) { | 1988 if (node is MethodDeclaration) { |
1925 MethodDeclaration method = node as MethodDeclaration; | 1989 MethodDeclaration method = node as MethodDeclaration; |
1926 SimpleIdentifier name = method.name; | 1990 SimpleIdentifier name = method.name; |
1927 FunctionBody body = method.body; | 1991 FunctionBody body = method.body; |
1928 if (name != null && body != null) { | 1992 if (name != null && body != null) { |
1929 _addReplaceEdit(range.endStart(name, body), ' '); | 1993 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1930 _addFix(DartFixKind.REMOVE_PARAMETERS_IN_GETTER_DECLARATION, []); | 1994 await changeBuilder.addFileEdit(file, fileStamp, |
1995 (DartFileEditBuilder builder) { | |
1996 builder.addSimpleReplacement(range.endStart(name, body), ' '); | |
1997 }); | |
1998 _addFixFromBuilder( | |
1999 changeBuilder, DartFixKind.REMOVE_PARAMETERS_IN_GETTER_DECLARATION); | |
1931 } | 2000 } |
1932 } | 2001 } |
1933 } | 2002 } |
1934 | 2003 |
1935 void _addFix_removeParentheses_inGetterInvocation() { | 2004 Future<Null> _addFix_removeParentheses_inGetterInvocation() async { |
1936 if (node is SimpleIdentifier && node.parent is MethodInvocation) { | 2005 if (node is SimpleIdentifier && node.parent is MethodInvocation) { |
1937 MethodInvocation invocation = node.parent as MethodInvocation; | 2006 MethodInvocation invocation = node.parent as MethodInvocation; |
1938 if (invocation.methodName == node && invocation.target != null) { | 2007 if (invocation.methodName == node && invocation.target != null) { |
1939 _addRemoveEdit(range.endEnd(node, invocation)); | 2008 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1940 _addFix(DartFixKind.REMOVE_PARENTHESIS_IN_GETTER_INVOCATION, []); | 2009 await changeBuilder.addFileEdit(file, fileStamp, |
2010 (DartFileEditBuilder builder) { | |
2011 builder.addDeletion(range.endEnd(node, invocation)); | |
2012 }); | |
2013 _addFixFromBuilder( | |
2014 changeBuilder, DartFixKind.REMOVE_PARENTHESIS_IN_GETTER_INVOCATION); | |
1941 } | 2015 } |
1942 } | 2016 } |
1943 } | 2017 } |
1944 | 2018 |
1945 void _addFix_removeThisExpression() { | 2019 Future<Null> _addFix_removeThisExpression() async { |
1946 final thisExpression = node is ThisExpression | 2020 final thisExpression = node is ThisExpression |
1947 ? node | 2021 ? node |
1948 : node.getAncestor((node) => node is ThisExpression); | 2022 : node.getAncestor((node) => node is ThisExpression); |
1949 final parent = thisExpression.parent; | 2023 final parent = thisExpression.parent; |
1950 if (parent is PropertyAccess) { | 2024 if (parent is PropertyAccess) { |
1951 _addRemoveEdit(range.startEnd(parent, parent.operator)); | 2025 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1952 _addFix(DartFixKind.REMOVE_THIS_EXPRESSION, []); | 2026 await changeBuilder.addFileEdit(file, fileStamp, |
2027 (DartFileEditBuilder builder) { | |
2028 builder.addDeletion(range.startEnd(parent, parent.operator)); | |
2029 }); | |
2030 _addFixFromBuilder(changeBuilder, DartFixKind.REMOVE_THIS_EXPRESSION); | |
1953 } else if (parent is MethodInvocation) { | 2031 } else if (parent is MethodInvocation) { |
1954 _addRemoveEdit(range.startEnd(parent, parent.operator)); | 2032 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1955 _addFix(DartFixKind.REMOVE_THIS_EXPRESSION, []); | 2033 await changeBuilder.addFileEdit(file, fileStamp, |
2034 (DartFileEditBuilder builder) { | |
2035 builder.addDeletion(range.startEnd(parent, parent.operator)); | |
2036 }); | |
2037 _addFixFromBuilder(changeBuilder, DartFixKind.REMOVE_THIS_EXPRESSION); | |
1956 } | 2038 } |
1957 } | 2039 } |
1958 | 2040 |
1959 void _addFix_removeTypeName() { | 2041 Future<Null> _addFix_removeTypeName() async { |
1960 final TypeName type = node.getAncestor((node) => node is TypeName); | 2042 final TypeName type = node.getAncestor((node) => node is TypeName); |
1961 if (type != null) { | 2043 if (type != null) { |
1962 _addRemoveEdit(range.startStart(type, type.endToken.next)); | 2044 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1963 _addFix(DartFixKind.REMOVE_TYPE_NAME, []); | 2045 await changeBuilder.addFileEdit(file, fileStamp, |
2046 (DartFileEditBuilder builder) { | |
2047 builder.addDeletion(range.startStart(type, type.endToken.next)); | |
2048 }); | |
2049 _addFixFromBuilder(changeBuilder, DartFixKind.REMOVE_TYPE_NAME); | |
1964 } | 2050 } |
1965 } | 2051 } |
1966 | 2052 |
1967 void _addFix_removeUnnecessaryCast() { | 2053 Future<Null> _addFix_removeUnnecessaryCast() async { |
1968 if (coveredNode is! AsExpression) { | 2054 if (coveredNode is! AsExpression) { |
1969 return; | 2055 return; |
1970 } | 2056 } |
1971 AsExpression asExpression = coveredNode as AsExpression; | 2057 AsExpression asExpression = coveredNode as AsExpression; |
1972 Expression expression = asExpression.expression; | 2058 Expression expression = asExpression.expression; |
1973 int expressionPrecedence = getExpressionPrecedence(expression); | 2059 int expressionPrecedence = getExpressionPrecedence(expression); |
1974 // remove 'as T' from 'e as T' | 2060 // remove 'as T' from 'e as T' |
1975 _addRemoveEdit(range.endEnd(expression, asExpression)); | 2061 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1976 _removeEnclosingParentheses(asExpression, expressionPrecedence); | 2062 await changeBuilder.addFileEdit(file, fileStamp, |
1977 // done | 2063 (DartFileEditBuilder builder) { |
1978 _addFix(DartFixKind.REMOVE_UNNECESSARY_CAST, []); | 2064 builder.addDeletion(range.endEnd(expression, asExpression)); |
2065 _removeEnclosingParentheses(builder, asExpression, expressionPrecedence); | |
2066 }); | |
2067 _addFixFromBuilder(changeBuilder, DartFixKind.REMOVE_UNNECESSARY_CAST); | |
1979 } | 2068 } |
1980 | 2069 |
1981 void _addFix_removeUnusedCatchClause() { | 2070 Future<Null> _addFix_removeUnusedCatchClause() async { |
1982 if (node is SimpleIdentifier) { | 2071 if (node is SimpleIdentifier) { |
1983 AstNode catchClause = node.parent; | 2072 AstNode catchClause = node.parent; |
1984 if (catchClause is CatchClause && | 2073 if (catchClause is CatchClause && |
1985 catchClause.exceptionParameter == node) { | 2074 catchClause.exceptionParameter == node) { |
1986 _addRemoveEdit( | 2075 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
1987 range.startStart(catchClause.catchKeyword, catchClause.body)); | 2076 await changeBuilder.addFileEdit(file, fileStamp, |
1988 _addFix(DartFixKind.REMOVE_UNUSED_CATCH_CLAUSE, []); | 2077 (DartFileEditBuilder builder) { |
2078 builder.addDeletion( | |
2079 range.startStart(catchClause.catchKeyword, catchClause.body)); | |
2080 }); | |
2081 _addFixFromBuilder( | |
2082 changeBuilder, DartFixKind.REMOVE_UNUSED_CATCH_CLAUSE); | |
1989 } | 2083 } |
1990 } | 2084 } |
1991 } | 2085 } |
1992 | 2086 |
1993 void _addFix_removeUnusedCatchStack() { | 2087 Future<Null> _addFix_removeUnusedCatchStack() async { |
1994 if (node is SimpleIdentifier) { | 2088 if (node is SimpleIdentifier) { |
1995 AstNode catchClause = node.parent; | 2089 AstNode catchClause = node.parent; |
1996 if (catchClause is CatchClause && | 2090 if (catchClause is CatchClause && |
1997 catchClause.stackTraceParameter == node && | 2091 catchClause.stackTraceParameter == node && |
1998 catchClause.exceptionParameter != null) { | 2092 catchClause.exceptionParameter != null) { |
1999 _addRemoveEdit(range.endEnd(catchClause.exceptionParameter, node)); | 2093 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
2000 _addFix(DartFixKind.REMOVE_UNUSED_CATCH_STACK, []); | 2094 await changeBuilder.addFileEdit(file, fileStamp, |
2095 (DartFileEditBuilder builder) { | |
2096 builder | |
2097 .addDeletion(range.endEnd(catchClause.exceptionParameter, node)); | |
2098 }); | |
2099 _addFixFromBuilder( | |
2100 changeBuilder, DartFixKind.REMOVE_UNUSED_CATCH_STACK); | |
2001 } | 2101 } |
2002 } | 2102 } |
2003 } | 2103 } |
2004 | 2104 |
2005 void _addFix_removeUnusedImport() { | 2105 Future<Null> _addFix_removeUnusedImport() async { |
2006 // prepare ImportDirective | 2106 // prepare ImportDirective |
2007 ImportDirective importDirective = | 2107 ImportDirective importDirective = |
2008 node.getAncestor((node) => node is ImportDirective); | 2108 node.getAncestor((node) => node is ImportDirective); |
2009 if (importDirective == null) { | 2109 if (importDirective == null) { |
2010 return; | 2110 return; |
2011 } | 2111 } |
2012 // remove the whole line with import | 2112 // remove the whole line with import |
2013 _addRemoveEdit(utils.getLinesRange(range.node(importDirective))); | 2113 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
2014 // done | 2114 await changeBuilder.addFileEdit(file, fileStamp, |
2015 _addFix(DartFixKind.REMOVE_UNUSED_IMPORT, []); | 2115 (DartFileEditBuilder builder) { |
2116 builder.addDeletion(utils.getLinesRange(range.node(importDirective))); | |
2117 }); | |
2118 _addFixFromBuilder(changeBuilder, DartFixKind.REMOVE_UNUSED_IMPORT); | |
2016 } | 2119 } |
2017 | 2120 |
2018 void _addFix_replaceVarWithDynamic() { | 2121 Future<Null> _addFix_replaceVarWithDynamic() async { |
2019 _addReplaceEdit(range.error(error), 'dynamic'); | 2122 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
2020 _addFix(DartFixKind.REPLACE_VAR_WITH_DYNAMIC, []); | 2123 await changeBuilder.addFileEdit(file, fileStamp, |
2124 (DartFileEditBuilder builder) { | |
2125 builder.addSimpleReplacement(range.error(error), 'dynamic'); | |
2126 }); | |
2127 _addFixFromBuilder(changeBuilder, DartFixKind.REPLACE_VAR_WITH_DYNAMIC); | |
2021 } | 2128 } |
2022 | 2129 |
2023 void _addFix_replaceWithConditionalAssignment() { | 2130 Future<Null> _addFix_replaceWithConditionalAssignment() async { |
2024 IfStatement ifStatement = node is IfStatement | 2131 IfStatement ifStatement = node is IfStatement |
2025 ? node | 2132 ? node |
2026 : node.getAncestor((node) => node is IfStatement); | 2133 : node.getAncestor((node) => node is IfStatement); |
2027 var thenStatement = ifStatement.thenStatement; | 2134 var thenStatement = ifStatement.thenStatement; |
2028 Statement uniqueStatement(Statement statement) { | 2135 Statement uniqueStatement(Statement statement) { |
2029 if (statement is Block) { | 2136 if (statement is Block) { |
2030 return uniqueStatement(statement.statements.first); | 2137 return uniqueStatement(statement.statements.first); |
2031 } | 2138 } |
2032 return statement; | 2139 return statement; |
2033 } | 2140 } |
2034 | 2141 |
2035 thenStatement = uniqueStatement(thenStatement); | 2142 thenStatement = uniqueStatement(thenStatement); |
2036 if (thenStatement is ExpressionStatement) { | 2143 if (thenStatement is ExpressionStatement) { |
2037 final expression = thenStatement.expression.unParenthesized; | 2144 final expression = thenStatement.expression.unParenthesized; |
2038 if (expression is AssignmentExpression) { | 2145 if (expression is AssignmentExpression) { |
2039 final buffer = new StringBuffer(); | 2146 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
2040 buffer.write(utils.getNodeText(expression.leftHandSide)); | 2147 await changeBuilder.addFileEdit(file, fileStamp, |
2041 buffer.write(' ??= '); | 2148 (DartFileEditBuilder builder) { |
2042 buffer.write(utils.getNodeText(expression.rightHandSide)); | 2149 builder.addReplacement(range.node(ifStatement), |
2043 buffer.write(';'); | 2150 (DartEditBuilder builder) { |
2044 _addReplaceEdit(range.node(ifStatement), buffer.toString()); | 2151 builder.write(utils.getNodeText(expression.leftHandSide)); |
2045 _addFix(DartFixKind.REPLACE_WITH_CONDITIONAL_ASSIGNMENT, []); | 2152 builder.write(' ??= '); |
2153 builder.write(utils.getNodeText(expression.rightHandSide)); | |
2154 builder.write(';'); | |
2155 }); | |
2156 }); | |
2157 _addFixFromBuilder( | |
2158 changeBuilder, DartFixKind.REPLACE_WITH_CONDITIONAL_ASSIGNMENT); | |
2046 } | 2159 } |
2047 } | 2160 } |
2048 } | 2161 } |
2049 | 2162 |
2050 void _addFix_replaceWithConstInstanceCreation() { | 2163 Future<Null> _addFix_replaceWithConstInstanceCreation() async { |
2051 if (coveredNode is InstanceCreationExpression) { | 2164 if (coveredNode is InstanceCreationExpression) { |
2052 var instanceCreation = coveredNode as InstanceCreationExpression; | 2165 var instanceCreation = coveredNode as InstanceCreationExpression; |
2053 _addReplaceEdit(range.token(instanceCreation.keyword), 'const'); | 2166 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
2054 _addFix(DartFixKind.USE_CONST, []); | 2167 await changeBuilder.addFileEdit(file, fileStamp, |
2168 (DartFileEditBuilder builder) { | |
2169 builder.addSimpleReplacement( | |
2170 range.token(instanceCreation.keyword), 'const'); | |
2171 }); | |
2172 _addFixFromBuilder(changeBuilder, DartFixKind.USE_CONST); | |
2055 } | 2173 } |
2056 } | 2174 } |
2057 | 2175 |
2058 void _addFix_replaceWithIdentifier() { | 2176 Future<Null> _addFix_replaceWithIdentifier() async { |
2059 final FunctionTypedFormalParameter functionTyped = | 2177 final FunctionTypedFormalParameter functionTyped = |
2060 node.getAncestor((node) => node is FunctionTypedFormalParameter); | 2178 node.getAncestor((node) => node is FunctionTypedFormalParameter); |
2061 if (functionTyped != null) { | 2179 if (functionTyped != null) { |
2062 _addReplaceEdit(range.node(functionTyped), | 2180 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
2063 utils.getNodeText(functionTyped.identifier)); | 2181 await changeBuilder.addFileEdit(file, fileStamp, |
2064 _addFix(DartFixKind.REPLACE_WITH_IDENTIFIER, []); | 2182 (DartFileEditBuilder builder) { |
2183 builder.addSimpleReplacement(range.node(functionTyped), | |
2184 utils.getNodeText(functionTyped.identifier)); | |
2185 }); | |
2186 _addFixFromBuilder(changeBuilder, DartFixKind.REPLACE_WITH_IDENTIFIER); | |
2065 } else { | 2187 } else { |
2066 _addFix_removeTypeName(); | 2188 await _addFix_removeTypeName(); |
2067 } | 2189 } |
2068 } | 2190 } |
2069 | 2191 |
2070 void _addFix_replaceWithLiteral() { | 2192 Future<Null> _addFix_replaceWithLiteral() async { |
2071 final InstanceCreationExpression instanceCreation = | 2193 final InstanceCreationExpression instanceCreation = |
2072 node.getAncestor((node) => node is InstanceCreationExpression); | 2194 node.getAncestor((node) => node is InstanceCreationExpression); |
2073 final InterfaceType type = instanceCreation.staticType; | 2195 final InterfaceType type = instanceCreation.staticType; |
2074 final buffer = new StringBuffer(); | |
2075 final generics = instanceCreation.constructorName.type.typeArguments; | 2196 final generics = instanceCreation.constructorName.type.typeArguments; |
2076 if (generics != null) { | 2197 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
2077 buffer.write(utils.getNodeText(generics)); | 2198 await changeBuilder.addFileEdit(file, fileStamp, |
2078 } | 2199 (DartFileEditBuilder builder) { |
2079 if (type.name == 'List') { | 2200 builder.addReplacement(range.node(instanceCreation), |
2080 buffer.write('[]'); | 2201 (DartEditBuilder builder) { |
2081 } else { | 2202 if (generics != null) { |
2082 buffer.write('{}'); | 2203 builder.write(utils.getNodeText(generics)); |
2083 } | 2204 } |
2084 _addReplaceEdit(range.node(instanceCreation), buffer.toString()); | 2205 if (type.name == 'List') { |
2085 _addFix(DartFixKind.REPLACE_WITH_LITERAL, []); | 2206 builder.write('[]'); |
2207 } else { | |
2208 builder.write('{}'); | |
2209 } | |
2210 }); | |
2211 }); | |
2212 _addFixFromBuilder(changeBuilder, DartFixKind.REPLACE_WITH_LITERAL); | |
2086 } | 2213 } |
2087 | 2214 |
2088 void _addFix_replaceWithTearOff() { | 2215 Future<Null> _addFix_replaceWithTearOff() async { |
2089 FunctionExpression ancestor = | 2216 FunctionExpression ancestor = |
2090 node.getAncestor((a) => a is FunctionExpression); | 2217 node.getAncestor((a) => a is FunctionExpression); |
2091 if (ancestor == null) { | 2218 if (ancestor == null) { |
2092 return; | 2219 return; |
2093 } | 2220 } |
2094 void addFixOfExpression(InvocationExpression expression) { | 2221 Future<Null> addFixOfExpression(InvocationExpression expression) async { |
2095 final buffer = new StringBuffer(); | 2222 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
2096 if (expression is MethodInvocation && expression.target != null) { | 2223 await changeBuilder.addFileEdit(file, fileStamp, |
2097 buffer.write(utils.getNodeText(expression.target)); | 2224 (DartFileEditBuilder builder) { |
2098 buffer.write('.'); | 2225 builder.addReplacement(range.node(ancestor), (DartEditBuilder builder) { |
2099 } | 2226 if (expression is MethodInvocation && expression.target != null) { |
2100 buffer.write(utils.getNodeText(expression.function)); | 2227 builder.write(utils.getNodeText(expression.target)); |
2101 _addReplaceEdit(range.node(ancestor), buffer.toString()); | 2228 builder.write('.'); |
2102 _addFix(DartFixKind.REPLACE_WITH_TEAR_OFF, []); | 2229 } |
2230 builder.write(utils.getNodeText(expression.function)); | |
2231 }); | |
2232 }); | |
2233 _addFixFromBuilder(changeBuilder, DartFixKind.REPLACE_WITH_TEAR_OFF); | |
2103 } | 2234 } |
2104 | 2235 |
2105 final body = ancestor.body; | 2236 final body = ancestor.body; |
2106 if (body is ExpressionFunctionBody) { | 2237 if (body is ExpressionFunctionBody) { |
2107 final expression = body.expression; | 2238 final expression = body.expression; |
2108 addFixOfExpression(expression.unParenthesized); | 2239 await addFixOfExpression(expression.unParenthesized); |
2109 } else if (body is BlockFunctionBody) { | 2240 } else if (body is BlockFunctionBody) { |
2110 final statement = body.block.statements.first; | 2241 final statement = body.block.statements.first; |
2111 if (statement is ExpressionStatement) { | 2242 if (statement is ExpressionStatement) { |
2112 final expression = statement.expression; | 2243 final expression = statement.expression; |
2113 addFixOfExpression(expression.unParenthesized); | 2244 await addFixOfExpression(expression.unParenthesized); |
2114 } else if (statement is ReturnStatement) { | 2245 } else if (statement is ReturnStatement) { |
2115 final expression = statement.expression; | 2246 final expression = statement.expression; |
2116 addFixOfExpression(expression.unParenthesized); | 2247 await addFixOfExpression(expression.unParenthesized); |
2117 } | 2248 } |
2118 } | 2249 } |
2119 } | 2250 } |
2120 | 2251 |
2121 void _addFix_undefinedClass_useSimilar() { | 2252 Future<Null> _addFix_undefinedClass_useSimilar() async { |
2122 AstNode node = this.node; | 2253 AstNode node = this.node; |
2123 // Prepare the optional import prefix name. | 2254 // Prepare the optional import prefix name. |
2124 String prefixName = null; | 2255 String prefixName = null; |
2125 if (node is SimpleIdentifier && node.staticElement is PrefixElement) { | 2256 if (node is SimpleIdentifier && node.staticElement is PrefixElement) { |
2126 AstNode parent = node.parent; | 2257 AstNode parent = node.parent; |
2127 if (parent is PrefixedIdentifier && | 2258 if (parent is PrefixedIdentifier && |
2128 parent.prefix == node && | 2259 parent.prefix == node && |
2129 parent.parent is TypeName) { | 2260 parent.parent is TypeName) { |
2130 prefixName = (node as SimpleIdentifier).name; | 2261 prefixName = (node as SimpleIdentifier).name; |
2131 node = parent.identifier; | 2262 node = parent.identifier; |
(...skipping 16 matching lines...) Expand all Loading... | |
2148 // Check elements from imports. | 2279 // Check elements from imports. |
2149 for (ImportElement importElement in unitLibraryElement.imports) { | 2280 for (ImportElement importElement in unitLibraryElement.imports) { |
2150 if (importElement.prefix?.name == prefixName) { | 2281 if (importElement.prefix?.name == prefixName) { |
2151 Map<String, Element> namespace = getImportNamespace(importElement); | 2282 Map<String, Element> namespace = getImportNamespace(importElement); |
2152 finder._updateList(namespace.values); | 2283 finder._updateList(namespace.values); |
2153 } | 2284 } |
2154 } | 2285 } |
2155 // If we have a close enough element, suggest to use it. | 2286 // If we have a close enough element, suggest to use it. |
2156 if (finder._element != null) { | 2287 if (finder._element != null) { |
2157 String closestName = finder._element.name; | 2288 String closestName = finder._element.name; |
2158 _addReplaceEdit(range.node(node), closestName); | |
2159 // Add proposal. | |
2160 if (closestName != null) { | 2289 if (closestName != null) { |
2161 _addFix(DartFixKind.CHANGE_TO, [closestName]); | 2290 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
2291 await changeBuilder.addFileEdit(file, fileStamp, | |
2292 (DartFileEditBuilder builder) { | |
2293 builder.addSimpleReplacement(range.node(node), closestName); | |
2294 }); | |
2295 _addFixFromBuilder(changeBuilder, DartFixKind.CHANGE_TO, | |
2296 args: [closestName]); | |
2162 } | 2297 } |
2163 } | 2298 } |
2164 } | 2299 } |
2165 } | 2300 } |
2166 | 2301 |
2167 void _addFix_undefinedClassAccessor_useSimilar() { | 2302 Future<Null> _addFix_undefinedClassAccessor_useSimilar() async { |
2168 AstNode node = this.node; | 2303 AstNode node = this.node; |
2169 if (node is SimpleIdentifier) { | 2304 if (node is SimpleIdentifier) { |
2170 // prepare target | 2305 // prepare target |
2171 Expression target = null; | 2306 Expression target = null; |
2172 if (node.parent is PrefixedIdentifier) { | 2307 if (node.parent is PrefixedIdentifier) { |
2173 PrefixedIdentifier invocation = node.parent as PrefixedIdentifier; | 2308 PrefixedIdentifier invocation = node.parent as PrefixedIdentifier; |
2174 target = invocation.prefix; | 2309 target = invocation.prefix; |
2175 } | 2310 } |
2176 // find getter | 2311 // find getter |
2177 if (node.inGetterContext()) { | 2312 if (node.inGetterContext()) { |
2178 _addFix_undefinedClassMember_useSimilar(target, (Element element) { | 2313 await _addFix_undefinedClassMember_useSimilar(target, |
2314 (Element element) { | |
2179 return element is PropertyAccessorElement && element.isGetter || | 2315 return element is PropertyAccessorElement && element.isGetter || |
2180 element is FieldElement && element.getter != null; | 2316 element is FieldElement && element.getter != null; |
2181 }); | 2317 }); |
2182 } | 2318 } |
2183 // find setter | 2319 // find setter |
2184 if (node.inSetterContext()) { | 2320 if (node.inSetterContext()) { |
2185 _addFix_undefinedClassMember_useSimilar(target, (Element element) { | 2321 await _addFix_undefinedClassMember_useSimilar(target, |
2322 (Element element) { | |
2186 return element is PropertyAccessorElement && element.isSetter || | 2323 return element is PropertyAccessorElement && element.isSetter || |
2187 element is FieldElement && element.setter != null; | 2324 element is FieldElement && element.setter != null; |
2188 }); | 2325 }); |
2189 } | 2326 } |
2190 } | 2327 } |
2191 } | 2328 } |
2192 | 2329 |
2193 void _addFix_undefinedClassMember_useSimilar( | 2330 Future<Null> _addFix_undefinedClassMember_useSimilar( |
2194 Expression target, ElementPredicate predicate) { | 2331 Expression target, ElementPredicate predicate) async { |
2195 if (node is SimpleIdentifier) { | 2332 if (node is SimpleIdentifier) { |
2196 String name = (node as SimpleIdentifier).name; | 2333 String name = (node as SimpleIdentifier).name; |
2197 _ClosestElementFinder finder = | 2334 _ClosestElementFinder finder = |
2198 new _ClosestElementFinder(name, predicate, MAX_LEVENSHTEIN_DISTANCE); | 2335 new _ClosestElementFinder(name, predicate, MAX_LEVENSHTEIN_DISTANCE); |
2199 // unqualified invocation | 2336 // unqualified invocation |
2200 if (target == null) { | 2337 if (target == null) { |
2201 ClassDeclaration clazz = | 2338 ClassDeclaration clazz = |
2202 node.getAncestor((node) => node is ClassDeclaration); | 2339 node.getAncestor((node) => node is ClassDeclaration); |
2203 if (clazz != null) { | 2340 if (clazz != null) { |
2204 ClassElement classElement = clazz.element; | 2341 ClassElement classElement = clazz.element; |
2205 _updateFinderWithClassMembers(finder, classElement); | 2342 _updateFinderWithClassMembers(finder, classElement); |
2206 } | 2343 } |
2207 } else { | 2344 } else { |
2208 DartType type = target.bestType; | 2345 DartType type = target.bestType; |
2209 if (type is InterfaceType) { | 2346 if (type is InterfaceType) { |
2210 ClassElement classElement = type.element; | 2347 ClassElement classElement = type.element; |
2211 _updateFinderWithClassMembers(finder, classElement); | 2348 _updateFinderWithClassMembers(finder, classElement); |
2212 } | 2349 } |
2213 } | 2350 } |
2214 // if we have close enough element, suggest to use it | 2351 // if we have close enough element, suggest to use it |
2215 if (finder._element != null) { | 2352 if (finder._element != null) { |
2216 String closestName = finder._element.name; | 2353 String closestName = finder._element.name; |
2217 _addReplaceEdit(range.node(node), closestName); | 2354 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
2218 _addFix(DartFixKind.CHANGE_TO, [closestName]); | 2355 await changeBuilder.addFileEdit(file, fileStamp, |
2356 (DartFileEditBuilder builder) { | |
2357 builder.addSimpleReplacement(range.node(node), closestName); | |
2358 }); | |
2359 _addFixFromBuilder(changeBuilder, DartFixKind.CHANGE_TO, | |
2360 args: [closestName]); | |
2219 } | 2361 } |
2220 } | 2362 } |
2221 } | 2363 } |
2222 | 2364 |
2223 void _addFix_undefinedFunction_create() { | 2365 Future<Null> _addFix_undefinedFunction_create() async { |
2224 // should be the name of the invocation | 2366 // should be the name of the invocation |
2225 if (node is SimpleIdentifier && node.parent is MethodInvocation) {} else { | 2367 if (node is SimpleIdentifier && node.parent is MethodInvocation) {} else { |
2226 return; | 2368 return; |
2227 } | 2369 } |
2228 String name = (node as SimpleIdentifier).name; | 2370 String name = (node as SimpleIdentifier).name; |
2229 MethodInvocation invocation = node.parent as MethodInvocation; | 2371 MethodInvocation invocation = node.parent as MethodInvocation; |
2230 // function invocation has no target | 2372 // function invocation has no target |
2231 Expression target = invocation.realTarget; | 2373 Expression target = invocation.realTarget; |
2232 if (target != null) { | 2374 if (target != null) { |
2233 return; | 2375 return; |
2234 } | 2376 } |
2235 // prepare environment | 2377 // prepare environment |
2236 int insertOffset; | 2378 int insertOffset; |
2237 String sourcePrefix; | 2379 String sourcePrefix; |
2238 AstNode enclosingMember = | 2380 AstNode enclosingMember = |
2239 node.getAncestor((node) => node is CompilationUnitMember); | 2381 node.getAncestor((node) => node is CompilationUnitMember); |
2240 insertOffset = enclosingMember.end; | 2382 insertOffset = enclosingMember.end; |
2241 sourcePrefix = '$eol$eol'; | 2383 sourcePrefix = '$eol$eol'; |
2242 utils.targetClassElement = null; | 2384 utils.targetClassElement = null; |
2243 // build method source | 2385 // build method source |
2244 SourceBuilder sb = new SourceBuilder(file, insertOffset); | 2386 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
2245 { | 2387 await changeBuilder.addFileEdit(file, fileStamp, |
2246 sb.append(sourcePrefix); | 2388 (DartFileEditBuilder builder) { |
2247 // append return type | 2389 builder.addInsertion(insertOffset, (DartEditBuilder builder) { |
2248 { | 2390 builder.write(sourcePrefix); |
2249 DartType type = _inferUndefinedExpressionType(invocation); | 2391 // append return type |
2250 _appendType(sb, type, groupId: 'RETURN_TYPE'); | 2392 { |
2251 } | 2393 DartType type = _inferUndefinedExpressionType(invocation); |
2252 // append name | 2394 if (builder.writeType(type, groupName: 'RETURN_TYPE')) { |
2253 { | 2395 builder.write(' '); |
2254 sb.startPosition('NAME'); | 2396 } |
2255 sb.append(name); | 2397 } |
2256 sb.endPosition(); | 2398 // append name |
2257 } | 2399 builder.addLinkedEdit('NAME', (DartLinkedEditBuilder builder) { |
2258 _addFix_undefinedMethod_create_parameters(sb, invocation.argumentList); | 2400 builder.write(name); |
2259 sb.append(') {$eol}'); | 2401 }); |
2260 } | 2402 builder.write('('); |
2261 // insert source | 2403 builder.writeParametersMatchingArguments(invocation.argumentList); |
2262 _insertBuilder(sb, unitElement); | 2404 builder.write(') {$eol}'); |
2263 _addLinkedPosition('NAME', sb, range.node(node)); | 2405 }); |
2264 // add proposal | 2406 builder.addLinkedPosition(range.node(node), 'NAME'); |
2265 _addFix(DartFixKind.CREATE_FUNCTION, [name]); | 2407 }); |
2408 _addFixFromBuilder(changeBuilder, DartFixKind.CREATE_FUNCTION, | |
2409 args: [name]); | |
2266 } | 2410 } |
2267 | 2411 |
2268 void _addFix_undefinedFunction_useSimilar() { | 2412 Future<Null> _addFix_undefinedFunction_useSimilar() async { |
2269 AstNode node = this.node; | 2413 AstNode node = this.node; |
2270 if (node is SimpleIdentifier) { | 2414 if (node is SimpleIdentifier) { |
2271 // Prepare the optional import prefix name. | 2415 // Prepare the optional import prefix name. |
2272 String prefixName = null; | 2416 String prefixName = null; |
2273 { | 2417 { |
2274 AstNode invocation = node.parent; | 2418 AstNode invocation = node.parent; |
2275 if (invocation is MethodInvocation && invocation.methodName == node) { | 2419 if (invocation is MethodInvocation && invocation.methodName == node) { |
2276 Expression target = invocation.target; | 2420 Expression target = invocation.target; |
2277 if (target is SimpleIdentifier && | 2421 if (target is SimpleIdentifier && |
2278 target.staticElement is PrefixElement) { | 2422 target.staticElement is PrefixElement) { |
(...skipping 15 matching lines...) Expand all Loading... | |
2294 // Check unprefixed imports. | 2438 // Check unprefixed imports. |
2295 for (ImportElement importElement in unitLibraryElement.imports) { | 2439 for (ImportElement importElement in unitLibraryElement.imports) { |
2296 if (importElement.prefix?.name == prefixName) { | 2440 if (importElement.prefix?.name == prefixName) { |
2297 Map<String, Element> namespace = getImportNamespace(importElement); | 2441 Map<String, Element> namespace = getImportNamespace(importElement); |
2298 finder._updateList(namespace.values); | 2442 finder._updateList(namespace.values); |
2299 } | 2443 } |
2300 } | 2444 } |
2301 // If we have a close enough element, suggest to use it. | 2445 // If we have a close enough element, suggest to use it. |
2302 if (finder._element != null) { | 2446 if (finder._element != null) { |
2303 String closestName = finder._element.name; | 2447 String closestName = finder._element.name; |
2304 _addReplaceEdit(range.node(node), closestName); | 2448 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
2305 _addFix(DartFixKind.CHANGE_TO, [closestName]); | 2449 await changeBuilder.addFileEdit(file, fileStamp, |
2450 (DartFileEditBuilder builder) { | |
2451 builder.addSimpleReplacement(range.node(node), closestName); | |
2452 }); | |
2453 _addFixFromBuilder(changeBuilder, DartFixKind.CHANGE_TO, | |
2454 args: [closestName]); | |
2306 } | 2455 } |
2307 } | 2456 } |
2308 } | 2457 } |
2309 | 2458 |
2310 void _addFix_undefinedMethod_create() { | 2459 Future<Null> _addFix_undefinedMethod_create() async { |
2311 if (node is SimpleIdentifier && node.parent is MethodInvocation) { | 2460 if (node is SimpleIdentifier && node.parent is MethodInvocation) { |
2312 String name = (node as SimpleIdentifier).name; | 2461 String name = (node as SimpleIdentifier).name; |
2313 MethodInvocation invocation = node.parent as MethodInvocation; | 2462 MethodInvocation invocation = node.parent as MethodInvocation; |
2314 // prepare environment | 2463 // prepare environment |
2315 Element targetElement; | 2464 Element targetElement; |
2316 bool staticModifier = false; | 2465 bool staticModifier = false; |
2317 | 2466 |
2318 ClassDeclaration targetClassNode; | 2467 ClassDeclaration targetClassNode; |
2319 Expression target = invocation.realTarget; | 2468 Expression target = invocation.realTarget; |
2320 if (target == null) { | 2469 if (target == null) { |
(...skipping 28 matching lines...) Expand all Loading... | |
2349 } | 2498 } |
2350 // use different utils | 2499 // use different utils |
2351 CompilationUnitElement targetUnitElement = | 2500 CompilationUnitElement targetUnitElement = |
2352 getCompilationUnitElement(targetClassElement); | 2501 getCompilationUnitElement(targetClassElement); |
2353 CompilationUnit targetUnit = getParsedUnit(targetUnitElement); | 2502 CompilationUnit targetUnit = getParsedUnit(targetUnitElement); |
2354 utils = new CorrectionUtils(targetUnit); | 2503 utils = new CorrectionUtils(targetUnit); |
2355 } | 2504 } |
2356 ClassMemberLocation targetLocation = | 2505 ClassMemberLocation targetLocation = |
2357 utils.prepareNewMethodLocation(targetClassNode); | 2506 utils.prepareNewMethodLocation(targetClassNode); |
2358 String targetFile = targetElement.source.fullName; | 2507 String targetFile = targetElement.source.fullName; |
2508 int targetStamp = | |
2509 targetElement.context.getModificationStamp(targetElement.source); | |
2359 // build method source | 2510 // build method source |
2360 SourceBuilder sb = new SourceBuilder(targetFile, targetLocation.offset); | 2511 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
2361 { | 2512 await changeBuilder.addFileEdit(targetFile, targetStamp, |
2362 sb.append(targetLocation.prefix); | 2513 (DartFileEditBuilder builder) { |
2363 // maybe "static" | 2514 builder.addInsertion(targetLocation.offset, (DartEditBuilder builder) { |
2364 if (staticModifier) { | 2515 builder.write(targetLocation.prefix); |
2365 sb.append('static '); | 2516 // maybe "static" |
2517 if (staticModifier) { | |
2518 builder.write('static '); | |
2519 } | |
2520 // append return type | |
2521 { | |
2522 DartType type = _inferUndefinedExpressionType(invocation); | |
2523 if (builder.writeType(type, groupName: 'RETURN_TYPE')) { | |
2524 builder.write(' '); | |
2525 } | |
2526 } | |
2527 // append name | |
2528 builder.addLinkedEdit('NAME', (DartLinkedEditBuilder builder) { | |
2529 builder.write(name); | |
2530 }); | |
2531 builder.write('('); | |
2532 builder.writeParametersMatchingArguments(invocation.argumentList); | |
2533 builder.write(') {}'); | |
2534 builder.write(targetLocation.suffix); | |
2535 }); | |
2536 if (targetFile == file) { | |
2537 builder.addLinkedPosition(range.node(node), 'NAME'); | |
2366 } | 2538 } |
2367 // append return type | 2539 }); |
2368 { | 2540 _addFixFromBuilder(changeBuilder, DartFixKind.CREATE_METHOD, |
2369 DartType type = _inferUndefinedExpressionType(invocation); | 2541 args: [name]); |
2370 _appendType(sb, type, groupId: 'RETURN_TYPE'); | |
2371 } | |
2372 // append name | |
2373 { | |
2374 sb.startPosition('NAME'); | |
2375 sb.append(name); | |
2376 sb.endPosition(); | |
2377 } | |
2378 _addFix_undefinedMethod_create_parameters(sb, invocation.argumentList); | |
2379 sb.append(') {}'); | |
2380 sb.append(targetLocation.suffix); | |
2381 } | |
2382 // insert source | |
2383 _insertBuilder(sb, targetElement); | |
2384 // add linked positions | |
2385 if (targetFile == file) { | |
2386 _addLinkedPosition('NAME', sb, range.node(node)); | |
2387 } | |
2388 // add proposal | |
2389 _addFix(DartFixKind.CREATE_METHOD, [name]); | |
2390 } | 2542 } |
2391 } | 2543 } |
2392 | 2544 |
2393 void _addFix_undefinedMethod_create_parameters( | 2545 Future<Null> _addFix_undefinedMethod_useSimilar() async { |
2394 SourceBuilder sb, ArgumentList argumentList) { | |
2395 Set<String> usedNames = new Set<String>(); | |
2396 // append parameters | |
2397 sb.append('('); | |
2398 List<Expression> arguments = argumentList.arguments; | |
2399 bool hasNamedParameters = false; | |
2400 for (int i = 0; i < arguments.length; i++) { | |
2401 Expression argument = arguments[i]; | |
2402 // append separator | |
2403 if (i != 0) { | |
2404 sb.append(', '); | |
2405 } | |
2406 // append parameter | |
2407 if (argument is NamedExpression && !hasNamedParameters) { | |
2408 hasNamedParameters = true; | |
2409 sb.append('{'); | |
2410 } | |
2411 _appendParameterForArgument(sb, usedNames, i, argument); | |
2412 } | |
2413 if (hasNamedParameters) { | |
2414 sb.append('}'); | |
2415 } | |
2416 } | |
2417 | |
2418 void _addFix_undefinedMethod_useSimilar() { | |
2419 if (node.parent is MethodInvocation) { | 2546 if (node.parent is MethodInvocation) { |
2420 MethodInvocation invocation = node.parent as MethodInvocation; | 2547 MethodInvocation invocation = node.parent as MethodInvocation; |
2421 _addFix_undefinedClassMember_useSimilar(invocation.realTarget, | 2548 await _addFix_undefinedClassMember_useSimilar(invocation.realTarget, |
2422 (Element element) => element is MethodElement && !element.isOperator); | 2549 (Element element) => element is MethodElement && !element.isOperator); |
2423 } | 2550 } |
2424 } | 2551 } |
2425 | 2552 |
2426 /** | 2553 /** |
2427 * Here we handle cases when a constructors does not initialize all of the | 2554 * Here we handle cases when a constructors does not initialize all of the |
2428 * final fields. | 2555 * final fields. |
2429 */ | 2556 */ |
2430 void _addFix_updateConstructor_forUninitializedFinalFields() { | 2557 Future<Null> _addFix_updateConstructor_forUninitializedFinalFields() async { |
2431 if (node is! SimpleIdentifier || node.parent is! ConstructorDeclaration) { | 2558 if (node is! SimpleIdentifier || node.parent is! ConstructorDeclaration) { |
2432 return; | 2559 return; |
2433 } | 2560 } |
2434 ConstructorDeclaration constructor = node.parent; | 2561 ConstructorDeclaration constructor = node.parent; |
2435 // add these fields | 2562 // add these fields |
2436 List<FieldElement> fields = | 2563 List<FieldElement> fields = |
2437 ErrorVerifier.computeNotInitializedFields(constructor); | 2564 ErrorVerifier.computeNotInitializedFields(constructor); |
2438 // prepare new parameters code | 2565 // prepare new parameters code |
2439 fields.sort((a, b) => a.nameOffset - b.nameOffset); | 2566 fields.sort((a, b) => a.nameOffset - b.nameOffset); |
2440 String fieldParametersCode = | 2567 String fieldParametersCode = |
2441 fields.map((field) => 'this.${field.name}').join(', '); | 2568 fields.map((field) => 'this.${field.name}').join(', '); |
2442 // prepare the last required parameter | 2569 // prepare the last required parameter |
2443 FormalParameter lastRequiredParameter; | 2570 FormalParameter lastRequiredParameter; |
2444 List<FormalParameter> parameters = constructor.parameters.parameters; | 2571 List<FormalParameter> parameters = constructor.parameters.parameters; |
2445 for (FormalParameter parameter in parameters) { | 2572 for (FormalParameter parameter in parameters) { |
2446 if (parameter.kind == ParameterKind.REQUIRED) { | 2573 if (parameter.kind == ParameterKind.REQUIRED) { |
2447 lastRequiredParameter = parameter; | 2574 lastRequiredParameter = parameter; |
2448 } | 2575 } |
2449 } | 2576 } |
2450 // append new field formal initializers | 2577 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
2451 if (lastRequiredParameter != null) { | 2578 await changeBuilder.addFileEdit(file, fileStamp, |
2452 _addInsertEdit(lastRequiredParameter.end, ', $fieldParametersCode'); | 2579 (DartFileEditBuilder builder) { |
2453 } else { | 2580 // append new field formal initializers |
2454 int offset = constructor.parameters.leftParenthesis.end; | 2581 if (lastRequiredParameter != null) { |
2455 if (parameters.isNotEmpty) { | 2582 builder.addSimpleInsertion( |
2456 fieldParametersCode += ', '; | 2583 lastRequiredParameter.end, ', $fieldParametersCode'); |
2584 } else { | |
2585 int offset = constructor.parameters.leftParenthesis.end; | |
2586 if (parameters.isNotEmpty) { | |
2587 fieldParametersCode += ', '; | |
2588 } | |
2589 builder.addSimpleInsertion(offset, fieldParametersCode); | |
2457 } | 2590 } |
2458 _addInsertEdit(offset, fieldParametersCode); | 2591 }); |
2459 } | 2592 _addFixFromBuilder(changeBuilder, DartFixKind.ADD_FIELD_FORMAL_PARAMETERS); |
2460 // add proposal | |
2461 _addFix(DartFixKind.ADD_FIELD_FORMAL_PARAMETERS, []); | |
2462 } | 2593 } |
2463 | 2594 |
2464 void _addFix_useEffectiveIntegerDivision() { | 2595 Future<Null> _addFix_useEffectiveIntegerDivision() async { |
2465 for (AstNode n = node; n != null; n = n.parent) { | 2596 for (AstNode n = node; n != null; n = n.parent) { |
2466 if (n is MethodInvocation && | 2597 if (n is MethodInvocation && |
2467 n.offset == errorOffset && | 2598 n.offset == errorOffset && |
2468 n.length == errorLength) { | 2599 n.length == errorLength) { |
2469 Expression target = n.target.unParenthesized; | 2600 Expression target = (n as MethodInvocation).target.unParenthesized; |
2470 // replace "/" with "~/" | 2601 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
2471 BinaryExpression binary = target as BinaryExpression; | 2602 await changeBuilder.addFileEdit(file, fileStamp, |
2472 _addReplaceEdit(range.token(binary.operator), '~/'); | 2603 (DartFileEditBuilder builder) { |
2473 // remove everything before and after | 2604 // replace "/" with "~/" |
2474 _addRemoveEdit(range.startStart(n, binary.leftOperand)); | 2605 BinaryExpression binary = target as BinaryExpression; |
2475 _addRemoveEdit(range.endEnd(binary.rightOperand, n)); | 2606 builder.addSimpleReplacement(range.token(binary.operator), '~/'); |
2476 // add proposal | 2607 // remove everything before and after |
2477 _addFix(DartFixKind.USE_EFFECTIVE_INTEGER_DIVISION, []); | 2608 builder.addDeletion(range.startStart(n, binary.leftOperand)); |
2609 builder.addDeletion(range.endEnd(binary.rightOperand, n)); | |
2610 }); | |
2611 _addFixFromBuilder( | |
2612 changeBuilder, DartFixKind.USE_EFFECTIVE_INTEGER_DIVISION); | |
2478 // done | 2613 // done |
2479 break; | 2614 break; |
2480 } | 2615 } |
2481 } | 2616 } |
2482 } | 2617 } |
2483 | 2618 |
2484 /** | 2619 /** |
2485 * Adds a fix that replaces [target] with a reference to the class declaring | 2620 * Adds a fix that replaces [target] with a reference to the class declaring |
2486 * the given [element]. | 2621 * the given [element]. |
2487 */ | 2622 */ |
2488 void _addFix_useStaticAccess(AstNode target, Element element) { | 2623 Future<Null> _addFix_useStaticAccess(AstNode target, Element element) async { |
2489 Element declaringElement = element.enclosingElement; | 2624 Element declaringElement = element.enclosingElement; |
2490 if (declaringElement is ClassElement) { | 2625 if (declaringElement is ClassElement) { |
2491 DartType declaringType = declaringElement.type; | 2626 DartType declaringType = declaringElement.type; |
2492 String declaringTypeCode = | 2627 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
2493 utils.getTypeSource(declaringType, librariesToImport); | 2628 await changeBuilder.addFileEdit(file, fileStamp, |
2494 // replace "target" with class name | 2629 (DartFileEditBuilder builder) { |
2495 _addReplaceEdit(range.node(target), declaringTypeCode); | 2630 // replace "target" with class name |
2496 // add proposal | 2631 builder.addReplacement(range.node(target), (DartEditBuilder builder) { |
2497 _addFix(DartFixKind.CHANGE_TO_STATIC_ACCESS, [declaringType]); | 2632 builder.writeType(declaringType); |
2633 }); | |
2634 }); | |
2635 _addFixFromBuilder(changeBuilder, DartFixKind.CHANGE_TO_STATIC_ACCESS, | |
2636 args: [declaringType]); | |
2498 } | 2637 } |
2499 } | 2638 } |
2500 | 2639 |
2501 void _addFix_useStaticAccess_method() { | 2640 Future<Null> _addFix_useStaticAccess_method() async { |
2502 if (node is SimpleIdentifier && node.parent is MethodInvocation) { | 2641 if (node is SimpleIdentifier && node.parent is MethodInvocation) { |
2503 MethodInvocation invocation = node.parent as MethodInvocation; | 2642 MethodInvocation invocation = node.parent as MethodInvocation; |
2504 if (invocation.methodName == node) { | 2643 if (invocation.methodName == node) { |
2505 Expression target = invocation.target; | 2644 Expression target = invocation.target; |
2506 Element invokedElement = invocation.methodName.bestElement; | 2645 Element invokedElement = invocation.methodName.bestElement; |
2507 _addFix_useStaticAccess(target, invokedElement); | 2646 await _addFix_useStaticAccess(target, invokedElement); |
2508 } | 2647 } |
2509 } | 2648 } |
2510 } | 2649 } |
2511 | 2650 |
2512 void _addFix_useStaticAccess_property() { | 2651 Future<Null> _addFix_useStaticAccess_property() async { |
2513 if (node is SimpleIdentifier && node.parent is PrefixedIdentifier) { | 2652 if (node is SimpleIdentifier && node.parent is PrefixedIdentifier) { |
2514 PrefixedIdentifier prefixed = node.parent as PrefixedIdentifier; | 2653 PrefixedIdentifier prefixed = node.parent as PrefixedIdentifier; |
2515 if (prefixed.identifier == node) { | 2654 if (prefixed.identifier == node) { |
2516 Expression target = prefixed.prefix; | 2655 Expression target = prefixed.prefix; |
2517 Element invokedElement = prefixed.identifier.bestElement; | 2656 Element invokedElement = prefixed.identifier.bestElement; |
2518 _addFix_useStaticAccess(target, invokedElement); | 2657 await _addFix_useStaticAccess(target, invokedElement); |
2519 } | 2658 } |
2520 } | 2659 } |
2521 } | 2660 } |
2522 | 2661 |
2523 void _addFixFromBuilder(DartChangeBuilder builder, FixKind kind, | 2662 void _addFixFromBuilder(DartChangeBuilder builder, FixKind kind, |
2524 {List args: null, bool importsOnly: false}) { | 2663 {List args: null, bool importsOnly: false}) { |
2525 SourceChange change = builder.sourceChange; | 2664 SourceChange change = builder.sourceChange; |
2526 if (change.edits.isEmpty && !importsOnly) { | 2665 if (change.edits.isEmpty && !importsOnly) { |
2527 return; | 2666 return; |
2528 } | 2667 } |
2529 change.message = formatList(kind.message, args); | 2668 change.message = formatList(kind.message, args); |
2530 fixes.add(new Fix(kind, change)); | 2669 fixes.add(new Fix(kind, change)); |
2531 } | 2670 } |
2532 | 2671 |
2533 /** | 2672 /** |
2534 * Adds a new [SourceEdit] to [change]. | |
2535 */ | |
2536 void _addInsertEdit(int offset, String text, [Element target]) { | |
2537 SourceEdit edit = new SourceEdit(offset, 0, text); | |
2538 _addEdit(target, edit); | |
2539 } | |
2540 | |
2541 /** | |
2542 * Adds a single linked position to [groupId]. | |
2543 */ | |
2544 void _addLinkedPosition(String groupId, SourceBuilder sb, SourceRange range) { | |
2545 // prepare offset | |
2546 int offset = range.offset; | |
2547 if (sb.offset <= offset) { | |
2548 int delta = sb.length; | |
2549 offset += delta; | |
2550 } | |
2551 // prepare group | |
2552 LinkedEditGroup group = _getLinkedPosition(groupId); | |
2553 // add position | |
2554 Position position = new Position(file, offset); | |
2555 group.addPosition(position, range.length); | |
2556 } | |
2557 | |
2558 void _addLintFixAddOverrideAnnotation() { | |
2559 ClassMember member = node.getAncestor((n) => n is ClassMember); | |
2560 if (member == null) { | |
2561 return; | |
2562 } | |
2563 | |
2564 //TODO(pq): migrate annotation edit building to change_builder | |
2565 | |
2566 // Handle doc comments. | |
2567 Token token = member.beginToken; | |
2568 if (token is CommentToken) { | |
2569 token = (token as CommentToken).parent; | |
2570 } | |
2571 | |
2572 exitPosition = new Position(file, token.offset - 1); | |
2573 String indent = utils.getIndent(1); | |
2574 _addReplaceEdit(range.startLength(token, 0), '@override$eol$indent'); | |
2575 _addFix(DartFixKind.LINT_ADD_OVERRIDE, []); | |
2576 } | |
2577 | |
2578 void _addLintRemoveInterpolationBraces() { | |
2579 AstNode node = this.node; | |
2580 if (node is InterpolationExpression) { | |
2581 Token right = node.rightBracket; | |
2582 if (node.expression != null && right != null) { | |
2583 _addReplaceEdit(range.startStart(node, node.expression), r'$'); | |
2584 _addRemoveEdit(range.token(right)); | |
2585 _addFix(DartFixKind.LINT_REMOVE_INTERPOLATION_BRACES, []); | |
2586 } | |
2587 } | |
2588 } | |
2589 | |
2590 /** | |
2591 * Prepares proposal for creating function corresponding to the given | 2673 * Prepares proposal for creating function corresponding to the given |
2592 * [FunctionType]. | 2674 * [FunctionType]. |
2593 */ | 2675 */ |
2594 void _addProposal_createFunction( | 2676 Future<DartChangeBuilder> _addProposal_createFunction( |
2595 FunctionType functionType, | 2677 FunctionType functionType, |
2596 String name, | 2678 String name, |
2597 Source targetSource, | 2679 Source targetSource, |
2598 int insertOffset, | 2680 int insertOffset, |
2599 bool isStatic, | 2681 bool isStatic, |
2600 String prefix, | 2682 String prefix, |
2601 String sourcePrefix, | 2683 String sourcePrefix, |
2602 String sourceSuffix, | 2684 String sourceSuffix, |
2603 Element target) { | 2685 Element target) async { |
2604 // build method source | 2686 // build method source |
2605 String targetFile = targetSource.fullName; | 2687 String targetFile = targetSource.fullName; |
2606 SourceBuilder sb = new SourceBuilder(targetFile, insertOffset); | 2688 int timeStamp = target.context.getModificationStamp(targetSource); |
2607 { | 2689 DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
2608 sb.append(sourcePrefix); | 2690 await changeBuilder.addFileEdit(targetFile, timeStamp, |
2609 sb.append(prefix); | 2691 (DartFileEditBuilder builder) { |
2610 // may be static | 2692 builder.addInsertion(insertOffset, (DartEditBuilder builder) { |
2611 if (isStatic) { | 2693 builder.write(sourcePrefix); |
2612 sb.append('static '); | 2694 builder.write(prefix); |
2695 // may be static | |
2696 if (isStatic) { | |
2697 builder.write('static '); | |
2698 } | |
2699 // append return type | |
2700 if (builder.writeType(functionType.returnType, | |
2701 groupName: 'RETURN_TYPE')) { | |
2702 builder.write(' '); | |
2703 } | |
2704 // append name | |
2705 builder.addLinkedEdit('NAME', (DartLinkedEditBuilder builder) { | |
2706 builder.write(name); | |
2707 }); | |
2708 // append parameters | |
2709 builder.write('('); | |
2710 List<ParameterElement> parameters = functionType.parameters; | |
2711 for (int i = 0; i < parameters.length; i++) { | |
2712 ParameterElement parameter = parameters[i]; | |
2713 // append separator | |
2714 if (i != 0) { | |
2715 builder.write(', '); | |
2716 } | |
2717 // append type name | |
2718 DartType type = parameter.type; | |
2719 if (!type.isDynamic) { | |
2720 builder.addLinkedEdit('TYPE$i', | |
2721 (DartLinkedEditBuilder innerBuilder) { | |
2722 builder.writeType(type); | |
2723 innerBuilder.addSuperTypesAsSuggestions(type); | |
2724 }); | |
2725 builder.write(' '); | |
2726 } | |
2727 // append parameter name | |
2728 builder.addLinkedEdit('ARG$i', (DartLinkedEditBuilder builder) { | |
2729 builder.write(parameter.displayName); | |
2730 }); | |
2731 } | |
2732 builder.write(')'); | |
2733 // close method | |
2734 builder.write(' {$eol$prefix}'); | |
2735 builder.write(sourceSuffix); | |
2736 }); | |
2737 if (targetSource == unitSource) { | |
2738 builder.addLinkedPosition(range.node(node), 'NAME'); | |
2613 } | 2739 } |
2614 // append return type | 2740 }); |
2615 _appendType(sb, functionType.returnType, groupId: 'RETURN_TYPE'); | 2741 return changeBuilder; |
2616 // append name | |
2617 { | |
2618 sb.startPosition('NAME'); | |
2619 sb.append(name); | |
2620 sb.endPosition(); | |
2621 } | |
2622 // append parameters | |
2623 sb.append('('); | |
2624 List<ParameterElement> parameters = functionType.parameters; | |
2625 for (int i = 0; i < parameters.length; i++) { | |
2626 ParameterElement parameter = parameters[i]; | |
2627 // append separator | |
2628 if (i != 0) { | |
2629 sb.append(', '); | |
2630 } | |
2631 // append type name | |
2632 DartType type = parameter.type; | |
2633 if (!type.isDynamic) { | |
2634 String typeSource = utils.getTypeSource(type, librariesToImport); | |
2635 { | |
2636 sb.startPosition('TYPE$i'); | |
2637 sb.append(typeSource); | |
2638 _addSuperTypeProposals(sb, type); | |
2639 sb.endPosition(); | |
2640 } | |
2641 sb.append(' '); | |
2642 } | |
2643 // append parameter name | |
2644 { | |
2645 sb.startPosition('ARG$i'); | |
2646 sb.append(parameter.displayName); | |
2647 sb.endPosition(); | |
2648 } | |
2649 } | |
2650 sb.append(')'); | |
2651 // close method | |
2652 sb.append(' {$eol$prefix}'); | |
2653 sb.append(sourceSuffix); | |
2654 } | |
2655 // insert source | |
2656 _insertBuilder(sb, target); | |
2657 // add linked positions | |
2658 if (targetSource == unitSource) { | |
2659 _addLinkedPosition('NAME', sb, range.node(node)); | |
2660 } | |
2661 } | 2742 } |
2662 | 2743 |
2663 /** | 2744 /** |
2664 * Adds proposal for creating method corresponding to the given [FunctionType] in the given | 2745 * Adds proposal for creating method corresponding to the given [FunctionType] in the given |
2665 * [ClassElement]. | 2746 * [ClassElement]. |
2666 */ | 2747 */ |
2667 void _addProposal_createFunction_function(FunctionType functionType) { | 2748 Future<Null> _addProposal_createFunction_function( |
2749 FunctionType functionType) async { | |
2668 String name = (node as SimpleIdentifier).name; | 2750 String name = (node as SimpleIdentifier).name; |
2669 // prepare environment | 2751 // prepare environment |
2670 int insertOffset = unit.end; | 2752 int insertOffset = unit.end; |
2671 // prepare prefix | 2753 // prepare prefix |
2672 String prefix = ''; | 2754 String prefix = ''; |
2673 String sourcePrefix = '$eol'; | 2755 String sourcePrefix = '$eol'; |
2674 String sourceSuffix = eol; | 2756 String sourceSuffix = eol; |
2675 _addProposal_createFunction(functionType, name, unitSource, insertOffset, | 2757 DartChangeBuilder changeBuilder = await _addProposal_createFunction( |
2676 false, prefix, sourcePrefix, sourceSuffix, unitElement); | 2758 functionType, |
2677 // add proposal | 2759 name, |
2678 _addFix(DartFixKind.CREATE_FUNCTION, [name]); | 2760 unitSource, |
2761 insertOffset, | |
2762 false, | |
2763 prefix, | |
2764 sourcePrefix, | |
2765 sourceSuffix, | |
2766 unitElement); | |
2767 _addFixFromBuilder(changeBuilder, DartFixKind.CREATE_FUNCTION, | |
2768 args: [name]); | |
2679 } | 2769 } |
2680 | 2770 |
2681 /** | 2771 /** |
2682 * Adds proposal for creating method corresponding to the given [FunctionType] in the given | 2772 * Adds proposal for creating method corresponding to the given [FunctionType] in the given |
2683 * [ClassElement]. | 2773 * [ClassElement]. |
2684 */ | 2774 */ |
2685 void _addProposal_createFunction_method( | 2775 Future<Null> _addProposal_createFunction_method( |
2686 ClassElement targetClassElement, FunctionType functionType) { | 2776 ClassElement targetClassElement, FunctionType functionType) async { |
2687 String name = (node as SimpleIdentifier).name; | 2777 String name = (node as SimpleIdentifier).name; |
2688 // prepare environment | 2778 // prepare environment |
2689 Source targetSource = targetClassElement.source; | 2779 Source targetSource = targetClassElement.source; |
2690 // prepare insert offset | 2780 // prepare insert offset |
2691 ClassDeclaration targetClassNode = | 2781 ClassDeclaration targetClassNode = |
2692 getParsedClassElementNode(targetClassElement); | 2782 getParsedClassElementNode(targetClassElement); |
2693 int insertOffset = targetClassNode.end - 1; | 2783 int insertOffset = targetClassNode.end - 1; |
2694 // prepare prefix | 2784 // prepare prefix |
2695 String prefix = ' '; | 2785 String prefix = ' '; |
2696 String sourcePrefix; | 2786 String sourcePrefix; |
2697 if (targetClassNode.members.isEmpty) { | 2787 if (targetClassNode.members.isEmpty) { |
2698 sourcePrefix = ''; | 2788 sourcePrefix = ''; |
2699 } else { | 2789 } else { |
2700 sourcePrefix = eol; | 2790 sourcePrefix = eol; |
2701 } | 2791 } |
2702 String sourceSuffix = eol; | 2792 String sourceSuffix = eol; |
2703 _addProposal_createFunction( | 2793 DartChangeBuilder changeBuilder = await _addProposal_createFunction( |
2704 functionType, | 2794 functionType, |
2705 name, | 2795 name, |
2706 targetSource, | 2796 targetSource, |
2707 insertOffset, | 2797 insertOffset, |
2708 _inStaticContext(), | 2798 _inStaticContext(), |
2709 prefix, | 2799 prefix, |
2710 sourcePrefix, | 2800 sourcePrefix, |
2711 sourceSuffix, | 2801 sourceSuffix, |
2712 targetClassElement); | 2802 targetClassElement); |
2713 // add proposal | 2803 _addFixFromBuilder(changeBuilder, DartFixKind.CREATE_METHOD, args: [name]); |
2714 _addFix(DartFixKind.CREATE_METHOD, [name]); | |
2715 } | 2804 } |
2716 | 2805 |
2717 /** | 2806 /** |
2718 * Adds a new [Edit] to [edits]. | |
2719 */ | |
2720 void _addRemoveEdit(SourceRange range) { | |
2721 _addReplaceEdit(range, ''); | |
2722 } | |
2723 | |
2724 /** | |
2725 * Adds a new [SourceEdit] to [change]. | |
2726 */ | |
2727 void _addReplaceEdit(SourceRange range, String text, [Element target]) { | |
2728 SourceEdit edit = new SourceEdit(range.offset, range.length, text); | |
2729 _addEdit(target, edit); | |
2730 } | |
2731 | |
2732 void _appendParameterForArgument( | |
2733 SourceBuilder sb, Set<String> excluded, int index, Expression argument) { | |
2734 DartType type = argument.bestType; | |
2735 if (type == null || type.isBottom || type.isDartCoreNull) { | |
2736 type = DynamicTypeImpl.instance; | |
2737 } | |
2738 // append type name | |
2739 String typeSource = utils.getTypeSource(type, librariesToImport); | |
2740 if (typeSource != 'dynamic') { | |
2741 sb.startPosition('TYPE$index'); | |
2742 sb.append(typeSource); | |
2743 _addSuperTypeProposals(sb, type); | |
2744 sb.endPosition(); | |
2745 sb.append(' '); | |
2746 } | |
2747 // append parameter name | |
2748 if (argument is NamedExpression) { | |
2749 sb.append(argument.name.label.name); | |
2750 } else { | |
2751 List<String> suggestions = | |
2752 _getArgumentNameSuggestions(excluded, type, argument, index); | |
2753 String favorite = suggestions[0]; | |
2754 excluded.add(favorite); | |
2755 sb.startPosition('ARG$index'); | |
2756 sb.append(favorite); | |
2757 sb.addSuggestions(LinkedEditSuggestionKind.PARAMETER, suggestions); | |
2758 sb.endPosition(); | |
2759 } | |
2760 } | |
2761 | |
2762 void _appendParameters(SourceBuilder sb, List<ParameterElement> parameters) { | |
2763 sb.append('('); | |
2764 bool firstParameter = true; | |
2765 bool sawNamed = false; | |
2766 bool sawPositional = false; | |
2767 for (ParameterElement parameter in parameters) { | |
2768 if (!firstParameter) { | |
2769 sb.append(', '); | |
2770 } else { | |
2771 firstParameter = false; | |
2772 } | |
2773 // may be optional | |
2774 ParameterKind parameterKind = parameter.parameterKind; | |
2775 if (parameterKind == ParameterKind.NAMED) { | |
2776 if (!sawNamed) { | |
2777 sb.append('{'); | |
2778 sawNamed = true; | |
2779 } | |
2780 } | |
2781 if (parameterKind == ParameterKind.POSITIONAL) { | |
2782 if (!sawPositional) { | |
2783 sb.append('['); | |
2784 sawPositional = true; | |
2785 } | |
2786 } | |
2787 // parameter | |
2788 _appendParameterSource(sb, parameter.type, parameter.name); | |
2789 // default value | |
2790 String defaultCode = parameter.defaultValueCode; | |
2791 if (defaultCode != null) { | |
2792 if (sawPositional) { | |
2793 sb.append(' = '); | |
2794 } else { | |
2795 sb.append(': '); | |
2796 } | |
2797 sb.append(defaultCode); | |
2798 } | |
2799 } | |
2800 // close parameters | |
2801 if (sawNamed) { | |
2802 sb.append('}'); | |
2803 } | |
2804 if (sawPositional) { | |
2805 sb.append(']'); | |
2806 } | |
2807 sb.append(')'); | |
2808 } | |
2809 | |
2810 void _appendParameterSource(SourceBuilder sb, DartType type, String name) { | |
2811 String parameterSource = | |
2812 utils.getParameterSource(type, name, librariesToImport); | |
2813 sb.append(parameterSource); | |
2814 } | |
2815 | |
2816 void _appendType(SourceBuilder sb, DartType type, | |
2817 {String groupId, bool orVar: false, bool trailingSpace: true}) { | |
2818 if (type != null && !type.isDynamic) { | |
2819 String typeSource = utils.getTypeSource(type, librariesToImport); | |
2820 if (groupId != null) { | |
2821 sb.startPosition(groupId); | |
2822 sb.append(typeSource); | |
2823 sb.endPosition(); | |
2824 } else { | |
2825 sb.append(typeSource); | |
2826 } | |
2827 if (trailingSpace) { | |
2828 sb.append(' '); | |
2829 } | |
2830 } else if (orVar) { | |
2831 sb.append('var '); | |
2832 } | |
2833 } | |
2834 | |
2835 /** | |
2836 * Computes the name of the library at the given [path]. | 2807 * Computes the name of the library at the given [path]. |
2837 * See https://www.dartlang.org/articles/style-guide/#names for conventions. | 2808 * See https://www.dartlang.org/articles/style-guide/#names for conventions. |
2838 */ | 2809 */ |
2839 String _computeLibraryName(String path) { | 2810 String _computeLibraryName(String path) { |
2840 Context pathContext = resourceProvider.pathContext; | 2811 Context pathContext = resourceProvider.pathContext; |
2841 String packageFolder = _computePackageFolder(path); | 2812 String packageFolder = _computePackageFolder(path); |
2842 if (packageFolder == null) { | 2813 if (packageFolder == null) { |
2843 return pathContext.basenameWithoutExtension(path); | 2814 return pathContext.basenameWithoutExtension(path); |
2844 } | 2815 } |
2845 String packageName = pathContext.basename(packageFolder); | 2816 String packageName = pathContext.basename(packageFolder); |
(...skipping 25 matching lines...) Expand all Loading... | |
2871 } | 2842 } |
2872 String pubspecFolderNew = pathContext.dirname(pubspecFolder); | 2843 String pubspecFolderNew = pathContext.dirname(pubspecFolder); |
2873 if (pubspecFolderNew == pubspecFolder) { | 2844 if (pubspecFolderNew == pubspecFolder) { |
2874 return null; | 2845 return null; |
2875 } | 2846 } |
2876 pubspecFolder = pubspecFolderNew; | 2847 pubspecFolder = pubspecFolderNew; |
2877 } | 2848 } |
2878 } | 2849 } |
2879 | 2850 |
2880 /** | 2851 /** |
2881 * @return the string to display as the name of the given constructor in a pro posal name. | 2852 * Return the string to display as the name of the given constructor in a |
2853 * proposal name. | |
2882 */ | 2854 */ |
2883 String _getConstructorProposalName(ConstructorElement constructor) { | 2855 String _getConstructorProposalName(ConstructorElement constructor) { |
2884 SourceBuilder proposalNameBuffer = new SourceBuilder.buffer(); | 2856 StringBuffer buffer = new StringBuffer(); |
2885 proposalNameBuffer.append('super'); | 2857 buffer.write('super'); |
2886 // may be named | |
2887 String constructorName = constructor.displayName; | 2858 String constructorName = constructor.displayName; |
2888 if (!constructorName.isEmpty) { | 2859 if (!constructorName.isEmpty) { |
2889 proposalNameBuffer.append('.'); | 2860 buffer.write('.'); |
2890 proposalNameBuffer.append(constructorName); | 2861 buffer.write(constructorName); |
2891 } | 2862 } |
2892 // parameters | 2863 buffer.write('(...)'); |
2893 _appendParameters(proposalNameBuffer, constructor.parameters); | 2864 return buffer.toString(); |
2894 // done | |
2895 return proposalNameBuffer.toString(); | |
2896 } | 2865 } |
2897 | 2866 |
2898 /** | 2867 /** |
2899 * Returns the [DartType] with given name from the `dart:core` library. | 2868 * Returns the [DartType] with given name from the `dart:core` library. |
2900 */ | 2869 */ |
2901 DartType _getCoreType(String name) { | 2870 DartType _getCoreType(String name) { |
2902 List<LibraryElement> libraries = unitLibraryElement.importedLibraries; | 2871 List<LibraryElement> libraries = unitLibraryElement.importedLibraries; |
2903 for (LibraryElement library in libraries) { | 2872 for (LibraryElement library in libraries) { |
2904 if (library.isDartCore) { | 2873 if (library.isDartCore) { |
2905 ClassElement classElement = library.getType(name); | 2874 ClassElement classElement = library.getType(name); |
2906 if (classElement != null) { | 2875 if (classElement != null) { |
2907 return classElement.type; | 2876 return classElement.type; |
2908 } | 2877 } |
2909 return null; | 2878 return null; |
2910 } | 2879 } |
2911 } | 2880 } |
2912 return null; | 2881 return null; |
2913 } | 2882 } |
2914 | 2883 |
2915 /** | 2884 /** |
2916 * Returns an existing or just added [LinkedEditGroup] with [groupId]. | |
2917 */ | |
2918 LinkedEditGroup _getLinkedPosition(String groupId) { | |
2919 LinkedEditGroup group = linkedPositionGroups[groupId]; | |
2920 if (group == null) { | |
2921 group = new LinkedEditGroup.empty(); | |
2922 linkedPositionGroups[groupId] = group; | |
2923 } | |
2924 return group; | |
2925 } | |
2926 | |
2927 /** | |
2928 * Returns an expected [DartType] of [expression], may be `null` if cannot be | 2885 * Returns an expected [DartType] of [expression], may be `null` if cannot be |
2929 * inferred. | 2886 * inferred. |
2930 */ | 2887 */ |
2931 DartType _inferUndefinedExpressionType(Expression expression) { | 2888 DartType _inferUndefinedExpressionType(Expression expression) { |
2932 AstNode parent = expression.parent; | 2889 AstNode parent = expression.parent; |
2933 // myFunction(); | 2890 // myFunction(); |
2934 if (parent is ExpressionStatement) { | 2891 if (parent is ExpressionStatement) { |
2935 if (expression is MethodInvocation) { | 2892 if (expression is MethodInvocation) { |
2936 return VoidTypeImpl.instance; | 2893 return VoidTypeImpl.instance; |
2937 } | 2894 } |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3044 operatorType == TokenType.BAR_BAR) { | 3001 operatorType == TokenType.BAR_BAR) { |
3045 return coreTypeBool; | 3002 return coreTypeBool; |
3046 } | 3003 } |
3047 } | 3004 } |
3048 } | 3005 } |
3049 // we don't know | 3006 // we don't know |
3050 return null; | 3007 return null; |
3051 } | 3008 } |
3052 | 3009 |
3053 /** | 3010 /** |
3054 * Inserts the given [SourceBuilder] at its offset. | |
3055 */ | |
3056 void _insertBuilder(SourceBuilder builder, Element target) { | |
3057 String text = builder.toString(); | |
3058 _addInsertEdit(builder.offset, text, target); | |
3059 // add linked positions | |
3060 builder.linkedPositionGroups.forEach((String id, LinkedEditGroup group) { | |
3061 LinkedEditGroup fixGroup = _getLinkedPosition(id); | |
3062 group.positions.forEach((Position position) { | |
3063 fixGroup.addPosition(position, group.length); | |
3064 }); | |
3065 group.suggestions.forEach((LinkedEditSuggestion suggestion) { | |
3066 fixGroup.addSuggestion(suggestion); | |
3067 }); | |
3068 }); | |
3069 } | |
3070 | |
3071 /** | |
3072 * Returns `true` if [node] is in static context. | 3011 * Returns `true` if [node] is in static context. |
3073 */ | 3012 */ |
3074 bool _inStaticContext() { | 3013 bool _inStaticContext() { |
3075 // constructor initializer cannot reference "this" | 3014 // constructor initializer cannot reference "this" |
3076 if (node.getAncestor((node) => node is ConstructorInitializer) != null) { | 3015 if (node.getAncestor((node) => node is ConstructorInitializer) != null) { |
3077 return true; | 3016 return true; |
3078 } | 3017 } |
3079 // field initializer cannot reference "this" | 3018 // field initializer cannot reference "this" |
3080 if (node.getAncestor((node) => node is FieldDeclaration) != null) { | 3019 if (node.getAncestor((node) => node is FieldDeclaration) != null) { |
3081 return true; | 3020 return true; |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3136 // TODO(brianwilkerson) We have lost the ability for clients to know whether | 3075 // TODO(brianwilkerson) We have lost the ability for clients to know whether |
3137 // it is safe to apply an edit. | 3076 // it is safe to apply an edit. |
3138 return driver.fsState.getFileForPath(filePath).exists ? 0 : -1; | 3077 return driver.fsState.getFileForPath(filePath).exists ? 0 : -1; |
3139 } | 3078 } |
3140 | 3079 |
3141 /** | 3080 /** |
3142 * Removes any [ParenthesizedExpression] enclosing [expr]. | 3081 * Removes any [ParenthesizedExpression] enclosing [expr]. |
3143 * | 3082 * |
3144 * [exprPrecedence] - the effective precedence of [expr]. | 3083 * [exprPrecedence] - the effective precedence of [expr]. |
3145 */ | 3084 */ |
3146 void _removeEnclosingParentheses(Expression expr, int exprPrecedence) { | 3085 void _removeEnclosingParentheses( |
3086 DartFileEditBuilder builder, Expression expr, int exprPrecedence) { | |
3147 while (expr.parent is ParenthesizedExpression) { | 3087 while (expr.parent is ParenthesizedExpression) { |
3148 ParenthesizedExpression parenthesized = | 3088 ParenthesizedExpression parenthesized = |
3149 expr.parent as ParenthesizedExpression; | 3089 expr.parent as ParenthesizedExpression; |
3150 if (getExpressionParentPrecedence(parenthesized) > exprPrecedence) { | 3090 if (getExpressionParentPrecedence(parenthesized) > exprPrecedence) { |
3151 break; | 3091 break; |
3152 } | 3092 } |
3153 _addRemoveEdit(range.token(parenthesized.leftParenthesis)); | 3093 builder.addDeletion(range.token(parenthesized.leftParenthesis)); |
3154 _addRemoveEdit(range.token(parenthesized.rightParenthesis)); | 3094 builder.addDeletion(range.token(parenthesized.rightParenthesis)); |
3155 expr = parenthesized; | 3095 expr = parenthesized; |
3156 } | 3096 } |
3157 } | 3097 } |
3158 | 3098 |
3159 void _updateFinderWithClassMembers( | 3099 void _updateFinderWithClassMembers( |
3160 _ClosestElementFinder finder, ClassElement clazz) { | 3100 _ClosestElementFinder finder, ClassElement clazz) { |
3161 if (clazz != null) { | 3101 if (clazz != null) { |
3162 List<Element> members = getMembers(clazz); | 3102 List<Element> members = getMembers(clazz); |
3163 finder._updateList(members); | 3103 finder._updateList(members); |
3164 } | 3104 } |
3165 } | 3105 } |
3166 | 3106 |
3167 static void _addSuperTypeProposals(SourceBuilder sb, DartType type, | |
3168 [Set<DartType> alreadyAdded]) { | |
3169 alreadyAdded ??= new Set<DartType>(); | |
3170 if (type is InterfaceType && alreadyAdded.add(type)) { | |
3171 sb.addSuggestion(LinkedEditSuggestionKind.TYPE, type.displayName); | |
3172 _addSuperTypeProposals(sb, type.superclass, alreadyAdded); | |
3173 for (InterfaceType interfaceType in type.interfaces) { | |
3174 _addSuperTypeProposals(sb, interfaceType, alreadyAdded); | |
3175 } | |
3176 } | |
3177 } | |
3178 | |
3179 /** | |
3180 * @return the suggestions for given [Type] and [DartExpression], not empty. | |
3181 */ | |
3182 static List<String> _getArgumentNameSuggestions( | |
3183 Set<String> excluded, DartType type, Expression expression, int index) { | |
3184 List<String> suggestions = | |
3185 getVariableNameSuggestionsForExpression(type, expression, excluded); | |
3186 if (suggestions.length != 0) { | |
3187 return suggestions; | |
3188 } | |
3189 return <String>['arg$index']; | |
3190 } | |
3191 | |
3192 static bool _isNameOfType(String name) { | 3107 static bool _isNameOfType(String name) { |
3193 if (name.isEmpty) { | 3108 if (name.isEmpty) { |
3194 return false; | 3109 return false; |
3195 } | 3110 } |
3196 String firstLetter = name.substring(0, 1); | 3111 String firstLetter = name.substring(0, 1); |
3197 if (firstLetter.toUpperCase() != firstLetter) { | 3112 if (firstLetter.toUpperCase() != firstLetter) { |
3198 return false; | 3113 return false; |
3199 } | 3114 } |
3200 return true; | 3115 return true; |
3201 } | 3116 } |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3260 } | 3175 } |
3261 } | 3176 } |
3262 } | 3177 } |
3263 | 3178 |
3264 void _updateList(Iterable<Element> elements) { | 3179 void _updateList(Iterable<Element> elements) { |
3265 for (Element element in elements) { | 3180 for (Element element in elements) { |
3266 _update(element); | 3181 _update(element); |
3267 } | 3182 } |
3268 } | 3183 } |
3269 } | 3184 } |
OLD | NEW |