Chromium Code Reviews| 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 |