Index: pkg/analysis_server/lib/src/services/correction/fix_internal.dart |
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart |
index c31ad8743d1a7083743979a970149537f104ef66..77d91014e401b00f7c50605de72d9d8974b6cd91 100644 |
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart |
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart |
@@ -47,6 +47,7 @@ import 'package:analyzer/src/generated/utilities_dart.dart'; |
import 'package:analyzer_plugin/protocol/protocol_common.dart' |
hide AnalysisError, Element, ElementKind; |
import 'package:analyzer_plugin/src/utilities/string_utilities.dart'; |
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart'; |
import 'package:analyzer_plugin/utilities/range_factory.dart'; |
import 'package:path/path.dart'; |
@@ -203,14 +204,14 @@ class FixProcessor { |
// analyze ErrorCode |
ErrorCode errorCode = error.errorCode; |
if (errorCode == StaticWarningCode.UNDEFINED_CLASS_BOOLEAN) { |
- _addFix_boolInsteadOfBoolean(); |
+ await _addFix_boolInsteadOfBoolean(); |
} |
if (errorCode == |
CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE) { |
_addFix_replaceWithConstInstanceCreation(); |
} |
if (errorCode == CompileTimeErrorCode.ASYNC_FOR_IN_WRONG_CONTEXT) { |
- _addFix_addAsync(); |
+ await _addFix_addAsync(); |
} |
if (errorCode == CompileTimeErrorCode.INVALID_ANNOTATION) { |
if (node is Annotation) { |
@@ -222,7 +223,7 @@ class FixProcessor { |
await _addFix_importLibrary_withTopLevelVariable(); |
} else { |
await _addFix_importLibrary_withType(); |
- _addFix_createClass(); |
+ await _addFix_createClass(); |
_addFix_undefinedClass_useSimilar(); |
} |
} |
@@ -230,22 +231,22 @@ class FixProcessor { |
} |
if (errorCode == |
CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT) { |
- _addFix_createConstructorSuperExplicit(); |
+ await _addFix_createConstructorSuperExplicit(); |
} |
if (errorCode == |
CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT) { |
- _addFix_createConstructorSuperImplicit(); |
+ await _addFix_createConstructorSuperImplicit(); |
} |
if (errorCode == |
CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT) { |
- _addFix_createConstructorSuperExplicit(); |
+ await _addFix_createConstructorSuperExplicit(); |
} |
if (errorCode == CompileTimeErrorCode.URI_DOES_NOT_EXIST) { |
_addFix_createImportUri(); |
_addFix_createPartUri(); |
} |
if (errorCode == HintCode.CAN_BE_NULL_AFTER_NULL_AWARE) { |
- _addFix_canBeNullAfterNullAware(); |
+ await _addFix_canBeNullAfterNullAware(); |
} |
if (errorCode == HintCode.DEAD_CODE) { |
_addFix_removeDeadCode(); |
@@ -261,12 +262,12 @@ class FixProcessor { |
} |
if (errorCode == HintCode.UNDEFINED_GETTER) { |
_addFix_undefinedClassAccessor_useSimilar(); |
- _addFix_createField(); |
- _addFix_createGetter(); |
+ await _addFix_createField(); |
+ await _addFix_createGetter(); |
} |
if (errorCode == HintCode.UNDEFINED_SETTER) { |
_addFix_undefinedClassAccessor_useSimilar(); |
- _addFix_createField(); |
+ await _addFix_createField(); |
} |
if (errorCode == HintCode.UNNECESSARY_CAST) { |
_addFix_removeUnnecessaryCast(); |
@@ -298,18 +299,18 @@ class FixProcessor { |
if (errorCode == StaticWarningCode.EXTRA_POSITIONAL_ARGUMENTS || |
errorCode == |
StaticWarningCode.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED) { |
- _addFix_createConstructor_insteadOfSyntheticDefault(); |
+ await _addFix_createConstructor_insteadOfSyntheticDefault(); |
await _addFix_addMissingParameter(); |
} |
if (errorCode == HintCode.MISSING_REQUIRED_PARAM || |
errorCode == HintCode.MISSING_REQUIRED_PARAM_WITH_DETAILS) { |
- _addFix_addMissingRequiredArgument(); |
+ await _addFix_addMissingRequiredArgument(); |
} |
if (errorCode == StaticWarningCode.FUNCTION_WITHOUT_CALL) { |
- _addFix_addMissingMethodCall(); |
+ await _addFix_addMissingMethodCall(); |
} |
if (errorCode == StaticWarningCode.NEW_WITH_UNDEFINED_CONSTRUCTOR) { |
- _addFix_createConstructor_named(); |
+ await _addFix_createConstructor_named(); |
} |
if (errorCode == |
StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE || |
@@ -326,7 +327,7 @@ class FixProcessor { |
.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS) { |
// make class abstract |
_addFix_makeEnclosingClassAbstract(); |
- _addFix_createNoSuchMethod(); |
+ await _addFix_createNoSuchMethod(); |
// implement methods |
_addFix_createMissingOverrides(); |
} |
@@ -335,11 +336,11 @@ class FixProcessor { |
errorCode == StaticWarningCode.TYPE_TEST_WITH_UNDEFINED_NAME || |
errorCode == StaticWarningCode.UNDEFINED_CLASS) { |
await _addFix_importLibrary_withType(); |
- _addFix_createClass(); |
+ await _addFix_createClass(); |
_addFix_undefinedClass_useSimilar(); |
} |
if (errorCode == StaticWarningCode.FINAL_NOT_INITIALIZED) { |
- _addFix_createConstructor_forUninitializedFinalFields(); |
+ await _addFix_createConstructor_forUninitializedFinalFields(); |
} |
if (errorCode == StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1 || |
errorCode == StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_2 || |
@@ -349,16 +350,16 @@ class FixProcessor { |
} |
if (errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER) { |
_addFix_undefinedClassAccessor_useSimilar(); |
- _addFix_createClass(); |
- _addFix_createField(); |
- _addFix_createGetter(); |
+ await _addFix_createClass(); |
+ await _addFix_createField(); |
+ await _addFix_createGetter(); |
_addFix_createFunction_forFunctionType(); |
await _addFix_importLibrary_withType(); |
await _addFix_importLibrary_withTopLevelVariable(); |
- _addFix_createLocalVariable(); |
+ await _addFix_createLocalVariable(); |
} |
if (errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER_AWAIT) { |
- _addFix_addAsync(); |
+ await _addFix_addAsync(); |
} |
if (errorCode == StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE) { |
_addFix_illegalAsyncReturnType(); |
@@ -368,7 +369,7 @@ class FixProcessor { |
_addFix_useStaticAccess_property(); |
} |
if (errorCode == StaticTypeWarningCode.INVALID_ASSIGNMENT) { |
- _addFix_changeTypeAnnotation(); |
+ await _addFix_changeTypeAnnotation(); |
} |
if (errorCode == StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION) { |
_addFix_removeParentheses_inGetterInvocation(); |
@@ -378,7 +379,7 @@ class FixProcessor { |
} |
if (errorCode == StaticTypeWarningCode.NON_TYPE_AS_TYPE_ARGUMENT) { |
await _addFix_importLibrary_withType(); |
- _addFix_createClass(); |
+ await _addFix_createClass(); |
} |
if (errorCode == StaticTypeWarningCode.UNDEFINED_FUNCTION) { |
await _addFix_importLibrary_withFunction(); |
@@ -387,8 +388,8 @@ class FixProcessor { |
} |
if (errorCode == StaticTypeWarningCode.UNDEFINED_GETTER) { |
_addFix_undefinedClassAccessor_useSimilar(); |
- _addFix_createField(); |
- _addFix_createGetter(); |
+ await _addFix_createField(); |
+ await _addFix_createGetter(); |
_addFix_createFunction_forFunctionType(); |
} |
if (errorCode == HintCode.UNDEFINED_METHOD || |
@@ -400,7 +401,7 @@ class FixProcessor { |
} |
if (errorCode == StaticTypeWarningCode.UNDEFINED_SETTER) { |
_addFix_undefinedClassAccessor_useSimilar(); |
- _addFix_createField(); |
+ await _addFix_createField(); |
} |
if (errorCode == CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER || |
errorCode == StaticWarningCode.UNDEFINED_NAMED_PARAMETER) { |
@@ -491,40 +492,44 @@ class FixProcessor { |
/** |
* Returns `true` if the `async` proposal was added. |
*/ |
- void _addFix_addAsync() { |
- AstNode node = this.node; |
+ Future<Null> _addFix_addAsync() async { |
FunctionBody body = node.getAncestor((n) => n is FunctionBody); |
if (body != null && body.keyword == null) { |
- _addReplaceEdit(range.startLength(body, 0), 'async '); |
- _replaceReturnTypeWithFuture(body, typeProvider); |
- _addFix(DartFixKind.ADD_ASYNC, []); |
+ TypeProvider typeProvider = await this.typeProvider; |
+ DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
+ await changeBuilder.addFileEdit(file, fileStamp, |
+ (DartFileEditBuilder builder) { |
+ builder.convertFunctionFromSyncToAsync(body, typeProvider); |
+ }); |
+ _addFixFromBuilder(changeBuilder, DartFixKind.ADD_ASYNC); |
} |
} |
- void _addFix_addMissingMethodCall() { |
+ Future<Null> _addFix_addMissingMethodCall() async { |
ClassDeclaration targetClass = node.parent as ClassDeclaration; |
- // prepare SourceBuilder |
int insertOffset = targetClass.end - 1; |
- SourceBuilder sb = new SourceBuilder(file, insertOffset); |
// prepare environment |
String prefix = utils.getIndent(1); |
String prefix2 = utils.getIndent(2); |
- // start method |
- sb.append(prefix); |
- sb.append('call() {'); |
- // TO-DO |
- sb.append(eol); |
- sb.append(prefix2); |
- sb.append('// TODO: implement call'); |
- sb.append(eol); |
- // close method |
- sb.append(prefix); |
- sb.append('}'); |
- sb.append(eol); |
- // add proposal |
- exitPosition = new Position(file, insertOffset); |
- _insertBuilder(sb, unitElement); |
- _addFix(DartFixKind.CREATE_MISSING_METHOD_CALL, []); |
+ DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
+ await changeBuilder.addFileEdit(file, fileStamp, |
+ (DartFileEditBuilder builder) { |
+ builder.addInsertion(insertOffset, (DartEditBuilder builder) { |
+ builder.selectHere(); |
+ builder.write(prefix); |
+ builder.write('call() {'); |
+ // TO-DO |
+ builder.write(eol); |
+ builder.write(prefix2); |
+ builder.write('// TODO: implement call'); |
+ builder.write(eol); |
+ // close method |
+ builder.write(prefix); |
+ builder.write('}'); |
+ builder.write(eol); |
+ }); |
+ }); |
+ _addFixFromBuilder(changeBuilder, DartFixKind.CREATE_MISSING_METHOD_CALL); |
} |
Future<Null> _addFix_addMissingParameter() async { |
@@ -578,43 +583,48 @@ class FixProcessor { |
return; |
} |
} |
- String targetFile = targetElement.source.fullName; |
- // required |
- { |
- SourceBuilder sb = new SourceBuilder(targetFile, targetOffset); |
- // append source |
- if (numRequired != 0) { |
- sb.append(', '); |
- } |
- _appendParameterForArgument( |
- sb, new Set<String>(), numRequired, argument); |
- if (numRequired != numParameters) { |
- sb.append(', '); |
- } |
- // add proposal |
- _insertBuilder(sb, targetElement); |
- _addFix(DartFixKind.ADD_MISSING_PARAMETER_REQUIRED, []); |
- } |
- // optional positional |
+ Source targetSource = targetElement.source; |
+ String targetFile = targetSource.fullName; |
+ DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
+ await changeBuilder |
+ .addFileEdit(targetFile, targetSource.modificationStamp, |
+ (DartFileEditBuilder builder) { |
+ builder.addInsertion(targetOffset, (DartEditBuilder builder) { |
+ if (numRequired != 0) { |
+ builder.write(', '); |
+ } |
+ builder.writeParameterMatchingArgument( |
+ argument, numRequired, new Set<String>()); |
+ if (numRequired != numParameters) { |
+ builder.write(', '); |
+ } |
+ }); |
+ }); |
+ _addFixFromBuilder( |
+ changeBuilder, DartFixKind.ADD_MISSING_PARAMETER_REQUIRED); |
if (optionalParameters.isEmpty) { |
- SourceBuilder sb = new SourceBuilder(targetFile, targetOffset); |
- // append source |
- if (numRequired != 0) { |
- sb.append(', '); |
- } |
- sb.append('['); |
- _appendParameterForArgument( |
- sb, new Set<String>(), numRequired, argument); |
- sb.append(']'); |
- // add proposal |
- _insertBuilder(sb, targetElement); |
- _addFix(DartFixKind.ADD_MISSING_PARAMETER_POSITIONAL, []); |
+ DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
+ await changeBuilder |
+ .addFileEdit(targetFile, targetSource.modificationStamp, |
+ (DartFileEditBuilder builder) { |
+ builder.addInsertion(targetOffset, (DartEditBuilder builder) { |
+ if (numRequired != 0) { |
+ builder.write(', '); |
+ } |
+ builder.write('['); |
+ builder.writeParameterMatchingArgument( |
+ argument, numRequired, new Set<String>()); |
+ builder.write(']'); |
+ }); |
+ }); |
+ _addFixFromBuilder( |
+ changeBuilder, DartFixKind.ADD_MISSING_PARAMETER_POSITIONAL); |
} |
} |
} |
} |
- void _addFix_addMissingRequiredArgument() { |
+ Future<Null> _addFix_addMissingRequiredArgument() async { |
Element targetElement; |
ArgumentList argumentList; |
@@ -640,63 +650,70 @@ class FixProcessor { |
return; |
} |
- // Grab just the name. |
- String paramName = parts[1]; |
- |
// add proposal |
- |
- SourceBuilder sb; |
- |
+ String paramName = parts[1]; |
final List<Expression> args = argumentList.arguments; |
- if (args.isEmpty) { |
- sb = new SourceBuilder(file, argumentList.leftParenthesis.end); |
- } else { |
- sb = new SourceBuilder(file, args.last.end); |
- sb.append(', '); |
- } |
- |
- List<ParameterElement> parameters = targetElement.parameters; |
- ParameterElement element = |
- parameters.firstWhere((p) => p.name == paramName, orElse: () => null); |
- String defaultValue = getDefaultStringParameterValue(element); |
- sb.append('$paramName: $defaultValue'); |
- |
- // Insert a trailing comma after Flutter instance creation params. |
- InstanceCreationExpression newExpr = identifyNewExpression(node); |
- if (newExpr != null && isFlutterInstanceCreationExpression(newExpr)) { |
- sb.append(','); |
- } |
- |
- _insertBuilder(sb, null); |
- _addFix(DartFixKind.ADD_MISSING_REQUIRED_ARGUMENT, [paramName]); |
+ int offset = |
+ args.isEmpty ? argumentList.leftParenthesis.end : args.last.end; |
+ DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
+ await changeBuilder.addFileEdit(file, fileStamp, |
+ (DartFileEditBuilder builder) { |
+ builder.addInsertion(offset, (DartEditBuilder builder) { |
+ if (args.isNotEmpty) { |
+ builder.write(', '); |
+ } |
+ List<ParameterElement> parameters = |
+ (targetElement as ExecutableElement).parameters; |
+ ParameterElement element = parameters |
+ .firstWhere((p) => p.name == paramName, orElse: () => null); |
+ String defaultValue = getDefaultStringParameterValue(element); |
+ builder.write('$paramName: $defaultValue'); |
+ // Insert a trailing comma after Flutter instance creation params. |
+ InstanceCreationExpression newExpr = identifyNewExpression(node); |
+ if (newExpr != null && isFlutterInstanceCreationExpression(newExpr)) { |
+ builder.write(','); |
+ } |
+ }); |
+ }); |
+ _addFixFromBuilder( |
+ changeBuilder, DartFixKind.ADD_MISSING_REQUIRED_ARGUMENT, |
+ args: [paramName]); |
} |
} |
- void _addFix_boolInsteadOfBoolean() { |
- _addReplaceEdit(range.error(error), 'bool'); |
- _addFix(DartFixKind.REPLACE_BOOLEAN_WITH_BOOL, []); |
+ Future<Null> _addFix_boolInsteadOfBoolean() async { |
+ DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
+ await changeBuilder.addFileEdit(file, fileStamp, |
+ (DartFileEditBuilder builder) { |
+ builder.addSimpleReplacement(range.error(error), 'bool'); |
+ }); |
+ _addFixFromBuilder(changeBuilder, DartFixKind.REPLACE_BOOLEAN_WITH_BOOL); |
} |
- void _addFix_canBeNullAfterNullAware() { |
+ Future<Null> _addFix_canBeNullAfterNullAware() async { |
AstNode node = coveredNode; |
if (node is Expression) { |
- AstNode parent = node.parent; |
- while (parent != null) { |
- if (parent is MethodInvocation && parent.target == node) { |
- _addReplaceEdit(range.token(parent.operator), '?.'); |
- } else if (parent is PropertyAccess && parent.target == node) { |
- _addReplaceEdit(range.token(parent.operator), '?.'); |
- } else { |
- break; |
+ DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
+ await changeBuilder.addFileEdit(file, fileStamp, |
+ (DartFileEditBuilder builder) { |
+ AstNode parent = node.parent; |
+ while (parent != null) { |
+ if (parent is MethodInvocation && parent.target == node) { |
+ builder.addSimpleReplacement(range.token(parent.operator), '?.'); |
+ } else if (parent is PropertyAccess && parent.target == node) { |
+ builder.addSimpleReplacement(range.token(parent.operator), '?.'); |
+ } else { |
+ break; |
+ } |
+ node = parent; |
+ parent = node.parent; |
} |
- node = parent; |
- parent = node.parent; |
- } |
- _addFix(DartFixKind.REPLACE_WITH_NULL_AWARE, []); |
+ }); |
+ _addFixFromBuilder(changeBuilder, DartFixKind.REPLACE_WITH_NULL_AWARE); |
} |
} |
- void _addFix_changeTypeAnnotation() { |
+ Future<Null> _addFix_changeTypeAnnotation() async { |
AstNode declaration = coveredNode.parent; |
if (declaration is VariableDeclaration && |
declaration.initializer == coveredNode) { |
@@ -710,9 +727,14 @@ class FixProcessor { |
if (newType is InterfaceType || newType is FunctionType) { |
String newTypeSource = |
utils.getTypeSource(newType, librariesToImport); |
- _addReplaceEdit(range.node(typeNode), newTypeSource); |
- _addFix(DartFixKind.CHANGE_TYPE_ANNOTATION, |
- [resolutionMap.typeForTypeName(typeNode), newTypeSource]); |
+ DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
+ await changeBuilder.addFileEdit(file, fileStamp, |
+ (DartFileEditBuilder builder) { |
+ builder.addSimpleReplacement(range.node(typeNode), newTypeSource); |
+ }); |
+ _addFixFromBuilder( |
+ changeBuilder, DartFixKind.CHANGE_TYPE_ANNOTATION, |
+ args: [resolutionMap.typeForTypeName(typeNode), newTypeSource]); |
} |
} |
} |
@@ -755,7 +777,7 @@ class FixProcessor { |
// TODO(messick) Implement _addFix_convertFlutterChildren() |
} |
- void _addFix_createClass() { |
+ Future<Null> _addFix_createClass() async { |
Element prefixElement = null; |
String name = null; |
SimpleIdentifier nameNode; |
@@ -782,9 +804,11 @@ class FixProcessor { |
} |
// prepare environment |
Element targetUnit; |
- SourceBuilder sb; |
String prefix = ''; |
String suffix = ''; |
+ int offset = -1; |
+ String filePath; |
+ int modificationTime = 0; |
if (prefixElement == null) { |
targetUnit = unitElement; |
CompilationUnitMember enclosingMember = |
@@ -792,8 +816,9 @@ class FixProcessor { |
if (enclosingMember == null) { |
return; |
} |
- int offset = enclosingMember.end; |
- sb = new SourceBuilder(file, offset); |
+ offset = enclosingMember.end; |
+ filePath = file; |
+ modificationTime = fileStamp; |
prefix = '$eol$eol'; |
} else { |
for (ImportElement import in unitLibraryElement.imports) { |
@@ -802,51 +827,39 @@ class FixProcessor { |
if (library != null) { |
targetUnit = library.definingCompilationUnit; |
Source targetSource = targetUnit.source; |
- int offset = targetSource.contents.data.length; |
- sb = new SourceBuilder(targetSource.fullName, offset); |
+ offset = targetSource.contents.data.length; |
+ filePath = targetSource.fullName; |
+ modificationTime = targetSource.modificationStamp; |
prefix = '$eol'; |
suffix = '$eol'; |
break; |
} |
} |
} |
- if (sb == null) { |
- return; |
- } |
} |
- // prepare source |
- { |
- sb.append(prefix); |
- // "class" |
- sb.append('class '); |
- // append name |
+ if (offset < 0) { |
+ return; |
+ } |
+ DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
+ await changeBuilder.addFileEdit(filePath, modificationTime, |
+ (DartFileEditBuilder builder) { |
+ builder.addInsertion(offset, (DartEditBuilder builder) { |
+ builder.write(prefix); |
+ builder.writeClassDeclaration(name, nameGroupName: 'NAME'); |
+ builder.write(suffix); |
+ }); |
if (prefixElement == null) { |
- sb.startPosition('NAME'); |
- sb.append(name); |
- sb.endPosition(); |
- } else { |
- sb.append(name); |
+ builder.addLinkedPosition(range.node(node), 'NAME'); |
} |
- // no members |
- sb.append(' {'); |
- sb.append(eol); |
- sb.append('}'); |
- sb.append(suffix); |
- } |
- // insert source |
- _insertBuilder(sb, targetUnit); |
- if (prefixElement == null) { |
- _addLinkedPosition('NAME', sb, range.node(node)); |
- } |
- // add proposal |
- _addFix(DartFixKind.CREATE_CLASS, [name]); |
+ }); |
+ _addFixFromBuilder(changeBuilder, DartFixKind.CREATE_CLASS, args: [name]); |
} |
/** |
* Here we handle cases when there are no constructors in a class, and the |
* class has uninitialized final fields. |
*/ |
- void _addFix_createConstructor_forUninitializedFinalFields() { |
+ Future<Null> _addFix_createConstructor_forUninitializedFinalFields() async { |
if (node is! SimpleIdentifier || node.parent is! VariableDeclaration) { |
return; |
} |
@@ -870,23 +883,21 @@ class FixProcessor { |
// prepare location for a new constructor |
ClassMemberLocation targetLocation = |
utils.prepareNewConstructorLocation(classDeclaration); |
- // build constructor source |
- SourceBuilder sb = new SourceBuilder(file, targetLocation.offset); |
- { |
- sb.append(targetLocation.prefix); |
- sb.append(classDeclaration.name.name); |
- sb.append('('); |
- sb.append(fieldNames.map((name) => 'this.$name').join(', ')); |
- sb.append(');'); |
- sb.append(targetLocation.suffix); |
- } |
- // insert source |
- _insertBuilder(sb, unitElement); |
- // add proposal |
- _addFix(DartFixKind.CREATE_CONSTRUCTOR_FOR_FINAL_FIELDS, []); |
+ DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
+ await changeBuilder.addFileEdit(file, fileStamp, |
+ (DartFileEditBuilder builder) { |
+ builder.addInsertion(targetLocation.offset, (DartEditBuilder builder) { |
+ builder.write(targetLocation.prefix); |
+ builder.writeConstructorDeclaration(classDeclaration.name.name, |
+ fieldNames: fieldNames); |
+ builder.write(targetLocation.suffix); |
+ }); |
+ }); |
+ _addFixFromBuilder( |
+ changeBuilder, DartFixKind.CREATE_CONSTRUCTOR_FOR_FINAL_FIELDS); |
} |
- void _addFix_createConstructor_insteadOfSyntheticDefault() { |
+ Future<Null> _addFix_createConstructor_insteadOfSyntheticDefault() async { |
if (node is! ArgumentList) { |
return; |
} |
@@ -914,24 +925,23 @@ class FixProcessor { |
} |
ClassMemberLocation targetLocation = |
utils.prepareNewConstructorLocation(targetTypeNode); |
- String targetFile = targetElement.source.fullName; |
- // build method source |
- SourceBuilder sb = new SourceBuilder(targetFile, targetLocation.offset); |
- { |
- sb.append(targetLocation.prefix); |
- sb.append(targetElement.name); |
- _addFix_undefinedMethod_create_parameters( |
- sb, instanceCreation.argumentList); |
- sb.append(');'); |
- sb.append(targetLocation.suffix); |
- } |
- // insert source |
- _insertBuilder(sb, targetElement); |
- // add proposal |
- _addFix(DartFixKind.CREATE_CONSTRUCTOR, [constructorName]); |
+ Source targetSource = targetElement.source; |
+ String targetFile = targetSource.fullName; |
+ DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
+ await changeBuilder.addFileEdit(targetFile, targetSource.modificationStamp, |
+ (DartFileEditBuilder builder) { |
+ builder.addInsertion(targetLocation.offset, (DartEditBuilder builder) { |
+ builder.write(targetLocation.prefix); |
+ builder.writeConstructorDeclaration(targetElement.name, |
+ argumentList: instanceCreation.argumentList); |
+ builder.write(targetLocation.suffix); |
+ }); |
+ }); |
+ _addFixFromBuilder(changeBuilder, DartFixKind.CREATE_CONSTRUCTOR, |
+ args: [constructorName]); |
} |
- void _addFix_createConstructor_named() { |
+ Future<Null> _addFix_createConstructor_named() async { |
SimpleIdentifier name = null; |
ConstructorName constructorName = null; |
InstanceCreationExpression instanceCreation = null; |
@@ -971,33 +981,26 @@ class FixProcessor { |
ClassMemberLocation targetLocation = |
utils.prepareNewConstructorLocation(targetTypeNode); |
String targetFile = targetElement.source.fullName; |
- // build method source |
- SourceBuilder sb = new SourceBuilder(targetFile, targetLocation.offset); |
- { |
- sb.append(targetLocation.prefix); |
- sb.append(targetElement.name); |
- sb.append('.'); |
- // append name |
- { |
- sb.startPosition('NAME'); |
- sb.append(name.name); |
- sb.endPosition(); |
+ DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
+ await changeBuilder.addFileEdit(file, fileStamp, |
+ (DartFileEditBuilder builder) { |
+ builder.addInsertion(targetLocation.offset, (DartEditBuilder builder) { |
+ builder.write(targetLocation.prefix); |
+ builder.writeConstructorDeclaration(targetElement.name, |
+ argumentList: instanceCreation.argumentList, |
+ constructorName: name, |
+ constructorNameGroupName: 'NAME'); |
+ builder.write(targetLocation.suffix); |
+ }); |
+ if (targetFile == file) { |
+ builder.addLinkedPosition(range.node(name), 'NAME'); |
} |
- _addFix_undefinedMethod_create_parameters( |
- sb, instanceCreation.argumentList); |
- sb.append(');'); |
- sb.append(targetLocation.suffix); |
- } |
- // insert source |
- _insertBuilder(sb, targetElement); |
- if (targetFile == file) { |
- _addLinkedPosition('NAME', sb, range.node(name)); |
- } |
- // add proposal |
- _addFix(DartFixKind.CREATE_CONSTRUCTOR, [constructorName]); |
+ }); |
+ _addFixFromBuilder(changeBuilder, DartFixKind.CREATE_CONSTRUCTOR, |
+ args: [constructorName]); |
} |
- void _addFix_createConstructorSuperExplicit() { |
+ Future<Null> _addFix_createConstructorSuperExplicit() async { |
if (node.parent is! ConstructorDeclaration || |
node.parent.parent is! ClassDeclaration) { |
return; |
@@ -1015,59 +1018,62 @@ class FixProcessor { |
if (Identifier.isPrivateName(constructorName)) { |
continue; |
} |
- // prepare SourceBuilder |
- SourceBuilder sb; |
- { |
- List<ConstructorInitializer> initializers = |
- targetConstructor.initializers; |
- if (initializers.isEmpty) { |
- int insertOffset = targetConstructor.parameters.end; |
- sb = new SourceBuilder(file, insertOffset); |
- sb.append(' : '); |
- } else { |
- ConstructorInitializer lastInitializer = |
- initializers[initializers.length - 1]; |
- int insertOffset = lastInitializer.end; |
- sb = new SourceBuilder(file, insertOffset); |
- sb.append(', '); |
- } |
- } |
- // add super constructor name |
- sb.append('super'); |
- if (!isEmpty(constructorName)) { |
- sb.append('.'); |
- sb.append(constructorName); |
- } |
- // add arguments |
- sb.append('('); |
- bool firstParameter = true; |
- for (ParameterElement parameter in superConstructor.parameters) { |
- // skip non-required parameters |
- if (parameter.parameterKind != ParameterKind.REQUIRED) { |
- break; |
- } |
- // comma |
- if (firstParameter) { |
- firstParameter = false; |
- } else { |
- sb.append(', '); |
- } |
- // default value |
- DartType parameterType = parameter.type; |
- sb.startPosition(parameter.name); |
- sb.append(getDefaultValueCode(parameterType)); |
- sb.endPosition(); |
+ List<ConstructorInitializer> initializers = |
+ targetConstructor.initializers; |
+ int insertOffset; |
+ String prefix; |
+ if (initializers.isEmpty) { |
+ insertOffset = targetConstructor.parameters.end; |
+ prefix = ' : '; |
+ } else { |
+ ConstructorInitializer lastInitializer = |
+ initializers[initializers.length - 1]; |
+ insertOffset = lastInitializer.end; |
+ prefix = ', '; |
} |
- sb.append(')'); |
- // insert proposal |
- _insertBuilder(sb, unitElement); |
- // add proposal |
String proposalName = _getConstructorProposalName(superConstructor); |
- _addFix(DartFixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION, [proposalName]); |
+ DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
+ await changeBuilder.addFileEdit(file, fileStamp, |
+ (DartFileEditBuilder builder) { |
+ builder.addInsertion(insertOffset, (DartEditBuilder builder) { |
+ builder.write(prefix); |
+ // add super constructor name |
+ builder.write('super'); |
+ if (!isEmpty(constructorName)) { |
+ builder.write('.'); |
+ builder.write(constructorName); |
+ } |
+ // add arguments |
+ builder.write('('); |
+ bool firstParameter = true; |
+ for (ParameterElement parameter in superConstructor.parameters) { |
+ // skip non-required parameters |
+ if (parameter.parameterKind != ParameterKind.REQUIRED) { |
+ break; |
+ } |
+ // comma |
+ if (firstParameter) { |
+ firstParameter = false; |
+ } else { |
+ builder.write(', '); |
+ } |
+ // default value |
+ DartType parameterType = parameter.type; |
+ builder.addLinkedEdit(parameter.name, |
+ (DartLinkedEditBuilder builder) { |
+ builder.write(getDefaultValueCode(parameterType)); |
+ }); |
+ } |
+ builder.write(')'); |
+ }); |
+ }); |
+ _addFixFromBuilder( |
+ changeBuilder, DartFixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION, |
+ args: [proposalName]); |
} |
} |
- void _addFix_createConstructorSuperImplicit() { |
+ Future<Null> _addFix_createConstructorSuperImplicit() async { |
ClassDeclaration targetClassNode = node.parent as ClassDeclaration; |
ClassElement targetClassElement = targetClassNode.element; |
InterfaceType superType = targetClassElement.supertype; |
@@ -1108,36 +1114,39 @@ class FixProcessor { |
// add proposal |
ClassMemberLocation targetLocation = |
utils.prepareNewConstructorLocation(targetClassNode); |
- SourceBuilder sb = new SourceBuilder(file, targetLocation.offset); |
- { |
- sb.append(targetLocation.prefix); |
- sb.append(targetClassName); |
- if (!constructorName.isEmpty) { |
- sb.startPosition('NAME'); |
- sb.append('.'); |
- sb.append(constructorName); |
- sb.endPosition(); |
- } |
- sb.append('('); |
- sb.append(parametersBuffer.toString()); |
- sb.append(') : super'); |
- if (!constructorName.isEmpty) { |
- sb.append('.'); |
- sb.append(constructorName); |
- } |
- sb.append('('); |
- sb.append(argumentsBuffer.toString()); |
- sb.append(');'); |
- sb.append(targetLocation.suffix); |
- } |
- _insertBuilder(sb, unitElement); |
- // add proposal |
String proposalName = _getConstructorProposalName(superConstructor); |
- _addFix(DartFixKind.CREATE_CONSTRUCTOR_SUPER, [proposalName]); |
+ DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
+ await changeBuilder.addFileEdit(file, fileStamp, |
+ (DartFileEditBuilder builder) { |
+ builder.addInsertion(targetLocation.offset, (DartEditBuilder builder) { |
+ builder.write(targetLocation.prefix); |
+ builder.write(targetClassName); |
+ if (!constructorName.isEmpty) { |
+ builder.addLinkedEdit('NAME', (DartLinkedEditBuilder builder) { |
+ builder.write('.'); |
+ builder.write(constructorName); |
+ }); |
+ } |
+ builder.write('('); |
+ builder.write(parametersBuffer.toString()); |
+ builder.write(') : super'); |
+ if (!constructorName.isEmpty) { |
+ builder.write('.'); |
+ builder.write(constructorName); |
+ } |
+ builder.write('('); |
+ builder.write(argumentsBuffer.toString()); |
+ builder.write(');'); |
+ builder.write(targetLocation.suffix); |
+ }); |
+ builder.importLibraries(librariesToImport); |
+ }); |
+ _addFixFromBuilder(changeBuilder, DartFixKind.CREATE_CONSTRUCTOR_SUPER, |
+ args: [proposalName]); |
} |
} |
- void _addFix_createField() { |
+ Future<Null> _addFix_createField() async { |
if (node is! SimpleIdentifier) { |
return; |
} |
@@ -1149,8 +1158,7 @@ class FixProcessor { |
AstNode nameParent = nameNode.parent; |
if (nameParent is PrefixedIdentifier) { |
target = nameParent.prefix; |
- } |
- if (nameParent is PropertyAccess) { |
+ } else if (nameParent is PropertyAccess) { |
target = nameParent.realTarget; |
} |
} |
@@ -1273,7 +1281,7 @@ class FixProcessor { |
} |
} |
- void _addFix_createGetter() { |
+ Future<Null> _addFix_createGetter() async { |
if (node is! SimpleIdentifier) { |
return; |
} |
@@ -1288,8 +1296,7 @@ class FixProcessor { |
AstNode nameParent = nameNode.parent; |
if (nameParent is PrefixedIdentifier) { |
target = nameParent.prefix; |
- } |
- if (nameParent is PropertyAccess) { |
+ } else if (nameParent is PropertyAccess) { |
target = nameParent.realTarget; |
} |
} |
@@ -1330,36 +1337,24 @@ class FixProcessor { |
ClassMemberLocation targetLocation = |
utils.prepareNewGetterLocation(targetClassNode); |
// build method source |
- String targetFile = targetClassElement.source.fullName; |
- SourceBuilder sb = new SourceBuilder(targetFile, targetLocation.offset); |
- { |
- sb.append(targetLocation.prefix); |
- // maybe "static" |
- if (staticModifier) { |
- sb.append('static '); |
- } |
- // append type |
- Expression fieldTypeNode = climbPropertyAccess(nameNode); |
- DartType fieldType = _inferUndefinedExpressionType(fieldTypeNode); |
- _appendType(sb, fieldType, groupId: 'TYPE'); |
- sb.append('get '); |
- // append name |
- { |
- sb.startPosition('NAME'); |
- sb.append(name); |
- sb.endPosition(); |
- } |
- sb.append(' => null;'); |
- sb.append(targetLocation.suffix); |
- } |
- // insert source |
- _insertBuilder(sb, targetClassElement); |
- // add linked positions |
- if (targetFile == file) { |
- _addLinkedPosition('NAME', sb, range.node(node)); |
- } |
- // add proposal |
- _addFix(DartFixKind.CREATE_GETTER, [name]); |
+ Source targetSource = targetClassElement.source; |
+ String targetFile = targetSource.fullName; |
+ DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
+ await changeBuilder.addFileEdit(targetFile, targetSource.modificationStamp, |
+ (DartFileEditBuilder builder) { |
+ builder.addInsertion(targetLocation.offset, (DartEditBuilder builder) { |
+ Expression fieldTypeNode = climbPropertyAccess(nameNode); |
+ DartType fieldType = _inferUndefinedExpressionType(fieldTypeNode); |
+ builder.write(targetLocation.prefix); |
+ builder.writeGetterDeclaration(name, |
+ isStatic: staticModifier, |
+ nameGroupName: 'NAME', |
+ returnType: fieldType, |
+ returnTypeGroupName: 'TYPE'); |
+ builder.write(targetLocation.suffix); |
+ }); |
+ }); |
+ _addFixFromBuilder(changeBuilder, DartFixKind.CREATE_GETTER, args: [name]); |
} |
void _addFix_createImportUri() { |
@@ -1380,7 +1375,7 @@ class FixProcessor { |
} |
} |
- void _addFix_createLocalVariable() { |
+ Future<Null> _addFix_createLocalVariable() async { |
if (node is! SimpleIdentifier) { |
return; |
} |
@@ -1392,8 +1387,13 @@ class FixProcessor { |
if (assignment.leftHandSide == node && |
assignment.operator.type == TokenType.EQ && |
assignment.parent is ExpressionStatement) { |
- _addInsertEdit(node.offset, 'var '); |
- _addFix(DartFixKind.CREATE_LOCAL_VARIABLE, [name]); |
+ DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
+ await changeBuilder.addFileEdit(file, fileStamp, |
+ (DartFileEditBuilder builder) { |
+ builder.addSimpleInsertion(node.offset, 'var '); |
+ }); |
+ _addFixFromBuilder(changeBuilder, DartFixKind.CREATE_LOCAL_VARIABLE, |
+ args: [name]); |
return; |
} |
} |
@@ -1403,35 +1403,29 @@ class FixProcessor { |
return; |
} |
String prefix = utils.getNodePrefix(target); |
- // build variable declaration source |
- SourceBuilder sb = new SourceBuilder(file, target.offset); |
- { |
- // append type |
- DartType type = _inferUndefinedExpressionType(node); |
- if (!(type == null || |
- type is InterfaceType || |
- type is FunctionType && |
- type.element != null && |
- !type.element.isSynthetic)) { |
- return; |
- } |
- _appendType(sb, type, groupId: 'TYPE', orVar: true); |
- // append name |
- { |
- sb.startPosition('NAME'); |
- sb.append(name); |
- sb.endPosition(); |
- } |
- sb.append(';'); |
- sb.append(eol); |
- sb.append(prefix); |
+ // compute type |
+ DartType type = _inferUndefinedExpressionType(node); |
+ if (!(type == null || |
+ type is InterfaceType || |
+ type is FunctionType && |
+ type.element != null && |
+ !type.element.isSynthetic)) { |
+ return; |
} |
- // insert source |
- _insertBuilder(sb, unitElement); |
- // add linked positions |
- _addLinkedPosition('NAME', sb, range.node(node)); |
- // add proposal |
- _addFix(DartFixKind.CREATE_LOCAL_VARIABLE, [name]); |
+ // build variable declaration source |
+ DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
+ await changeBuilder.addFileEdit(file, fileStamp, |
+ (DartFileEditBuilder builder) { |
+ builder.addInsertion(target.offset, (DartEditBuilder builder) { |
+ builder.writeLocalVariableDeclaration(name, |
+ nameGroupName: 'NAME', type: type, typeGroupName: 'TYPE'); |
+ builder.write(eol); |
+ builder.write(prefix); |
+ }); |
+ builder.addLinkedPosition(range.node(node), 'NAME'); |
+ }); |
+ _addFixFromBuilder(changeBuilder, DartFixKind.CREATE_LOCAL_VARIABLE, |
+ args: [name]); |
} |
void _addFix_createMissingOverrides() { |
@@ -1570,29 +1564,28 @@ class FixProcessor { |
utils.targetExecutableElement = null; |
} |
- void _addFix_createNoSuchMethod() { |
+ Future<Null> _addFix_createNoSuchMethod() async { |
ClassDeclaration targetClass = node.parent as ClassDeclaration; |
// prepare environment |
String prefix = utils.getIndent(1); |
int insertOffset = targetClass.end - 1; |
- // prepare source |
- SourceBuilder sb = new SourceBuilder(file, insertOffset); |
- { |
- // insert empty line before existing member |
- if (!targetClass.members.isEmpty) { |
- sb.append(eol); |
- } |
- // append method |
- sb.append(prefix); |
- sb.append( |
- 'noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);'); |
- sb.append(eol); |
- } |
- // done |
- _insertBuilder(sb, unitElement); |
- exitPosition = new Position(file, insertOffset); |
- // add proposal |
- _addFix(DartFixKind.CREATE_NO_SUCH_METHOD, []); |
+ DartChangeBuilder changeBuilder = new DartChangeBuilder(driver); |
+ await changeBuilder.addFileEdit(file, fileStamp, |
+ (DartFileEditBuilder builder) { |
+ builder.addInsertion(insertOffset, (DartEditBuilder builder) { |
+ builder.selectHere(); |
+ // insert empty line before existing member |
+ if (!targetClass.members.isEmpty) { |
+ builder.write(eol); |
+ } |
+ // append method |
+ builder.write(prefix); |
+ builder.write( |
+ 'noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);'); |
+ builder.write(eol); |
+ }); |
+ }); |
+ _addFixFromBuilder(changeBuilder, DartFixKind.CREATE_NO_SUCH_METHOD); |
} |
void _addFix_createPartUri() { |
@@ -2499,6 +2492,16 @@ class FixProcessor { |
} |
} |
+ void _addFixFromBuilder(DartChangeBuilder builder, FixKind kind, |
+ {List args: null, bool importsOnly: false}) { |
+ SourceChange change = builder.sourceChange; |
+ if (change.edits.isEmpty && !importsOnly) { |
+ return; |
+ } |
+ change.message = formatList(kind.message, args); |
+ fixes.add(new Fix(kind, change)); |
+ } |
+ |
/** |
* Adds a new [SourceEdit] to [change]. |
*/ |
@@ -3150,18 +3153,6 @@ class FixProcessor { |
} |
} |
- void _replaceReturnTypeWithFuture(AstNode node, TypeProvider typeProvider) { |
- for (; node != null; node = node.parent) { |
- if (node is FunctionDeclaration) { |
- _replaceTypeWithFuture(node.returnType, typeProvider); |
- return; |
- } else if (node is MethodDeclaration) { |
- _replaceTypeWithFuture(node.returnType, typeProvider); |
- return; |
- } |
- } |
- } |
- |
void _replaceTypeWithFuture( |
TypeAnnotation typeName, TypeProvider typeProvider) { |
InterfaceType futureType = typeProvider.futureType; |