Index: pkg/analysis_server/lib/src/services/refactoring/extract_local.dart |
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart |
index ad42a6eb27d8e9f9f1cc34959163bfe2c0630108..f238cd554e5b1e5a398adb4f340dd3d4185aa04b 100644 |
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart |
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart |
@@ -59,6 +59,7 @@ class ExtractLocalRefactoringImpl extends RefactoringImpl |
unitElement = unit.element; |
selectionRange = new SourceRange(selectionOffset, selectionLength); |
utils = new CorrectionUtils(unit); |
+ file = unitElement.source.fullName; |
} |
@override |
@@ -117,6 +118,7 @@ class ExtractLocalRefactoringImpl extends RefactoringImpl |
} else { |
occurrences = [selectionRange]; |
} |
+ occurrences.sort((a, b) => a.offset - b.offset); |
// If the whole expression of a statement is selected, like '1 + 2', |
// then convert it into a variable declaration statement. |
if (wholeStatementExpression && occurrences.length == 1) { |
@@ -127,36 +129,53 @@ class ExtractLocalRefactoringImpl extends RefactoringImpl |
doSourceChange_addElementEdit(change, unitElement, edit); |
return new Future.value(change); |
} |
+ // prepare positions |
+ List<Position> positions = <Position>[]; |
+ int occurrencesShift = 0; |
+ void addPosition(int offset) { |
+ positions.add(new Position(file, offset)); |
+ } |
// add variable declaration |
{ |
- String declarationSource; |
+ String declarationCode; |
+ int nameOffsetInDeclarationCode; |
if (stringLiteralPart != null) { |
- declarationSource = "var $name = '$stringLiteralPart';"; |
+ declarationCode = 'var '; |
+ nameOffsetInDeclarationCode = declarationCode.length; |
+ declarationCode += "$name = '$stringLiteralPart';"; |
} else { |
String keyword = _declarationKeyword; |
- String initializerSource = utils.getRangeText(selectionRange); |
- declarationSource = "$keyword $name = $initializerSource;"; |
+ String initializerCode = utils.getRangeText(selectionRange); |
+ declarationCode = '$keyword '; |
+ nameOffsetInDeclarationCode = declarationCode.length; |
+ declarationCode += '$name = $initializerCode;'; |
} |
- String eol = utils.endOfLine; |
// prepare location for declaration |
AstNode target = _findDeclarationTarget(occurrences); |
+ String eol = utils.endOfLine; |
// insert variable declaration |
if (target is Statement) { |
String prefix = utils.getNodePrefix(target); |
SourceEdit edit = |
- new SourceEdit(target.offset, 0, declarationSource + eol + prefix); |
+ new SourceEdit(target.offset, 0, declarationCode + eol + prefix); |
doSourceChange_addElementEdit(change, unitElement, edit); |
+ addPosition(edit.offset + nameOffsetInDeclarationCode); |
+ occurrencesShift = edit.replacement.length; |
} else if (target is ExpressionFunctionBody) { |
String prefix = utils.getNodePrefix(target.parent); |
String indent = utils.getIndent(1); |
- String declStatement = prefix + indent + declarationSource + eol; |
- String exprStatement = prefix + indent + 'return '; |
Expression expr = target.expression; |
- doSourceChange_addElementEdit( |
- change, |
- unitElement, |
- new SourceEdit(target.offset, expr.offset - target.offset, |
- '{' + eol + declStatement + exprStatement)); |
+ { |
+ String code = '{' + eol + prefix + indent; |
+ addPosition( |
+ target.offset + code.length + nameOffsetInDeclarationCode); |
+ code += declarationCode + eol; |
+ code += prefix + indent + 'return '; |
+ SourceEdit edit = |
+ new SourceEdit(target.offset, expr.offset - target.offset, code); |
+ occurrencesShift = target.offset + code.length - expr.offset; |
+ doSourceChange_addElementEdit(change, unitElement, edit); |
+ } |
doSourceChange_addElementEdit(change, unitElement, |
new SourceEdit(expr.end, 0, ';' + eol + prefix + '}')); |
} |
@@ -165,12 +184,23 @@ class ExtractLocalRefactoringImpl extends RefactoringImpl |
String occurrenceReplacement = name; |
if (stringLiteralPart != null) { |
occurrenceReplacement = "\${$name}"; |
+ occurrencesShift += 2; |
} |
// replace occurrences with variable reference |
for (SourceRange range in occurrences) { |
SourceEdit edit = newSourceEdit_range(range, occurrenceReplacement); |
+ addPosition(range.offset + occurrencesShift); |
+ occurrencesShift += name.length - range.length; |
doSourceChange_addElementEdit(change, unitElement, edit); |
} |
+ // add the linked group |
+ change.addLinkedEditGroup(new LinkedEditGroup( |
+ positions, |
+ name.length, |
+ names |
+ .map((name) => new LinkedEditSuggestion( |
+ name, LinkedEditSuggestionKind.VARIABLE)) |
+ .toList())); |
// done |
return new Future.value(change); |
} |
@@ -194,8 +224,9 @@ class ExtractLocalRefactoringImpl extends RefactoringImpl |
selectionRange = new SourceRange(offset, end - offset); |
} |
// get covering node |
- AstNode coveringNode = new NodeLocator( |
- selectionRange.offset, selectionRange.end).searchWithin(unit); |
+ AstNode coveringNode = |
+ new NodeLocator(selectionRange.offset, selectionRange.end) |
+ .searchWithin(unit); |
// compute covering expressions |
for (AstNode node = coveringNode; |
node is Expression || node is ArgumentList; |