| Index: pkg/analysis_server/lib/src/services/correction/assist_internal.dart
|
| diff --git a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
|
| index b26a22588d219d745b02cf827b8b64a462234145..11c253a8b68d77e7a70eb0fffcd76eb8eb5820a8 100644
|
| --- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
|
| +++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
|
| @@ -7,11 +7,9 @@ import 'dart:collection';
|
|
|
| import 'package:analysis_server/plugin/edit/assist/assist_core.dart';
|
| import 'package:analysis_server/plugin/edit/assist/assist_dart.dart';
|
| -import 'package:analysis_server/src/protocol_server.dart' hide Element;
|
| import 'package:analysis_server/src/services/correction/assist.dart';
|
| import 'package:analysis_server/src/services/correction/flutter_util.dart';
|
| import 'package:analysis_server/src/services/correction/name_suggestion.dart';
|
| -import 'package:analysis_server/src/services/correction/source_buffer.dart';
|
| import 'package:analysis_server/src/services/correction/statement_analyzer.dart';
|
| import 'package:analysis_server/src/services/correction/util.dart';
|
| import 'package:analysis_server/src/services/search/hierarchy.dart';
|
| @@ -27,6 +25,8 @@ import 'package:analyzer/src/dart/ast/utilities.dart';
|
| import 'package:analyzer/src/generated/java_core.dart';
|
| import 'package:analyzer/src/generated/resolver.dart';
|
| import 'package:analyzer/src/generated/source.dart';
|
| +import 'package:analyzer_plugin/protocol/protocol_common.dart' hide Element;
|
| +import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
|
| import 'package:analyzer_plugin/utilities/range_factory.dart';
|
| import 'package:path/path.dart';
|
|
|
| @@ -57,14 +57,12 @@ class AssistProcessor {
|
| int selectionEnd;
|
|
|
| final List<Assist> assists = <Assist>[];
|
| - final Map<String, LinkedEditGroup> linkedPositionGroups =
|
| - <String, LinkedEditGroup>{};
|
| +
|
| Position exitPosition = null;
|
|
|
| CorrectionUtils utils;
|
| - AstNode node;
|
|
|
| - SourceChange change = new SourceChange('<message>');
|
| + AstNode node;
|
|
|
| TypeProvider _typeProvider;
|
|
|
| @@ -118,44 +116,44 @@ class AssistProcessor {
|
| if (node == null) {
|
| return assists;
|
| }
|
| - // try to add proposals
|
| - _addProposal_addTypeAnnotation_DeclaredIdentifier();
|
| - _addProposal_addTypeAnnotation_SimpleFormalParameter();
|
| - _addProposal_addTypeAnnotation_VariableDeclaration();
|
| - _addProposal_assignToLocalVariable();
|
| - _addProposal_convertIntoFinalField();
|
| - _addProposal_convertIntoGetter();
|
| - _addProposal_convertDocumentationIntoBlock();
|
| - _addProposal_convertDocumentationIntoLine();
|
| - _addProposal_convertToBlockFunctionBody();
|
| - _addProposal_convertToExpressionFunctionBody();
|
| - _addProposal_convertFlutterChild();
|
| - _addProposal_convertToForIndexLoop();
|
| - _addProposal_convertToIsNot_onIs();
|
| - _addProposal_convertToIsNot_onNot();
|
| - _addProposal_convertToIsNotEmpty();
|
| - _addProposal_convertToFieldParameter();
|
| - _addProposal_convertToNormalParameter();
|
| - _addProposal_encapsulateField();
|
| - _addProposal_exchangeOperands();
|
| - _addProposal_importAddShow();
|
| - _addProposal_introduceLocalTestedType();
|
| - _addProposal_invertIf();
|
| - _addProposal_joinIfStatementInner();
|
| - _addProposal_joinIfStatementOuter();
|
| - _addProposal_joinVariableDeclaration_onAssignment();
|
| - _addProposal_joinVariableDeclaration_onDeclaration();
|
| - _addProposal_moveFlutterWidgetDown();
|
| - _addProposal_moveFlutterWidgetUp();
|
| - _addProposal_removeTypeAnnotation();
|
| - _addProposal_reparentFlutterList();
|
| - _addProposal_reparentFlutterWidget();
|
| - _addProposal_replaceConditionalWithIfElse();
|
| - _addProposal_replaceIfElseWithConditional();
|
| - _addProposal_splitAndCondition();
|
| - _addProposal_splitVariableDeclaration();
|
| - _addProposal_surroundWith();
|
| - // done
|
| +
|
| + await _addProposal_addTypeAnnotation_DeclaredIdentifier();
|
| + await _addProposal_addTypeAnnotation_SimpleFormalParameter();
|
| + await _addProposal_addTypeAnnotation_VariableDeclaration();
|
| + await _addProposal_assignToLocalVariable();
|
| + await _addProposal_convertIntoFinalField();
|
| + await _addProposal_convertIntoGetter();
|
| + await _addProposal_convertDocumentationIntoBlock();
|
| + await _addProposal_convertDocumentationIntoLine();
|
| + await _addProposal_convertToBlockFunctionBody();
|
| + await _addProposal_convertToExpressionFunctionBody();
|
| + await _addProposal_convertFlutterChild();
|
| + await _addProposal_convertToForIndexLoop();
|
| + await _addProposal_convertToIsNot_onIs();
|
| + await _addProposal_convertToIsNot_onNot();
|
| + await _addProposal_convertToIsNotEmpty();
|
| + await _addProposal_convertToFieldParameter();
|
| + await _addProposal_convertToNormalParameter();
|
| + await _addProposal_encapsulateField();
|
| + await _addProposal_exchangeOperands();
|
| + await _addProposal_importAddShow();
|
| + await _addProposal_introduceLocalTestedType();
|
| + await _addProposal_invertIf();
|
| + await _addProposal_joinIfStatementInner();
|
| + await _addProposal_joinIfStatementOuter();
|
| + await _addProposal_joinVariableDeclaration_onAssignment();
|
| + await _addProposal_joinVariableDeclaration_onDeclaration();
|
| + await _addProposal_moveFlutterWidgetDown();
|
| + await _addProposal_moveFlutterWidgetUp();
|
| + await _addProposal_removeTypeAnnotation();
|
| + await _addProposal_reparentFlutterList();
|
| + await _addProposal_reparentFlutterWidget();
|
| + await _addProposal_replaceConditionalWithIfElse();
|
| + await _addProposal_replaceIfElseWithConditional();
|
| + await _addProposal_splitAndCondition();
|
| + await _addProposal_splitVariableDeclaration();
|
| + await _addProposal_surroundWith();
|
| +
|
| return assists;
|
| }
|
|
|
| @@ -191,43 +189,18 @@ class AssistProcessor {
|
| return null;
|
| }
|
|
|
| - void _addAssist(AssistKind kind, List args, {String assistFile}) {
|
| - if (assistFile == null) {
|
| - assistFile = file;
|
| - }
|
| - // check is there are any edits
|
| + void _addAssistFromBuilder(DartChangeBuilder builder, AssistKind kind,
|
| + {List args: null}) {
|
| + SourceChange change = builder.sourceChange;
|
| if (change.edits.isEmpty) {
|
| _coverageMarker();
|
| return;
|
| }
|
| - // prepare Change
|
| change.message = formatList(kind.message, args);
|
| - linkedPositionGroups.values
|
| - .forEach((group) => change.addLinkedEditGroup(group));
|
| - change.selection = exitPosition;
|
| - // add Assist
|
| - Assist assist = new Assist(kind, change);
|
| - assists.add(assist);
|
| - // clear
|
| - change = new SourceChange('<message>');
|
| - linkedPositionGroups.clear();
|
| - exitPosition = null;
|
| - }
|
| -
|
| - void _addIndentEdit(SourceRange range, String oldIndent, String newIndent) {
|
| - SourceEdit edit = utils.createIndentEdit(range, oldIndent, newIndent);
|
| - doSourceChange_addElementEdit(change, unitElement, edit);
|
| + assists.add(new Assist(kind, change));
|
| }
|
|
|
| - /**
|
| - * Adds a new [Edit] to [edits].
|
| - */
|
| - void _addInsertEdit(int offset, String text) {
|
| - SourceEdit edit = new SourceEdit(offset, 0, text);
|
| - doSourceChange_addElementEdit(change, unitElement, edit);
|
| - }
|
| -
|
| - void _addProposal_addTypeAnnotation_DeclaredIdentifier() {
|
| + Future<Null> _addProposal_addTypeAnnotation_DeclaredIdentifier() async {
|
| DeclaredIdentifier declaredIdentifier =
|
| node.getAncestor((n) => n is DeclaredIdentifier);
|
| if (declaredIdentifier == null) {
|
| @@ -243,40 +216,41 @@ class AssistProcessor {
|
| _coverageMarker();
|
| return;
|
| }
|
| - // may be has type annotation already
|
| + // Ensure that there isn't already a type annotation.
|
| if (declaredIdentifier.type != null) {
|
| _coverageMarker();
|
| return;
|
| }
|
| - // prepare type source
|
| - String typeSource;
|
| DartType type = declaredIdentifier.identifier.bestType;
|
| - if (type is InterfaceType || type is FunctionType) {
|
| - _configureTargetLocation(node);
|
| - Set<Source> librariesToImport = new Set<Source>();
|
| - typeSource = utils.getTypeSource(type, librariesToImport);
|
| - addLibraryImports(change, unitLibraryElement, librariesToImport);
|
| - } else {
|
| + if (type is! InterfaceType && type is! FunctionType) {
|
| _coverageMarker();
|
| return;
|
| }
|
| - // type source might be null, if the type is private
|
| + _configureTargetLocation(node);
|
| + Set<Source> librariesToImport = new Set<Source>();
|
| + String typeSource = utils.getTypeSource(type, librariesToImport);
|
| if (typeSource == null) {
|
| + // The type source might be null if the type is private.
|
| _coverageMarker();
|
| return;
|
| }
|
| - // add edit
|
| - Token keyword = declaredIdentifier.keyword;
|
| - if (keyword.keyword == Keyword.VAR) {
|
| - _addReplaceEdit(range.token(keyword), typeSource);
|
| - } else {
|
| - _addInsertEdit(declaredIdentifier.identifier.offset, '$typeSource ');
|
| - }
|
| - // add proposal
|
| - _addAssist(DartAssistKind.ADD_TYPE_ANNOTATION, []);
|
| +
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + Token keyword = declaredIdentifier.keyword;
|
| + if (keyword.keyword == Keyword.VAR) {
|
| + builder.addSimpleReplacement(range.token(keyword), typeSource);
|
| + } else {
|
| + builder.addSimpleInsertion(
|
| + declaredIdentifier.identifier.offset, '$typeSource ');
|
| + }
|
| + builder.importLibraries(librariesToImport);
|
| + });
|
| + _addAssistFromBuilder(changeBuilder, DartAssistKind.ADD_TYPE_ANNOTATION);
|
| }
|
|
|
| - void _addProposal_addTypeAnnotation_SimpleFormalParameter() {
|
| + Future<Null> _addProposal_addTypeAnnotation_SimpleFormalParameter() async {
|
| AstNode node = this.node;
|
| // should be the name of a simple parameter
|
| if (node is! SimpleIdentifier || node.parent is! SimpleFormalParameter) {
|
| @@ -301,25 +275,25 @@ class AssistProcessor {
|
| return;
|
| }
|
| // prepare type source
|
| - String typeSource;
|
| - {
|
| - _configureTargetLocation(node);
|
| - Set<Source> librariesToImport = new Set<Source>();
|
| - typeSource = utils.getTypeSource(type, librariesToImport);
|
| - addLibraryImports(change, unitLibraryElement, librariesToImport);
|
| - }
|
| + _configureTargetLocation(node);
|
| + Set<Source> librariesToImport = new Set<Source>();
|
| + String typeSource = utils.getTypeSource(type, librariesToImport);
|
| // type source might be null, if the type is private
|
| if (typeSource == null) {
|
| _coverageMarker();
|
| return;
|
| }
|
| - // add edit
|
| - _addInsertEdit(name.offset, '$typeSource ');
|
| - // add proposal
|
| - _addAssist(DartAssistKind.ADD_TYPE_ANNOTATION, []);
|
| +
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + builder.addSimpleInsertion(name.offset, '$typeSource ');
|
| + builder.importLibraries(librariesToImport);
|
| + });
|
| + _addAssistFromBuilder(changeBuilder, DartAssistKind.ADD_TYPE_ANNOTATION);
|
| }
|
|
|
| - void _addProposal_addTypeAnnotation_VariableDeclaration() {
|
| + Future<Null> _addProposal_addTypeAnnotation_VariableDeclaration() async {
|
| AstNode node = this.node;
|
| // prepare VariableDeclarationList
|
| VariableDeclarationList declarationList =
|
| @@ -353,33 +327,54 @@ class AssistProcessor {
|
| }
|
| DartType type = initializer.bestType;
|
| // prepare type source
|
| - String typeSource;
|
| - if (type is InterfaceType && !type.isDartCoreNull || type is FunctionType) {
|
| - _configureTargetLocation(node);
|
| - Set<Source> librariesToImport = new Set<Source>();
|
| - typeSource = utils.getTypeSource(type, librariesToImport);
|
| - addLibraryImports(change, unitLibraryElement, librariesToImport);
|
| - } else {
|
| + if ((type is! InterfaceType || type.isDartCoreNull) &&
|
| + type is! FunctionType) {
|
| _coverageMarker();
|
| return;
|
| }
|
| + _configureTargetLocation(node);
|
| + Set<Source> librariesToImport = new Set<Source>();
|
| + String typeSource = utils.getTypeSource(type, librariesToImport);
|
| // type source might be null, if the type is private
|
| if (typeSource == null) {
|
| _coverageMarker();
|
| return;
|
| }
|
| - // add edit
|
| - Token keyword = declarationList.keyword;
|
| - if (keyword?.keyword == Keyword.VAR) {
|
| - _addReplaceEdit(range.token(keyword), typeSource);
|
| +
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + if (unitLibraryFile == file) {
|
| + // TODO(brianwilkerson) Make ChangeBuilder merge multiple edits to the
|
| + // same file so that only the else block is necessary.
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + Token keyword = declarationList.keyword;
|
| + if (keyword?.keyword == Keyword.VAR) {
|
| + builder.addSimpleReplacement(range.token(keyword), typeSource);
|
| + } else {
|
| + builder.addSimpleInsertion(variable.offset, '$typeSource ');
|
| + }
|
| + builder.importLibraries(librariesToImport);
|
| + });
|
| } else {
|
| - _addInsertEdit(variable.offset, '$typeSource ');
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + Token keyword = declarationList.keyword;
|
| + if (keyword?.keyword == Keyword.VAR) {
|
| + builder.addSimpleReplacement(range.token(keyword), typeSource);
|
| + } else {
|
| + builder.addSimpleInsertion(variable.offset, '$typeSource ');
|
| + }
|
| + });
|
| + await changeBuilder
|
| + .addFileEdit(unitLibraryFile, _modificationStamp(unitLibraryFile),
|
| + (DartFileEditBuilder builder) {
|
| + builder.importLibraries(librariesToImport);
|
| + });
|
| }
|
| - // add proposal
|
| - _addAssist(DartAssistKind.ADD_TYPE_ANNOTATION, []);
|
| + _addAssistFromBuilder(changeBuilder, DartAssistKind.ADD_TYPE_ANNOTATION);
|
| }
|
|
|
| - void _addProposal_assignToLocalVariable() {
|
| + Future<Null> _addProposal_assignToLocalVariable() async {
|
| // prepare enclosing ExpressionStatement
|
| ExpressionStatement expressionStatement;
|
| for (AstNode node = this.node; node != null; node = node.parent) {
|
| @@ -408,111 +403,124 @@ class AssistProcessor {
|
| _coverageMarker();
|
| return;
|
| }
|
| - // prepare source
|
| - SourceBuilder builder = new SourceBuilder(file, offset);
|
| - builder.append('var ');
|
| // prepare excluded names
|
| Set<String> excluded = new Set<String>();
|
| - {
|
| - ScopedNameFinder scopedNameFinder = new ScopedNameFinder(offset);
|
| - expression.accept(scopedNameFinder);
|
| - excluded.addAll(scopedNameFinder.locals.keys.toSet());
|
| - }
|
| - // name(s)
|
| - {
|
| - List<String> suggestions =
|
| - getVariableNameSuggestionsForExpression(type, expression, excluded);
|
| - builder.startPosition('NAME');
|
| - for (int i = 0; i < suggestions.length; i++) {
|
| - String name = suggestions[i];
|
| - if (i == 0) {
|
| - builder.append(name);
|
| - }
|
| - builder.addSuggestion(LinkedEditSuggestionKind.VARIABLE, name);
|
| - }
|
| - builder.endPosition();
|
| + ScopedNameFinder scopedNameFinder = new ScopedNameFinder(offset);
|
| + expression.accept(scopedNameFinder);
|
| + excluded.addAll(scopedNameFinder.locals.keys.toSet());
|
| + List<String> suggestions =
|
| + getVariableNameSuggestionsForExpression(type, expression, excluded);
|
| +
|
| + if (suggestions.isNotEmpty) {
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + builder.addInsertion(offset, (DartEditBuilder builder) {
|
| + builder.write('var ');
|
| + builder.addSimpleLinkedEdit('NAME', suggestions[0],
|
| + kind: LinkedEditSuggestionKind.VARIABLE,
|
| + suggestions: suggestions);
|
| + builder.write(' = ');
|
| + });
|
| + });
|
| + _addAssistFromBuilder(
|
| + changeBuilder, DartAssistKind.ASSIGN_TO_LOCAL_VARIABLE);
|
| }
|
| - builder.append(' = ');
|
| - // add proposal
|
| - _insertBuilder(builder);
|
| - _addAssist(DartAssistKind.ASSIGN_TO_LOCAL_VARIABLE, []);
|
| }
|
|
|
| - void _addProposal_convertDocumentationIntoBlock() {
|
| + Future<Null> _addProposal_convertDocumentationIntoBlock() async {
|
| Comment comment = node.getAncestor((n) => n is Comment);
|
| - if (comment != null && comment.isDocumentation) {
|
| - String prefix = utils.getNodePrefix(comment);
|
| - SourceBuilder sb = new SourceBuilder(file, comment.offset);
|
| - sb.append('/**');
|
| - sb.append(eol);
|
| - for (Token token in comment.tokens) {
|
| - if (token is DocumentationCommentToken &&
|
| - token.type == TokenType.SINGLE_LINE_COMMENT) {
|
| - sb.append(prefix);
|
| - sb.append(' *');
|
| - sb.append(token.lexeme.substring('///'.length));
|
| - sb.append(eol);
|
| - } else {
|
| - return;
|
| - }
|
| - }
|
| - sb.append(prefix);
|
| - sb.append(' */');
|
| - _insertBuilder(sb, comment.length);
|
| + if (comment == null || !comment.isDocumentation) {
|
| + return;
|
| }
|
| - // add proposal
|
| - _addAssist(DartAssistKind.CONVERT_DOCUMENTATION_INTO_BLOCK, []);
|
| + var tokens = comment.tokens;
|
| + if (tokens.isEmpty ||
|
| + tokens.any((Token token) =>
|
| + token is! DocumentationCommentToken ||
|
| + token.type != TokenType.SINGLE_LINE_COMMENT)) {
|
| + return;
|
| + }
|
| + String prefix = utils.getNodePrefix(comment);
|
| +
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + builder.addReplacement(range.node(comment), (DartEditBuilder builder) {
|
| + builder.writeln('/**');
|
| + for (Token token in comment.tokens) {
|
| + builder.write(prefix);
|
| + builder.write(' *');
|
| + builder.writeln(token.lexeme.substring('///'.length));
|
| + }
|
| + builder.write(prefix);
|
| + builder.write(' */');
|
| + });
|
| + });
|
| + _addAssistFromBuilder(
|
| + changeBuilder, DartAssistKind.CONVERT_DOCUMENTATION_INTO_BLOCK);
|
| }
|
|
|
| - void _addProposal_convertDocumentationIntoLine() {
|
| + Future<Null> _addProposal_convertDocumentationIntoLine() async {
|
| Comment comment = node.getAncestor((n) => n is Comment);
|
| - if (comment != null && comment.isDocumentation) {
|
| - if (comment.tokens.length == 1) {
|
| - Token token = comment.tokens.first;
|
| - if (token.type == TokenType.MULTI_LINE_COMMENT) {
|
| - String text = token.lexeme;
|
| - List<String> lines = text.split('\n');
|
| - String prefix = utils.getNodePrefix(comment);
|
| - SourceBuilder sb = new SourceBuilder(file, comment.offset);
|
| - bool firstLine = true;
|
| - String linePrefix = '';
|
| - for (String line in lines) {
|
| - if (firstLine) {
|
| - firstLine = false;
|
| - String expectedPrefix = '/**';
|
| - if (!line.startsWith(expectedPrefix)) {
|
| - return;
|
| - }
|
| - line = line.substring(expectedPrefix.length).trim();
|
| - if (line.isNotEmpty) {
|
| - sb.append('/// ');
|
| - sb.append(line);
|
| - linePrefix = eol + prefix;
|
| - }
|
| - } else {
|
| - if (line.startsWith(prefix + ' */')) {
|
| - break;
|
| - }
|
| - String expectedPrefix = prefix + ' * ';
|
| - if (!line.startsWith(expectedPrefix)) {
|
| - return;
|
| - }
|
| - line = line.substring(expectedPrefix.length).trim();
|
| - sb.append(linePrefix);
|
| - sb.append('/// ');
|
| - sb.append(line);
|
| - linePrefix = eol + prefix;
|
| - }
|
| - }
|
| - _insertBuilder(sb, comment.length);
|
| + if (comment == null ||
|
| + !comment.isDocumentation ||
|
| + comment.tokens.length != 1) {
|
| + _coverageMarker();
|
| + return;
|
| + }
|
| + Token token = comment.tokens.first;
|
| + if (token.type != TokenType.MULTI_LINE_COMMENT) {
|
| + _coverageMarker();
|
| + return;
|
| + }
|
| + String text = token.lexeme;
|
| + List<String> lines = text.split('\n');
|
| + String prefix = utils.getNodePrefix(comment);
|
| + List<String> newLines = <String>[];
|
| + bool firstLine = true;
|
| + String linePrefix = '';
|
| + for (String line in lines) {
|
| + if (firstLine) {
|
| + firstLine = false;
|
| + String expectedPrefix = '/**';
|
| + if (!line.startsWith(expectedPrefix)) {
|
| + _coverageMarker();
|
| + return;
|
| + }
|
| + line = line.substring(expectedPrefix.length).trim();
|
| + if (line.isNotEmpty) {
|
| + newLines.add('/// $line');
|
| + linePrefix = eol + prefix;
|
| + }
|
| + } else {
|
| + if (line.startsWith(prefix + ' */')) {
|
| + break;
|
| }
|
| + String expectedPrefix = prefix + ' * ';
|
| + if (!line.startsWith(expectedPrefix)) {
|
| + _coverageMarker();
|
| + return;
|
| + }
|
| + line = line.substring(expectedPrefix.length).trim();
|
| + newLines.add('$linePrefix/// $line');
|
| + linePrefix = eol + prefix;
|
| }
|
| }
|
| - // add proposal
|
| - _addAssist(DartAssistKind.CONVERT_DOCUMENTATION_INTO_LINE, []);
|
| +
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + builder.addReplacement(range.node(comment), (DartEditBuilder builder) {
|
| + for (String newLine in newLines) {
|
| + builder.write(newLine);
|
| + }
|
| + });
|
| + });
|
| + _addAssistFromBuilder(
|
| + changeBuilder, DartAssistKind.CONVERT_DOCUMENTATION_INTO_LINE);
|
| }
|
|
|
| - void _addProposal_convertFlutterChild() {
|
| + Future<Null> _addProposal_convertFlutterChild() async {
|
| NamedExpression namedExp;
|
| // Allow assist to activate from either the new-expr or the child: arg.
|
| if (node is SimpleIdentifier &&
|
| @@ -547,22 +555,16 @@ class AssistProcessor {
|
| _coverageMarker();
|
| return;
|
| }
|
| - convertFlutterChildToChildren(
|
| - childArg,
|
| - namedExp,
|
| - eol,
|
| - utils.getNodeText,
|
| - utils.getLinePrefix,
|
| - utils.getIndent,
|
| - utils.getText,
|
| - _addInsertEdit,
|
| - _addRemoveEdit,
|
| - _addReplaceEdit,
|
| - range.node);
|
| - _addAssist(DartAssistKind.CONVERT_FLUTTER_CHILD, []);
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + _convertFlutterChildToChildren(childArg, namedExp, eol, utils.getNodeText,
|
| + utils.getLinePrefix, utils.getIndent, utils.getText, builder);
|
| + });
|
| + _addAssistFromBuilder(changeBuilder, DartAssistKind.CONVERT_FLUTTER_CHILD);
|
| }
|
|
|
| - void _addProposal_convertIntoFinalField() {
|
| + Future<Null> _addProposal_convertIntoFinalField() async {
|
| // Find the enclosing getter.
|
| MethodDeclaration getter;
|
| for (AstNode n = node; n != null; n = n.parent) {
|
| @@ -622,12 +624,18 @@ class AssistProcessor {
|
| code += ' = ' + _getNodeText(expression);
|
| }
|
| code += ';';
|
| - _addReplaceEdit(range.startEnd(beginNodeToReplace, getter), code);
|
| - _addAssist(DartAssistKind.CONVERT_INTO_FINAL_FIELD, []);
|
| + SourceRange replacementRange = range.startEnd(beginNodeToReplace, getter);
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + builder.addSimpleReplacement(replacementRange, code);
|
| + });
|
| + _addAssistFromBuilder(
|
| + changeBuilder, DartAssistKind.CONVERT_INTO_FINAL_FIELD);
|
| }
|
| }
|
|
|
| - void _addProposal_convertIntoGetter() {
|
| + Future<Null> _addProposal_convertIntoGetter() async {
|
| // Find the enclosing field declaration.
|
| FieldDeclaration fieldDeclaration;
|
| for (AstNode n = node; n != null; n = n.parent) {
|
| @@ -667,11 +675,17 @@ class AssistProcessor {
|
| code += ' ' + _getNodeText(field.name);
|
| code += ' => ' + _getNodeText(initializer);
|
| code += ';';
|
| - _addReplaceEdit(range.startEnd(fieldList.keyword, fieldDeclaration), code);
|
| - _addAssist(DartAssistKind.CONVERT_INTO_GETTER, []);
|
| + SourceRange replacementRange =
|
| + range.startEnd(fieldList.keyword, fieldDeclaration);
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + builder.addSimpleReplacement(replacementRange, code);
|
| + });
|
| + _addAssistFromBuilder(changeBuilder, DartAssistKind.CONVERT_INTO_GETTER);
|
| }
|
|
|
| - void _addProposal_convertToBlockFunctionBody() {
|
| + Future<Null> _addProposal_convertToBlockFunctionBody() async {
|
| FunctionBody body = getEnclosingFunctionBody();
|
| // prepare expression body
|
| if (body is! ExpressionFunctionBody || body.isGenerator) {
|
| @@ -684,25 +698,29 @@ class AssistProcessor {
|
| // prepare prefix
|
| String prefix = utils.getNodePrefix(body.parent);
|
| String indent = utils.getIndent(1);
|
| - // add change
|
| - SourceBuilder sb = new SourceBuilder(file, body.offset);
|
| - if (body.isAsynchronous) {
|
| - sb.append('async ');
|
| - }
|
| - sb.append('{$eol$prefix$indent');
|
| - if (!returnValueType.isVoid) {
|
| - sb.append('return ');
|
| - }
|
| - sb.append(returnValueCode);
|
| - sb.append(';');
|
| - sb.setExitOffset();
|
| - sb.append('$eol$prefix}');
|
| - _insertBuilder(sb, body.length);
|
| - // add proposal
|
| - _addAssist(DartAssistKind.CONVERT_INTO_BLOCK_BODY, []);
|
| +
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + builder.addReplacement(range.node(body), (DartEditBuilder builder) {
|
| + if (body.isAsynchronous) {
|
| + builder.write('async ');
|
| + }
|
| + builder.write('{$eol$prefix$indent');
|
| + if (!returnValueType.isVoid) {
|
| + builder.write('return ');
|
| + }
|
| + builder.write(returnValueCode);
|
| + builder.write(';');
|
| + builder.selectHere();
|
| + builder.write('$eol$prefix}');
|
| + });
|
| + });
|
| + _addAssistFromBuilder(
|
| + changeBuilder, DartAssistKind.CONVERT_INTO_BLOCK_BODY);
|
| }
|
|
|
| - void _addProposal_convertToExpressionFunctionBody() {
|
| + Future<Null> _addProposal_convertToExpressionFunctionBody() async {
|
| // prepare current body
|
| FunctionBody body = getEnclosingFunctionBody();
|
| if (body is! BlockFunctionBody || body.isGenerator) {
|
| @@ -727,23 +745,27 @@ class AssistProcessor {
|
| _coverageMarker();
|
| return;
|
| }
|
| - // add change
|
| - SourceBuilder sb = new SourceBuilder(file, body.offset);
|
| - if (body.isAsynchronous) {
|
| - sb.append('async ');
|
| - }
|
| - sb.append('=> ');
|
| - sb.append(_getNodeText(returnExpression));
|
| - if (body.parent is! FunctionExpression ||
|
| - body.parent.parent is FunctionDeclaration) {
|
| - sb.append(';');
|
| - }
|
| - _insertBuilder(sb, body.length);
|
| - // add proposal
|
| - _addAssist(DartAssistKind.CONVERT_INTO_EXPRESSION_BODY, []);
|
| +
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + builder.addReplacement(range.node(body), (DartEditBuilder builder) {
|
| + if (body.isAsynchronous) {
|
| + builder.write('async ');
|
| + }
|
| + builder.write('=> ');
|
| + builder.write(_getNodeText(returnExpression));
|
| + if (body.parent is! FunctionExpression ||
|
| + body.parent.parent is FunctionDeclaration) {
|
| + builder.write(';');
|
| + }
|
| + });
|
| + });
|
| + _addAssistFromBuilder(
|
| + changeBuilder, DartAssistKind.CONVERT_INTO_EXPRESSION_BODY);
|
| }
|
|
|
| - void _addProposal_convertToFieldParameter() {
|
| + Future<Null> _addProposal_convertToFieldParameter() async {
|
| if (node == null) {
|
| return;
|
| }
|
| @@ -810,27 +832,33 @@ class AssistProcessor {
|
| return;
|
| }
|
| String fieldName = parameterInitializer.fieldName.name;
|
| - // replace parameter
|
| - _addReplaceEdit(range.node(parameter), 'this.$fieldName');
|
| - // remove initializer
|
| - int initializerIndex = initializers.indexOf(parameterInitializer);
|
| - if (initializers.length == 1) {
|
| - _addRemoveEdit(range.endEnd(parameterList, parameterInitializer));
|
| - } else {
|
| - if (initializerIndex == 0) {
|
| - ConstructorInitializer next = initializers[initializerIndex + 1];
|
| - _addRemoveEdit(range.startStart(parameterInitializer, next));
|
| +
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + // replace parameter
|
| + builder.addSimpleReplacement(range.node(parameter), 'this.$fieldName');
|
| + // remove initializer
|
| + int initializerIndex = initializers.indexOf(parameterInitializer);
|
| + if (initializers.length == 1) {
|
| + builder
|
| + .addDeletion(range.endEnd(parameterList, parameterInitializer));
|
| } else {
|
| - ConstructorInitializer prev = initializers[initializerIndex - 1];
|
| - _addRemoveEdit(range.endEnd(prev, parameterInitializer));
|
| + if (initializerIndex == 0) {
|
| + ConstructorInitializer next = initializers[initializerIndex + 1];
|
| + builder.addDeletion(range.startStart(parameterInitializer, next));
|
| + } else {
|
| + ConstructorInitializer prev = initializers[initializerIndex - 1];
|
| + builder.addDeletion(range.endEnd(prev, parameterInitializer));
|
| + }
|
| }
|
| - }
|
| - // add proposal
|
| - _addAssist(DartAssistKind.CONVERT_TO_FIELD_PARAMETER, []);
|
| + });
|
| + _addAssistFromBuilder(
|
| + changeBuilder, DartAssistKind.CONVERT_TO_FIELD_PARAMETER);
|
| }
|
| }
|
|
|
| - void _addProposal_convertToForIndexLoop() {
|
| + Future<Null> _addProposal_convertToForIndexLoop() async {
|
| // find enclosing ForEachStatement
|
| ForEachStatement forEachStatement =
|
| node.getAncestor((n) => n is ForEachStatement);
|
| @@ -896,16 +924,20 @@ class AssistProcessor {
|
| String indent = utils.getIndent(1);
|
| int firstBlockLine = utils.getLineContentEnd(body.leftBracket.end);
|
| // add change
|
| - _addReplaceEdit(
|
| - range.startEnd(forEachStatement, forEachStatement.rightParenthesis),
|
| - 'for (int $indexName = 0; $indexName < $listName.length; $indexName++)');
|
| - _addInsertEdit(firstBlockLine,
|
| - '$prefix$indent$loopVariable = $listName[$indexName];$eol');
|
| - // add proposal
|
| - _addAssist(DartAssistKind.CONVERT_INTO_FOR_INDEX, []);
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + // TODO(brianwilkerson) Create linked positions for the loop variable.
|
| + builder.addSimpleReplacement(
|
| + range.startEnd(forEachStatement, forEachStatement.rightParenthesis),
|
| + 'for (int $indexName = 0; $indexName < $listName.length; $indexName++)');
|
| + builder.addSimpleInsertion(firstBlockLine,
|
| + '$prefix$indent$loopVariable = $listName[$indexName];$eol');
|
| + });
|
| + _addAssistFromBuilder(changeBuilder, DartAssistKind.CONVERT_INTO_FOR_INDEX);
|
| }
|
|
|
| - void _addProposal_convertToIsNot_onIs() {
|
| + Future<Null> _addProposal_convertToIsNot_onIs() async {
|
| // may be child of "is"
|
| AstNode node = this.node;
|
| while (node != null && node is! IsExpression) {
|
| @@ -939,22 +971,25 @@ class AssistProcessor {
|
| _coverageMarker();
|
| return;
|
| }
|
| - // strip !()
|
| - if (getExpressionParentPrecedence(prefExpression) >=
|
| - TokenClass.RELATIONAL_OPERATOR.precedence) {
|
| - _addRemoveEdit(range.token(prefExpression.operator));
|
| - } else {
|
| - _addRemoveEdit(
|
| - range.startEnd(prefExpression, parExpression.leftParenthesis));
|
| - _addRemoveEdit(
|
| - range.startEnd(parExpression.rightParenthesis, prefExpression));
|
| - }
|
| - _addInsertEdit(isExpression.isOperator.end, '!');
|
| - // add proposal
|
| - _addAssist(DartAssistKind.CONVERT_INTO_IS_NOT, []);
|
| +
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + if (getExpressionParentPrecedence(prefExpression) >=
|
| + TokenClass.RELATIONAL_OPERATOR.precedence) {
|
| + builder.addDeletion(range.token(prefExpression.operator));
|
| + } else {
|
| + builder.addDeletion(
|
| + range.startEnd(prefExpression, parExpression.leftParenthesis));
|
| + builder.addDeletion(
|
| + range.startEnd(parExpression.rightParenthesis, prefExpression));
|
| + }
|
| + builder.addSimpleInsertion(isExpression.isOperator.end, '!');
|
| + });
|
| + _addAssistFromBuilder(changeBuilder, DartAssistKind.CONVERT_INTO_IS_NOT);
|
| }
|
|
|
| - void _addProposal_convertToIsNot_onNot() {
|
| + Future<Null> _addProposal_convertToIsNot_onNot() async {
|
| // may be () in prefix expression
|
| if (node is ParenthesizedExpression && node.parent is PrefixExpression) {
|
| node = node.parent;
|
| @@ -988,25 +1023,28 @@ class AssistProcessor {
|
| _coverageMarker();
|
| return;
|
| }
|
| - // strip !()
|
| - if (getExpressionParentPrecedence(prefExpression) >=
|
| - TokenClass.RELATIONAL_OPERATOR.precedence) {
|
| - _addRemoveEdit(range.token(prefExpression.operator));
|
| - } else {
|
| - _addRemoveEdit(
|
| - range.startEnd(prefExpression, parExpression.leftParenthesis));
|
| - _addRemoveEdit(
|
| - range.startEnd(parExpression.rightParenthesis, prefExpression));
|
| - }
|
| - _addInsertEdit(isExpression.isOperator.end, '!');
|
| - // add proposal
|
| - _addAssist(DartAssistKind.CONVERT_INTO_IS_NOT, []);
|
| +
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + if (getExpressionParentPrecedence(prefExpression) >=
|
| + TokenClass.RELATIONAL_OPERATOR.precedence) {
|
| + builder.addDeletion(range.token(prefExpression.operator));
|
| + } else {
|
| + builder.addDeletion(
|
| + range.startEnd(prefExpression, parExpression.leftParenthesis));
|
| + builder.addDeletion(
|
| + range.startEnd(parExpression.rightParenthesis, prefExpression));
|
| + }
|
| + builder.addSimpleInsertion(isExpression.isOperator.end, '!');
|
| + });
|
| + _addAssistFromBuilder(changeBuilder, DartAssistKind.CONVERT_INTO_IS_NOT);
|
| }
|
|
|
| /**
|
| * Converts "!isEmpty" -> "isNotEmpty" if possible.
|
| */
|
| - void _addProposal_convertToIsNotEmpty() {
|
| + Future<Null> _addProposal_convertToIsNotEmpty() async {
|
| // prepare "expr.isEmpty"
|
| AstNode isEmptyAccess = null;
|
| SimpleIdentifier isEmptyIdentifier = null;
|
| @@ -1053,15 +1091,19 @@ class AssistProcessor {
|
| _coverageMarker();
|
| return;
|
| }
|
| - // do replace
|
| - _addRemoveEdit(
|
| - range.startStart(prefixExpression, prefixExpression.operand));
|
| - _addReplaceEdit(range.node(isEmptyIdentifier), 'isNotEmpty');
|
| - // add proposal
|
| - _addAssist(DartAssistKind.CONVERT_INTO_IS_NOT_EMPTY, []);
|
| +
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + builder.addDeletion(
|
| + range.startStart(prefixExpression, prefixExpression.operand));
|
| + builder.addSimpleReplacement(range.node(isEmptyIdentifier), 'isNotEmpty');
|
| + });
|
| + _addAssistFromBuilder(
|
| + changeBuilder, DartAssistKind.CONVERT_INTO_IS_NOT_EMPTY);
|
| }
|
|
|
| - void _addProposal_convertToNormalParameter() {
|
| + Future<Null> _addProposal_convertToNormalParameter() async {
|
| if (node is SimpleIdentifier &&
|
| node.parent is FieldFormalParameter &&
|
| node.parent.parent is FormalParameterList &&
|
| @@ -1075,25 +1117,31 @@ class AssistProcessor {
|
| DartType type = parameterElement.type;
|
| Set<Source> librariesToImport = new Set<Source>();
|
| String typeCode = utils.getTypeSource(type, librariesToImport);
|
| - // replace parameter
|
| - if (type.isDynamic) {
|
| - _addReplaceEdit(range.node(parameter), name);
|
| - } else {
|
| - _addReplaceEdit(range.node(parameter), '$typeCode $name');
|
| - }
|
| - // add field initializer
|
| - List<ConstructorInitializer> initializers = constructor.initializers;
|
| - if (initializers.isEmpty) {
|
| - _addInsertEdit(parameterList.end, ' : $name = $name');
|
| - } else {
|
| - _addInsertEdit(initializers.last.end, ', $name = $name');
|
| - }
|
| - // add proposal
|
| - _addAssist(DartAssistKind.CONVERT_TO_NORMAL_PARAMETER, []);
|
| +
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + // replace parameter
|
| + if (type.isDynamic) {
|
| + builder.addSimpleReplacement(range.node(parameter), name);
|
| + } else {
|
| + builder.addSimpleReplacement(
|
| + range.node(parameter), '$typeCode $name');
|
| + }
|
| + // add field initializer
|
| + List<ConstructorInitializer> initializers = constructor.initializers;
|
| + if (initializers.isEmpty) {
|
| + builder.addSimpleInsertion(parameterList.end, ' : $name = $name');
|
| + } else {
|
| + builder.addSimpleInsertion(initializers.last.end, ', $name = $name');
|
| + }
|
| + });
|
| + _addAssistFromBuilder(
|
| + changeBuilder, DartAssistKind.CONVERT_TO_NORMAL_PARAMETER);
|
| }
|
| }
|
|
|
| - void _addProposal_encapsulateField() {
|
| + Future<Null> _addProposal_encapsulateField() async {
|
| // find FieldDeclaration
|
| FieldDeclaration fieldDeclaration =
|
| node.getAncestor((x) => x is FieldDeclaration);
|
| @@ -1137,36 +1185,41 @@ class AssistProcessor {
|
| _coverageMarker();
|
| return;
|
| }
|
| - // rename field
|
| - _addReplaceEdit(range.node(nameNode), '_$name');
|
| - // update references in constructors
|
| - ClassDeclaration classDeclaration = fieldDeclaration.parent;
|
| - for (ClassMember member in classDeclaration.members) {
|
| - if (member is ConstructorDeclaration) {
|
| - for (FormalParameter parameter in member.parameters.parameters) {
|
| - ParameterElement parameterElement = parameter.element;
|
| - if (parameterElement is FieldFormalParameterElement &&
|
| - parameterElement.field == fieldElement) {
|
| - _addReplaceEdit(range.node(parameter.identifier), '_$name');
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + // rename field
|
| + builder.addSimpleReplacement(range.node(nameNode), '_$name');
|
| + // update references in constructors
|
| + ClassDeclaration classDeclaration = fieldDeclaration.parent;
|
| + for (ClassMember member in classDeclaration.members) {
|
| + if (member is ConstructorDeclaration) {
|
| + for (FormalParameter parameter in member.parameters.parameters) {
|
| + ParameterElement parameterElement = parameter.element;
|
| + if (parameterElement is FieldFormalParameterElement &&
|
| + parameterElement.field == fieldElement) {
|
| + SimpleIdentifier identifier = parameter.identifier;
|
| + builder.addSimpleReplacement(range.node(identifier), '_$name');
|
| + }
|
| }
|
| }
|
| }
|
| - }
|
| - // add accessors
|
| - String eol2 = eol + eol;
|
| - String typeNameCode =
|
| - variableList.type != null ? _getNodeText(variableList.type) + ' ' : '';
|
| - String getterCode = '$eol2 ${typeNameCode}get $name => _$name;';
|
| - String setterCode = '$eol2'
|
| - ' void set $name($typeNameCode$name) {$eol'
|
| - ' _$name = $name;$eol'
|
| - ' }';
|
| - _addInsertEdit(fieldDeclaration.end, getterCode + setterCode);
|
| - // add proposal
|
| - _addAssist(DartAssistKind.ENCAPSULATE_FIELD, []);
|
| + // add accessors
|
| + String eol2 = eol + eol;
|
| + String typeNameCode = variableList.type != null
|
| + ? _getNodeText(variableList.type) + ' '
|
| + : '';
|
| + String getterCode = '$eol2 ${typeNameCode}get $name => _$name;';
|
| + String setterCode = '$eol2'
|
| + ' void set $name($typeNameCode$name) {$eol'
|
| + ' _$name = $name;$eol'
|
| + ' }';
|
| + builder.addSimpleInsertion(fieldDeclaration.end, getterCode + setterCode);
|
| + });
|
| + _addAssistFromBuilder(changeBuilder, DartAssistKind.ENCAPSULATE_FIELD);
|
| }
|
|
|
| - void _addProposal_exchangeOperands() {
|
| + Future<Null> _addProposal_exchangeOperands() async {
|
| // check that user invokes quick assist on binary expression
|
| if (node is! BinaryExpression) {
|
| _coverageMarker();
|
| @@ -1180,51 +1233,49 @@ class AssistProcessor {
|
| return;
|
| }
|
| // add edits
|
| - {
|
| - Expression leftOperand = binaryExpression.leftOperand;
|
| - Expression rightOperand = binaryExpression.rightOperand;
|
| - // find "wide" enclosing binary expression with same operator
|
| - while (binaryExpression.parent is BinaryExpression) {
|
| - BinaryExpression newBinaryExpression =
|
| - binaryExpression.parent as BinaryExpression;
|
| - if (newBinaryExpression.operator.type !=
|
| - binaryExpression.operator.type) {
|
| - _coverageMarker();
|
| - break;
|
| - }
|
| - binaryExpression = newBinaryExpression;
|
| + Expression leftOperand = binaryExpression.leftOperand;
|
| + Expression rightOperand = binaryExpression.rightOperand;
|
| + // find "wide" enclosing binary expression with same operator
|
| + while (binaryExpression.parent is BinaryExpression) {
|
| + BinaryExpression newBinaryExpression =
|
| + binaryExpression.parent as BinaryExpression;
|
| + if (newBinaryExpression.operator.type != binaryExpression.operator.type) {
|
| + _coverageMarker();
|
| + break;
|
| }
|
| - // exchange parts of "wide" expression parts
|
| - SourceRange leftRange = range.startEnd(binaryExpression, leftOperand);
|
| - SourceRange rightRange = range.startEnd(rightOperand, binaryExpression);
|
| - _addReplaceEdit(leftRange, _getRangeText(rightRange));
|
| - _addReplaceEdit(rightRange, _getRangeText(leftRange));
|
| - // maybe replace the operator
|
| - {
|
| - Token operator = binaryExpression.operator;
|
| - // prepare a new operator
|
| - String newOperator = null;
|
| - TokenType operatorType = operator.type;
|
| - if (operatorType == TokenType.LT) {
|
| - newOperator = '>';
|
| - } else if (operatorType == TokenType.LT_EQ) {
|
| - newOperator = '>=';
|
| - } else if (operatorType == TokenType.GT) {
|
| - newOperator = '<';
|
| - } else if (operatorType == TokenType.GT_EQ) {
|
| - newOperator = '<=';
|
| - }
|
| - // replace the operator
|
| - if (newOperator != null) {
|
| - _addReplaceEdit(range.token(operator), newOperator);
|
| - }
|
| + binaryExpression = newBinaryExpression;
|
| + }
|
| + // exchange parts of "wide" expression parts
|
| + SourceRange leftRange = range.startEnd(binaryExpression, leftOperand);
|
| + SourceRange rightRange = range.startEnd(rightOperand, binaryExpression);
|
| + // maybe replace the operator
|
| + Token operator = binaryExpression.operator;
|
| + // prepare a new operator
|
| + String newOperator = null;
|
| + TokenType operatorType = operator.type;
|
| + if (operatorType == TokenType.LT) {
|
| + newOperator = '>';
|
| + } else if (operatorType == TokenType.LT_EQ) {
|
| + newOperator = '>=';
|
| + } else if (operatorType == TokenType.GT) {
|
| + newOperator = '<';
|
| + } else if (operatorType == TokenType.GT_EQ) {
|
| + newOperator = '<=';
|
| + }
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + builder.addSimpleReplacement(leftRange, _getRangeText(rightRange));
|
| + builder.addSimpleReplacement(rightRange, _getRangeText(leftRange));
|
| + // Optionally replace the operator.
|
| + if (newOperator != null) {
|
| + builder.addSimpleReplacement(range.token(operator), newOperator);
|
| }
|
| - }
|
| - // add proposal
|
| - _addAssist(DartAssistKind.EXCHANGE_OPERANDS, []);
|
| + });
|
| + _addAssistFromBuilder(changeBuilder, DartAssistKind.EXCHANGE_OPERANDS);
|
| }
|
|
|
| - void _addProposal_importAddShow() {
|
| + Future<Null> _addProposal_importAddShow() async {
|
| // prepare ImportDirective
|
| ImportDirective importDirective =
|
| node.getAncestor((node) => node is ImportDirective);
|
| @@ -1259,14 +1310,16 @@ class AssistProcessor {
|
| _coverageMarker();
|
| return;
|
| }
|
| - // prepare change
|
| - String showCombinator = ' show ${referencedNames.join(', ')}';
|
| - _addInsertEdit(importDirective.end - 1, showCombinator);
|
| - // add proposal
|
| - _addAssist(DartAssistKind.IMPORT_ADD_SHOW, []);
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + String showCombinator = ' show ${referencedNames.join(', ')}';
|
| + builder.addSimpleInsertion(importDirective.end - 1, showCombinator);
|
| + });
|
| + _addAssistFromBuilder(changeBuilder, DartAssistKind.IMPORT_ADD_SHOW);
|
| }
|
|
|
| - void _addProposal_introduceLocalTestedType() {
|
| + Future<Null> _addProposal_introduceLocalTestedType() async {
|
| AstNode node = this.node;
|
| if (node is IfStatement) {
|
| node = (node as IfStatement).condition;
|
| @@ -1307,42 +1360,38 @@ class AssistProcessor {
|
| offset = targetBlock.rightBracket.end;
|
| statementPrefix = '';
|
| }
|
| - // prepare source
|
| - SourceBuilder builder = new SourceBuilder(file, offset);
|
| - builder.append(eol + prefix + statementPrefix);
|
| - builder.append(castTypeCode);
|
| // prepare excluded names
|
| Set<String> excluded = new Set<String>();
|
| - {
|
| - ScopedNameFinder scopedNameFinder = new ScopedNameFinder(offset);
|
| - isExpression.accept(scopedNameFinder);
|
| - excluded.addAll(scopedNameFinder.locals.keys.toSet());
|
| - }
|
| + ScopedNameFinder scopedNameFinder = new ScopedNameFinder(offset);
|
| + isExpression.accept(scopedNameFinder);
|
| + excluded.addAll(scopedNameFinder.locals.keys.toSet());
|
| // name(s)
|
| - {
|
| - List<String> suggestions =
|
| - getVariableNameSuggestionsForExpression(castType, null, excluded);
|
| - builder.append(' ');
|
| - builder.startPosition('NAME');
|
| - for (int i = 0; i < suggestions.length; i++) {
|
| - String name = suggestions[i];
|
| - if (i == 0) {
|
| - builder.append(name);
|
| - }
|
| - builder.addSuggestion(LinkedEditSuggestionKind.VARIABLE, name);
|
| - }
|
| - builder.endPosition();
|
| - }
|
| - builder.append(' = ');
|
| - builder.append(_getNodeText(isExpression.expression));
|
| - builder.append(';');
|
| - builder.setExitOffset();
|
| - // add proposal
|
| - _insertBuilder(builder);
|
| - _addAssist(DartAssistKind.INTRODUCE_LOCAL_CAST_TYPE, []);
|
| + List<String> suggestions =
|
| + getVariableNameSuggestionsForExpression(castType, null, excluded);
|
| +
|
| + if (suggestions.isNotEmpty) {
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + builder.addInsertion(offset, (DartEditBuilder builder) {
|
| + builder.write(eol + prefix + statementPrefix);
|
| + builder.write(castTypeCode);
|
| + builder.write(' ');
|
| + builder.addSimpleLinkedEdit('NAME', suggestions[0],
|
| + kind: LinkedEditSuggestionKind.VARIABLE,
|
| + suggestions: suggestions);
|
| + builder.write(' = ');
|
| + builder.write(_getNodeText(isExpression.expression));
|
| + builder.write(';');
|
| + builder.selectHere();
|
| + });
|
| + });
|
| + _addAssistFromBuilder(
|
| + changeBuilder, DartAssistKind.INTRODUCE_LOCAL_CAST_TYPE);
|
| + }
|
| }
|
|
|
| - void _addProposal_invertIf() {
|
| + Future<Null> _addProposal_invertIf() async {
|
| if (node is! IfStatement) {
|
| return;
|
| }
|
| @@ -1358,15 +1407,18 @@ class AssistProcessor {
|
| String invertedCondition = utils.invertCondition(condition);
|
| String thenSource = _getNodeText(thenStatement);
|
| String elseSource = _getNodeText(elseStatement);
|
| - // do replacements
|
| - _addReplaceEdit(range.node(condition), invertedCondition);
|
| - _addReplaceEdit(range.node(thenStatement), elseSource);
|
| - _addReplaceEdit(range.node(elseStatement), thenSource);
|
| - // add proposal
|
| - _addAssist(DartAssistKind.INVERT_IF_STATEMENT, []);
|
| +
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + builder.addSimpleReplacement(range.node(condition), invertedCondition);
|
| + builder.addSimpleReplacement(range.node(thenStatement), elseSource);
|
| + builder.addSimpleReplacement(range.node(elseStatement), thenSource);
|
| + });
|
| + _addAssistFromBuilder(changeBuilder, DartAssistKind.INVERT_IF_STATEMENT);
|
| }
|
|
|
| - void _addProposal_joinIfStatementInner() {
|
| + Future<Null> _addProposal_joinIfStatementInner() async {
|
| // climb up condition to the (supposedly) "if" statement
|
| AstNode node = this.node;
|
| while (node is Expression) {
|
| @@ -1412,21 +1464,22 @@ class AssistProcessor {
|
| condition = '$targetConditionSource && $innerConditionSource';
|
| }
|
| // replace target "if" statement
|
| - {
|
| - Statement innerThenStatement = innerIfStatement.thenStatement;
|
| - List<Statement> innerThenStatements = getStatements(innerThenStatement);
|
| - SourceRange lineRanges =
|
| - utils.getLinesRangeStatements(innerThenStatements);
|
| - String oldSource = utils.getRangeText(lineRanges);
|
| - String newSource = utils.indentSourceLeftRight(oldSource, false);
|
| - _addReplaceEdit(range.node(targetIfStatement),
|
| + Statement innerThenStatement = innerIfStatement.thenStatement;
|
| + List<Statement> innerThenStatements = getStatements(innerThenStatement);
|
| + SourceRange lineRanges = utils.getLinesRangeStatements(innerThenStatements);
|
| + String oldSource = utils.getRangeText(lineRanges);
|
| + String newSource = utils.indentSourceLeftRight(oldSource, false);
|
| +
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + builder.addSimpleReplacement(range.node(targetIfStatement),
|
| 'if ($condition) {$eol$newSource$prefix}');
|
| - }
|
| - // done
|
| - _addAssist(DartAssistKind.JOIN_IF_WITH_INNER, []);
|
| + });
|
| + _addAssistFromBuilder(changeBuilder, DartAssistKind.JOIN_IF_WITH_INNER);
|
| }
|
|
|
| - void _addProposal_joinIfStatementOuter() {
|
| + Future<Null> _addProposal_joinIfStatementOuter() async {
|
| // climb up condition to the (supposedly) "if" statement
|
| AstNode node = this.node;
|
| while (node is Expression) {
|
| @@ -1463,36 +1516,35 @@ class AssistProcessor {
|
| // prepare environment
|
| String prefix = utils.getNodePrefix(outerIfStatement);
|
| // merge conditions
|
| - String condition;
|
| - {
|
| - Expression targetCondition = targetIfStatement.condition;
|
| - Expression outerCondition = outerIfStatement.condition;
|
| - String targetConditionSource = _getNodeText(targetCondition);
|
| - String outerConditionSource = _getNodeText(outerCondition);
|
| - if (_shouldWrapParenthesisBeforeAnd(targetCondition)) {
|
| - targetConditionSource = '($targetConditionSource)';
|
| - }
|
| - if (_shouldWrapParenthesisBeforeAnd(outerCondition)) {
|
| - outerConditionSource = '($outerConditionSource)';
|
| - }
|
| - condition = '$outerConditionSource && $targetConditionSource';
|
| + Expression targetCondition = targetIfStatement.condition;
|
| + Expression outerCondition = outerIfStatement.condition;
|
| + String targetConditionSource = _getNodeText(targetCondition);
|
| + String outerConditionSource = _getNodeText(outerCondition);
|
| + if (_shouldWrapParenthesisBeforeAnd(targetCondition)) {
|
| + targetConditionSource = '($targetConditionSource)';
|
| + }
|
| + if (_shouldWrapParenthesisBeforeAnd(outerCondition)) {
|
| + outerConditionSource = '($outerConditionSource)';
|
| }
|
| + String condition = '$outerConditionSource && $targetConditionSource';
|
| // replace outer "if" statement
|
| - {
|
| - Statement targetThenStatement = targetIfStatement.thenStatement;
|
| - List<Statement> targetThenStatements = getStatements(targetThenStatement);
|
| - SourceRange lineRanges =
|
| - utils.getLinesRangeStatements(targetThenStatements);
|
| - String oldSource = utils.getRangeText(lineRanges);
|
| - String newSource = utils.indentSourceLeftRight(oldSource, false);
|
| - _addReplaceEdit(range.node(outerIfStatement),
|
| + Statement targetThenStatement = targetIfStatement.thenStatement;
|
| + List<Statement> targetThenStatements = getStatements(targetThenStatement);
|
| + SourceRange lineRanges =
|
| + utils.getLinesRangeStatements(targetThenStatements);
|
| + String oldSource = utils.getRangeText(lineRanges);
|
| + String newSource = utils.indentSourceLeftRight(oldSource, false);
|
| +
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + builder.addSimpleReplacement(range.node(outerIfStatement),
|
| 'if ($condition) {$eol$newSource$prefix}');
|
| - }
|
| - // done
|
| - _addAssist(DartAssistKind.JOIN_IF_WITH_OUTER, []);
|
| + });
|
| + _addAssistFromBuilder(changeBuilder, DartAssistKind.JOIN_IF_WITH_OUTER);
|
| }
|
|
|
| - void _addProposal_joinVariableDeclaration_onAssignment() {
|
| + Future<Null> _addProposal_joinVariableDeclaration_onAssignment() async {
|
| // check that node is LHS in assignment
|
| if (node is SimpleIdentifier &&
|
| node.parent is AssignmentExpression &&
|
| @@ -1553,13 +1605,18 @@ class AssistProcessor {
|
| _coverageMarker();
|
| return;
|
| }
|
| - // add edits
|
| - _addReplaceEdit(range.endStart(declNode, assignExpression.operator), ' ');
|
| - // add proposal
|
| - _addAssist(DartAssistKind.JOIN_VARIABLE_DECLARATION, []);
|
| +
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + builder.addSimpleReplacement(
|
| + range.endStart(declNode, assignExpression.operator), ' ');
|
| + });
|
| + _addAssistFromBuilder(
|
| + changeBuilder, DartAssistKind.JOIN_VARIABLE_DECLARATION);
|
| }
|
|
|
| - void _addProposal_joinVariableDeclaration_onDeclaration() {
|
| + Future<Null> _addProposal_joinVariableDeclaration_onDeclaration() async {
|
| // prepare enclosing VariableDeclarationList
|
| VariableDeclarationList declList =
|
| node.getAncestor((node) => node is VariableDeclarationList);
|
| @@ -1612,13 +1669,18 @@ class AssistProcessor {
|
| _coverageMarker();
|
| return;
|
| }
|
| - // add edits
|
| - _addReplaceEdit(range.endStart(decl.name, assignExpression.operator), ' ');
|
| - // add proposal
|
| - _addAssist(DartAssistKind.JOIN_VARIABLE_DECLARATION, []);
|
| +
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + builder.addSimpleReplacement(
|
| + range.endStart(decl.name, assignExpression.operator), ' ');
|
| + });
|
| + _addAssistFromBuilder(
|
| + changeBuilder, DartAssistKind.JOIN_VARIABLE_DECLARATION);
|
| }
|
|
|
| - void _addProposal_moveFlutterWidgetDown() {
|
| + Future<Null> _addProposal_moveFlutterWidgetDown() async {
|
| InstanceCreationExpression exprGoingDown = identifyNewExpression(node);
|
| if (exprGoingDown == null ||
|
| !isFlutterInstanceCreationExpression(exprGoingDown)) {
|
| @@ -1647,11 +1709,11 @@ class AssistProcessor {
|
| _coverageMarker();
|
| return; // Inner new-expr needs to be in multi-line format already.
|
| }
|
| - _swapFlutterWidgets(exprGoingDown, exprGoingUp, stableChild,
|
| + await _swapFlutterWidgets(exprGoingDown, exprGoingUp, stableChild,
|
| DartAssistKind.MOVE_FLUTTER_WIDGET_DOWN);
|
| }
|
|
|
| - void _addProposal_moveFlutterWidgetUp() {
|
| + Future<Null> _addProposal_moveFlutterWidgetUp() async {
|
| InstanceCreationExpression exprGoingUp = identifyNewExpression(node);
|
| if (exprGoingUp == null ||
|
| !isFlutterInstanceCreationExpression(exprGoingUp)) {
|
| @@ -1681,11 +1743,11 @@ class AssistProcessor {
|
| _coverageMarker();
|
| return; // Outer new-expr needs to be in multi-line format already.
|
| }
|
| - _swapFlutterWidgets(exprGoingDown, exprGoingUp, stableChild,
|
| + await _swapFlutterWidgets(exprGoingDown, exprGoingUp, stableChild,
|
| DartAssistKind.MOVE_FLUTTER_WIDGET_UP);
|
| }
|
|
|
| - void _addProposal_removeTypeAnnotation() {
|
| + Future<Null> _addProposal_removeTypeAnnotation() async {
|
| VariableDeclarationList declarationList =
|
| node.getAncestor((n) => n is VariableDeclarationList);
|
| if (declarationList == null) {
|
| @@ -1712,17 +1774,20 @@ class AssistProcessor {
|
| }
|
| // add edit
|
| Token keyword = declarationList.keyword;
|
| - SourceRange typeRange = range.startStart(typeNode, firstVariable);
|
| - if (keyword != null && keyword.lexeme != 'var') {
|
| - _addReplaceEdit(typeRange, '');
|
| - } else {
|
| - _addReplaceEdit(typeRange, 'var ');
|
| - }
|
| - // add proposal
|
| - _addAssist(DartAssistKind.REMOVE_TYPE_ANNOTATION, []);
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + SourceRange typeRange = range.startStart(typeNode, firstVariable);
|
| + if (keyword != null && keyword.lexeme != 'var') {
|
| + builder.addSimpleReplacement(typeRange, '');
|
| + } else {
|
| + builder.addSimpleReplacement(typeRange, 'var ');
|
| + }
|
| + });
|
| + _addAssistFromBuilder(changeBuilder, DartAssistKind.REMOVE_TYPE_ANNOTATION);
|
| }
|
|
|
| - void _addProposal_reparentFlutterList() {
|
| + Future<Null> _addProposal_reparentFlutterList() async {
|
| if (node is! ListLiteral) {
|
| return;
|
| }
|
| @@ -1733,7 +1798,6 @@ class AssistProcessor {
|
| return;
|
| }
|
| String literalSrc = utils.getNodeText(node);
|
| - SourceBuilder sb = new SourceBuilder(file, node.offset);
|
| int newlineIdx = literalSrc.lastIndexOf(eol);
|
| if (newlineIdx < 0 || newlineIdx == literalSrc.length - 1) {
|
| _coverageMarker();
|
| @@ -1742,72 +1806,78 @@ class AssistProcessor {
|
| String indentOld = utils.getLinePrefix(node.offset + 1 + newlineIdx);
|
| String indentArg = '$indentOld${utils.getIndent(1)}';
|
| String indentList = '$indentOld${utils.getIndent(2)}';
|
| - sb.append('[');
|
| - sb.append(eol);
|
| - sb.append(indentArg);
|
| - sb.append('new ');
|
| - sb.startPosition('WIDGET');
|
| - sb.append('widget');
|
| - sb.endPosition();
|
| - sb.append('(');
|
| - sb.append(eol);
|
| - sb.append(indentList);
|
| - // Linked editing not needed since arg is always a list.
|
| - sb.append('children: ');
|
| - sb.append(literalSrc.replaceAll(
|
| - new RegExp("^$indentOld", multiLine: true), "$indentList"));
|
| - sb.append(',');
|
| - sb.append(eol);
|
| - sb.append(indentArg);
|
| - sb.append('),');
|
| - sb.append(eol);
|
| - sb.append(indentOld);
|
| - sb.append(']');
|
| - exitPosition = _newPosition(sb.offset + sb.length);
|
| - _insertBuilder(sb, literalSrc.length);
|
| - _addAssist(DartAssistKind.REPARENT_FLUTTER_LIST, []);
|
| +
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + builder.addReplacement(range.node(node), (DartEditBuilder builder) {
|
| + builder.write('[');
|
| + builder.write(eol);
|
| + builder.write(indentArg);
|
| + builder.write('new ');
|
| + builder.addSimpleLinkedEdit('WIDGET', 'widget');
|
| + builder.write('(');
|
| + builder.write(eol);
|
| + builder.write(indentList);
|
| + // Linked editing not needed since arg is always a list.
|
| + builder.write('children: ');
|
| + builder.write(literalSrc.replaceAll(
|
| + new RegExp("^$indentOld", multiLine: true), "$indentList"));
|
| + builder.write(',');
|
| + builder.write(eol);
|
| + builder.write(indentArg);
|
| + builder.write('),');
|
| + builder.write(eol);
|
| + builder.write(indentOld);
|
| + builder.write(']');
|
| + builder.selectHere();
|
| + });
|
| + });
|
| + _addAssistFromBuilder(changeBuilder, DartAssistKind.REPARENT_FLUTTER_LIST);
|
| }
|
|
|
| - void _addProposal_reparentFlutterWidget() {
|
| + Future<Null> _addProposal_reparentFlutterWidget() async {
|
| InstanceCreationExpression newExpr = identifyNewExpression(node);
|
| if (newExpr == null || !isFlutterInstanceCreationExpression(newExpr)) {
|
| _coverageMarker();
|
| return;
|
| }
|
| String newExprSrc = utils.getNodeText(newExpr);
|
| - SourceBuilder sb = new SourceBuilder(file, newExpr.offset);
|
| - sb.append('new ');
|
| - sb.startPosition('WIDGET');
|
| - sb.append('widget');
|
| - sb.endPosition();
|
| - sb.append('(');
|
| - if (newExprSrc.contains(eol)) {
|
| - int newlineIdx = newExprSrc.lastIndexOf(eol);
|
| - int eolLen = eol.length;
|
| - if (newlineIdx == newExprSrc.length - eolLen) {
|
| - newlineIdx -= eolLen;
|
| - }
|
| - String indentOld =
|
| - utils.getLinePrefix(newExpr.offset + eolLen + newlineIdx);
|
| - String indentNew = '$indentOld${utils.getIndent(1)}';
|
| - sb.append(eol);
|
| - sb.append(indentNew);
|
| - newExprSrc = newExprSrc.replaceAll(
|
| - new RegExp("^$indentOld", multiLine: true), "$indentNew");
|
| - newExprSrc += ",$eol$indentOld";
|
| - }
|
| - sb.startPosition('CHILD');
|
| - sb.append('child');
|
| - sb.endPosition();
|
| - sb.append(': ');
|
| - sb.append(newExprSrc);
|
| - sb.append(')');
|
| - exitPosition = _newPosition(sb.offset + sb.length);
|
| - _insertBuilder(sb, newExpr.length);
|
| - _addAssist(DartAssistKind.REPARENT_FLUTTER_WIDGET, []);
|
| +
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + builder.addReplacement(range.node(newExpr), (DartEditBuilder builder) {
|
| + builder.write('new ');
|
| + builder.addSimpleLinkedEdit('WIDGET', 'widget');
|
| + builder.write('(');
|
| + if (newExprSrc.contains(eol)) {
|
| + int newlineIdx = newExprSrc.lastIndexOf(eol);
|
| + int eolLen = eol.length;
|
| + if (newlineIdx == newExprSrc.length - eolLen) {
|
| + newlineIdx -= eolLen;
|
| + }
|
| + String indentOld =
|
| + utils.getLinePrefix(newExpr.offset + eolLen + newlineIdx);
|
| + String indentNew = '$indentOld${utils.getIndent(1)}';
|
| + builder.write(eol);
|
| + builder.write(indentNew);
|
| + newExprSrc = newExprSrc.replaceAll(
|
| + new RegExp("^$indentOld", multiLine: true), indentNew);
|
| + newExprSrc += ",$eol$indentOld";
|
| + }
|
| + builder.addSimpleLinkedEdit('CHILD', 'child');
|
| + builder.write(': ');
|
| + builder.write(newExprSrc);
|
| + builder.write(')');
|
| + builder.selectHere();
|
| + });
|
| + });
|
| + _addAssistFromBuilder(
|
| + changeBuilder, DartAssistKind.REPARENT_FLUTTER_WIDGET);
|
| }
|
|
|
| - void _addProposal_replaceConditionalWithIfElse() {
|
| + Future<Null> _addProposal_replaceConditionalWithIfElse() async {
|
| ConditionalExpression conditional = null;
|
| // may be on Statement with Conditional
|
| Statement statement = node.getAncestor((node) => node is Statement);
|
| @@ -1854,57 +1924,65 @@ class AssistProcessor {
|
| // prepare environment
|
| String indent = utils.getIndent(1);
|
| String prefix = utils.getNodePrefix(statement);
|
| - // Type v = Conditional;
|
| - if (inVariable) {
|
| - VariableDeclaration variable = conditional.parent as VariableDeclaration;
|
| - _addRemoveEdit(range.endEnd(variable.name, conditional));
|
| - String conditionSrc = _getNodeText(conditional.condition);
|
| - String thenSrc = _getNodeText(conditional.thenExpression);
|
| - String elseSrc = _getNodeText(conditional.elseExpression);
|
| - String name = variable.name.name;
|
| - String src = eol;
|
| - src += prefix + 'if ($conditionSrc) {' + eol;
|
| - src += prefix + indent + '$name = $thenSrc;' + eol;
|
| - src += prefix + '} else {' + eol;
|
| - src += prefix + indent + '$name = $elseSrc;' + eol;
|
| - src += prefix + '}';
|
| - _addReplaceEdit(range.endLength(statement, 0), src);
|
| - }
|
| - // v = Conditional;
|
| - if (inAssignment) {
|
| - AssignmentExpression assignment =
|
| - conditional.parent as AssignmentExpression;
|
| - Expression leftSide = assignment.leftHandSide;
|
| - String conditionSrc = _getNodeText(conditional.condition);
|
| - String thenSrc = _getNodeText(conditional.thenExpression);
|
| - String elseSrc = _getNodeText(conditional.elseExpression);
|
| - String name = _getNodeText(leftSide);
|
| - String src = '';
|
| - src += 'if ($conditionSrc) {' + eol;
|
| - src += prefix + indent + '$name = $thenSrc;' + eol;
|
| - src += prefix + '} else {' + eol;
|
| - src += prefix + indent + '$name = $elseSrc;' + eol;
|
| - src += prefix + '}';
|
| - _addReplaceEdit(range.node(statement), src);
|
| - }
|
| - // return Conditional;
|
| - if (inReturn) {
|
| - String conditionSrc = _getNodeText(conditional.condition);
|
| - String thenSrc = _getNodeText(conditional.thenExpression);
|
| - String elseSrc = _getNodeText(conditional.elseExpression);
|
| - String src = '';
|
| - src += 'if ($conditionSrc) {' + eol;
|
| - src += prefix + indent + 'return $thenSrc;' + eol;
|
| - src += prefix + '} else {' + eol;
|
| - src += prefix + indent + 'return $elseSrc;' + eol;
|
| - src += prefix + '}';
|
| - _addReplaceEdit(range.node(statement), src);
|
| - }
|
| - // add proposal
|
| - _addAssist(DartAssistKind.REPLACE_CONDITIONAL_WITH_IF_ELSE, []);
|
| +
|
| + if (inVariable || inAssignment || inReturn) {
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + // Type v = Conditional;
|
| + if (inVariable) {
|
| + VariableDeclaration variable =
|
| + conditional.parent as VariableDeclaration;
|
| + builder.addDeletion(range.endEnd(variable.name, conditional));
|
| + String conditionSrc = _getNodeText(conditional.condition);
|
| + String thenSrc = _getNodeText(conditional.thenExpression);
|
| + String elseSrc = _getNodeText(conditional.elseExpression);
|
| + String name = variable.name.name;
|
| + String src = eol;
|
| + src += prefix + 'if ($conditionSrc) {' + eol;
|
| + src += prefix + indent + '$name = $thenSrc;' + eol;
|
| + src += prefix + '} else {' + eol;
|
| + src += prefix + indent + '$name = $elseSrc;' + eol;
|
| + src += prefix + '}';
|
| + builder.addSimpleReplacement(range.endLength(statement, 0), src);
|
| + }
|
| + // v = Conditional;
|
| + if (inAssignment) {
|
| + AssignmentExpression assignment =
|
| + conditional.parent as AssignmentExpression;
|
| + Expression leftSide = assignment.leftHandSide;
|
| + String conditionSrc = _getNodeText(conditional.condition);
|
| + String thenSrc = _getNodeText(conditional.thenExpression);
|
| + String elseSrc = _getNodeText(conditional.elseExpression);
|
| + String name = _getNodeText(leftSide);
|
| + String src = '';
|
| + src += 'if ($conditionSrc) {' + eol;
|
| + src += prefix + indent + '$name = $thenSrc;' + eol;
|
| + src += prefix + '} else {' + eol;
|
| + src += prefix + indent + '$name = $elseSrc;' + eol;
|
| + src += prefix + '}';
|
| + builder.addSimpleReplacement(range.node(statement), src);
|
| + }
|
| + // return Conditional;
|
| + if (inReturn) {
|
| + String conditionSrc = _getNodeText(conditional.condition);
|
| + String thenSrc = _getNodeText(conditional.thenExpression);
|
| + String elseSrc = _getNodeText(conditional.elseExpression);
|
| + String src = '';
|
| + src += 'if ($conditionSrc) {' + eol;
|
| + src += prefix + indent + 'return $thenSrc;' + eol;
|
| + src += prefix + '} else {' + eol;
|
| + src += prefix + indent + 'return $elseSrc;' + eol;
|
| + src += prefix + '}';
|
| + builder.addSimpleReplacement(range.node(statement), src);
|
| + }
|
| + });
|
| + _addAssistFromBuilder(
|
| + changeBuilder, DartAssistKind.REPLACE_CONDITIONAL_WITH_IF_ELSE);
|
| + }
|
| }
|
|
|
| - void _addProposal_replaceIfElseWithConditional() {
|
| + Future<Null> _addProposal_replaceIfElseWithConditional() async {
|
| // should be "if"
|
| if (node is! IfStatement) {
|
| _coverageMarker();
|
| @@ -1918,41 +1996,60 @@ class AssistProcessor {
|
| _coverageMarker();
|
| return;
|
| }
|
| - // returns
|
| + Expression thenExpression = null;
|
| + Expression elseExpression = null;
|
| + bool hasReturnStatements = false;
|
| if (thenStatement is ReturnStatement && elseStatement is ReturnStatement) {
|
| - String conditionSrc = _getNodeText(ifStatement.condition);
|
| - String theSrc = _getNodeText(thenStatement.expression);
|
| - String elseSrc = _getNodeText(elseStatement.expression);
|
| - _addReplaceEdit(range.node(ifStatement),
|
| - 'return $conditionSrc ? $theSrc : $elseSrc;');
|
| + hasReturnStatements = true;
|
| + thenExpression = thenStatement.expression;
|
| + elseExpression = elseStatement.expression;
|
| }
|
| - // assignments -> v = Conditional;
|
| + bool hasExpressionStatements = false;
|
| if (thenStatement is ExpressionStatement &&
|
| elseStatement is ExpressionStatement) {
|
| - Expression thenExpression = thenStatement.expression;
|
| - Expression elseExpression = elseStatement.expression;
|
| - if (thenExpression is AssignmentExpression &&
|
| - elseExpression is AssignmentExpression) {
|
| - AssignmentExpression thenAssignment = thenExpression;
|
| - AssignmentExpression elseAssignment = elseExpression;
|
| - String thenTarget = _getNodeText(thenAssignment.leftHandSide);
|
| - String elseTarget = _getNodeText(elseAssignment.leftHandSide);
|
| - if (thenAssignment.operator.type == TokenType.EQ &&
|
| - elseAssignment.operator.type == TokenType.EQ &&
|
| - thenTarget == elseTarget) {
|
| + if (thenStatement.expression is AssignmentExpression &&
|
| + elseStatement.expression is AssignmentExpression) {
|
| + hasExpressionStatements = true;
|
| + thenExpression = thenStatement.expression;
|
| + elseExpression = elseStatement.expression;
|
| + }
|
| + }
|
| +
|
| + if (hasReturnStatements || hasExpressionStatements) {
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + // returns
|
| + if (hasReturnStatements) {
|
| String conditionSrc = _getNodeText(ifStatement.condition);
|
| - String theSrc = _getNodeText(thenAssignment.rightHandSide);
|
| - String elseSrc = _getNodeText(elseAssignment.rightHandSide);
|
| - _addReplaceEdit(range.node(ifStatement),
|
| - '$thenTarget = $conditionSrc ? $theSrc : $elseSrc;');
|
| + String theSrc = _getNodeText(thenExpression);
|
| + String elseSrc = _getNodeText(elseExpression);
|
| + builder.addSimpleReplacement(range.node(ifStatement),
|
| + 'return $conditionSrc ? $theSrc : $elseSrc;');
|
| }
|
| - }
|
| + // assignments -> v = Conditional;
|
| + if (hasExpressionStatements) {
|
| + AssignmentExpression thenAssignment = thenExpression;
|
| + AssignmentExpression elseAssignment = elseExpression;
|
| + String thenTarget = _getNodeText(thenAssignment.leftHandSide);
|
| + String elseTarget = _getNodeText(elseAssignment.leftHandSide);
|
| + if (thenAssignment.operator.type == TokenType.EQ &&
|
| + elseAssignment.operator.type == TokenType.EQ &&
|
| + thenTarget == elseTarget) {
|
| + String conditionSrc = _getNodeText(ifStatement.condition);
|
| + String theSrc = _getNodeText(thenAssignment.rightHandSide);
|
| + String elseSrc = _getNodeText(elseAssignment.rightHandSide);
|
| + builder.addSimpleReplacement(range.node(ifStatement),
|
| + '$thenTarget = $conditionSrc ? $theSrc : $elseSrc;');
|
| + }
|
| + }
|
| + });
|
| + _addAssistFromBuilder(
|
| + changeBuilder, DartAssistKind.REPLACE_IF_ELSE_WITH_CONDITIONAL);
|
| }
|
| - // add proposal
|
| - _addAssist(DartAssistKind.REPLACE_IF_ELSE_WITH_CONDITIONAL, []);
|
| }
|
|
|
| - void _addProposal_splitAndCondition() {
|
| + Future<Null> _addProposal_splitAndCondition() async {
|
| // check that user invokes quick assist on binary expression
|
| if (node is! BinaryExpression) {
|
| _coverageMarker();
|
| @@ -2003,45 +2100,48 @@ class AssistProcessor {
|
| range.startEnd(binaryExpression.rightOperand, condition);
|
| rightConditionSource = _getRangeText(rightConditionRange);
|
| }
|
| - // remove "&& rightCondition"
|
| - _addRemoveEdit(range.endEnd(binaryExpression.leftOperand, condition));
|
| - // update "then" statement
|
| - Statement thenStatement = ifStatement.thenStatement;
|
| - if (thenStatement is Block) {
|
| - Block thenBlock = thenStatement;
|
| - SourceRange thenBlockRange = range.node(thenBlock);
|
| - // insert inner "if" with right part of "condition"
|
| - {
|
| - String source = '$eol$prefix${indent}if ($rightConditionSource) {';
|
| +
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + // remove "&& rightCondition"
|
| + builder
|
| + .addDeletion(range.endEnd(binaryExpression.leftOperand, condition));
|
| + // update "then" statement
|
| + Statement thenStatement = ifStatement.thenStatement;
|
| + if (thenStatement is Block) {
|
| + Block thenBlock = thenStatement;
|
| + SourceRange thenBlockRange = range.node(thenBlock);
|
| + // insert inner "if" with right part of "condition"
|
| int thenBlockInsideOffset = thenBlockRange.offset + 1;
|
| - _addInsertEdit(thenBlockInsideOffset, source);
|
| - }
|
| - // insert closing "}" for inner "if"
|
| - {
|
| + builder.addSimpleInsertion(thenBlockInsideOffset,
|
| + '$eol$prefix${indent}if ($rightConditionSource) {');
|
| + // insert closing "}" for inner "if"
|
| int thenBlockEnd = thenBlockRange.end;
|
| - String source = "$indent}";
|
| // insert before outer "then" block "}"
|
| - source += '$eol$prefix';
|
| - _addInsertEdit(thenBlockEnd - 1, source);
|
| + builder.addSimpleInsertion(thenBlockEnd - 1, '$indent}$eol$prefix');
|
| + } else {
|
| + // insert inner "if" with right part of "condition"
|
| + String source = '$eol$prefix${indent}if ($rightConditionSource)';
|
| + builder.addSimpleInsertion(
|
| + ifStatement.rightParenthesis.offset + 1, source);
|
| }
|
| - } else {
|
| - // insert inner "if" with right part of "condition"
|
| - String source = '$eol$prefix${indent}if ($rightConditionSource)';
|
| - _addInsertEdit(ifStatement.rightParenthesis.offset + 1, source);
|
| - }
|
| - // indent "then" statements to correspond inner "if"
|
| - {
|
| - List<Statement> thenStatements = getStatements(thenStatement);
|
| - SourceRange linesRange = utils.getLinesRangeStatements(thenStatements);
|
| - String thenIndentOld = '$prefix$indent';
|
| - String thenIndentNew = '$thenIndentOld$indent';
|
| - _addIndentEdit(linesRange, thenIndentOld, thenIndentNew);
|
| - }
|
| - // add proposal
|
| - _addAssist(DartAssistKind.SPLIT_AND_CONDITION, []);
|
| + // indent "then" statements to correspond inner "if"
|
| + {
|
| + List<Statement> thenStatements = getStatements(thenStatement);
|
| + SourceRange linesRange = utils.getLinesRangeStatements(thenStatements);
|
| + String thenIndentOld = '$prefix$indent';
|
| + String thenIndentNew = '$thenIndentOld$indent';
|
| + builder.addSimpleReplacement(
|
| + linesRange,
|
| + utils.replaceSourceRangeIndent(
|
| + linesRange, thenIndentOld, thenIndentNew));
|
| + }
|
| + });
|
| + _addAssistFromBuilder(changeBuilder, DartAssistKind.SPLIT_AND_CONDITION);
|
| }
|
|
|
| - void _addProposal_splitVariableDeclaration() {
|
| + Future<Null> _addProposal_splitVariableDeclaration() async {
|
| // prepare DartVariableStatement, should be part of Block
|
| VariableDeclarationStatement statement =
|
| node.getAncestor((node) => node is VariableDeclarationStatement);
|
| @@ -2062,25 +2162,29 @@ class AssistProcessor {
|
| _coverageMarker();
|
| return;
|
| }
|
| - // remove initializer value
|
| - _addRemoveEdit(range.endStart(variable.name, statement.semicolon));
|
| - // add assignment statement
|
| - String indent = utils.getNodePrefix(statement);
|
| - String name = variable.name.name;
|
| - String initSrc = _getNodeText(initializer);
|
| - SourceRange assignRange = range.endLength(statement, 0);
|
| - _addReplaceEdit(assignRange, eol + indent + name + ' = ' + initSrc + ';');
|
| - // add proposal
|
| - _addAssist(DartAssistKind.SPLIT_VARIABLE_DECLARATION, []);
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + // remove initializer value
|
| + builder.addDeletion(range.endStart(variable.name, statement.semicolon));
|
| + // add assignment statement
|
| + String indent = utils.getNodePrefix(statement);
|
| + String name = variable.name.name;
|
| + String initSrc = _getNodeText(initializer);
|
| + SourceRange assignRange = range.endLength(statement, 0);
|
| + builder.addSimpleReplacement(
|
| + assignRange, eol + indent + name + ' = ' + initSrc + ';');
|
| + });
|
| + _addAssistFromBuilder(
|
| + changeBuilder, DartAssistKind.SPLIT_VARIABLE_DECLARATION);
|
| }
|
|
|
| - void _addProposal_surroundWith() {
|
| + Future<Null> _addProposal_surroundWith() async {
|
| // prepare selected statements
|
| List<Statement> selectedStatements;
|
| {
|
| - SourceRange selection = new SourceRange(selectionOffset, selectionLength);
|
| - StatementAnalyzer selectionAnalyzer =
|
| - new StatementAnalyzer(unit, selection);
|
| + StatementAnalyzer selectionAnalyzer = new StatementAnalyzer(
|
| + unit, new SourceRange(selectionOffset, selectionLength));
|
| unit.accept(selectionAnalyzer);
|
| List<AstNode> selectedNodes = selectionAnalyzer.selectedNodes;
|
| // convert nodes to statements
|
| @@ -2108,238 +2212,191 @@ class AssistProcessor {
|
| utils.replaceSourceRangeIndent(statementsRange, indentOld, indentNew);
|
| // "block"
|
| {
|
| - _addInsertEdit(statementsRange.offset, '$indentOld{$eol');
|
| - _addIndentEdit(statementsRange, indentOld, indentNew);
|
| - _addInsertEdit(statementsRange.end, '$indentOld}$eol');
|
| - exitPosition = _newPosition(lastStatement.end);
|
| - // add proposal
|
| - _addAssist(DartAssistKind.SURROUND_WITH_BLOCK, []);
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + builder.addSimpleInsertion(statementsRange.offset, '$indentOld{$eol');
|
| + builder.addSimpleReplacement(
|
| + statementsRange,
|
| + utils.replaceSourceRangeIndent(
|
| + statementsRange, indentOld, indentNew));
|
| + builder.addSimpleInsertion(statementsRange.end, '$indentOld}$eol');
|
| + exitPosition = _newPosition(lastStatement.end);
|
| + });
|
| + _addAssistFromBuilder(changeBuilder, DartAssistKind.SURROUND_WITH_BLOCK);
|
| }
|
| // "if"
|
| {
|
| - int offset = statementsRange.offset;
|
| - SourceBuilder sb = new SourceBuilder(file, offset);
|
| - sb.append(indentOld);
|
| - sb.append('if (');
|
| - {
|
| - sb.startPosition('CONDITION');
|
| - sb.append('condition');
|
| - sb.endPosition();
|
| - }
|
| - sb.append(') {');
|
| - sb.append(eol);
|
| - sb.append(indentedCode);
|
| - sb.append(indentOld);
|
| - sb.append('}');
|
| - exitPosition = _newPosition(sb.offset + sb.length);
|
| - sb.append(eol);
|
| - _insertBuilder(sb, statementsRange.length);
|
| - // add proposal
|
| - _addAssist(DartAssistKind.SURROUND_WITH_IF, []);
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + builder.addReplacement(statementsRange, (DartEditBuilder builder) {
|
| + builder.write(indentOld);
|
| + builder.write('if (');
|
| + builder.addSimpleLinkedEdit('CONDITION', 'condition');
|
| + builder.write(') {');
|
| + builder.write(eol);
|
| + builder.write(indentedCode);
|
| + builder.write(indentOld);
|
| + builder.write('}');
|
| + builder.selectHere();
|
| + builder.write(eol);
|
| + });
|
| + });
|
| + _addAssistFromBuilder(changeBuilder, DartAssistKind.SURROUND_WITH_IF);
|
| }
|
| // "while"
|
| {
|
| - int offset = statementsRange.offset;
|
| - SourceBuilder sb = new SourceBuilder(file, offset);
|
| - sb.append(indentOld);
|
| - sb.append('while (');
|
| - {
|
| - sb.startPosition('CONDITION');
|
| - sb.append('condition');
|
| - sb.endPosition();
|
| - }
|
| - sb.append(') {');
|
| - sb.append(eol);
|
| - sb.append(indentedCode);
|
| - sb.append(indentOld);
|
| - sb.append('}');
|
| - exitPosition = _newPosition(sb.offset + sb.length);
|
| - sb.append(eol);
|
| - _insertBuilder(sb, statementsRange.length);
|
| - // add proposal
|
| - _addAssist(DartAssistKind.SURROUND_WITH_WHILE, []);
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + builder.addReplacement(statementsRange, (DartEditBuilder builder) {
|
| + builder.write(indentOld);
|
| + builder.write('while (');
|
| + builder.addSimpleLinkedEdit('CONDITION', 'condition');
|
| + builder.write(') {');
|
| + builder.write(eol);
|
| + builder.write(indentedCode);
|
| + builder.write(indentOld);
|
| + builder.write('}');
|
| + builder.selectHere();
|
| + builder.write(eol);
|
| + });
|
| + });
|
| + _addAssistFromBuilder(changeBuilder, DartAssistKind.SURROUND_WITH_WHILE);
|
| }
|
| // "for-in"
|
| {
|
| - int offset = statementsRange.offset;
|
| - SourceBuilder sb = new SourceBuilder(file, offset);
|
| - sb.append(indentOld);
|
| - sb.append('for (var ');
|
| - {
|
| - sb.startPosition('NAME');
|
| - sb.append('item');
|
| - sb.endPosition();
|
| - }
|
| - sb.append(' in ');
|
| - {
|
| - sb.startPosition('ITERABLE');
|
| - sb.append('iterable');
|
| - sb.endPosition();
|
| - }
|
| - sb.append(') {');
|
| - sb.append(eol);
|
| - sb.append(indentedCode);
|
| - sb.append(indentOld);
|
| - sb.append('}');
|
| - exitPosition = _newPosition(sb.offset + sb.length);
|
| - sb.append(eol);
|
| - _insertBuilder(sb, statementsRange.length);
|
| - // add proposal
|
| - _addAssist(DartAssistKind.SURROUND_WITH_FOR_IN, []);
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + builder.addReplacement(statementsRange, (DartEditBuilder builder) {
|
| + builder.write(indentOld);
|
| + builder.write('for (var ');
|
| + builder.addSimpleLinkedEdit('NAME', 'item');
|
| + builder.write(' in ');
|
| + builder.addSimpleLinkedEdit('ITERABLE', 'iterable');
|
| + builder.write(') {');
|
| + builder.write(eol);
|
| + builder.write(indentedCode);
|
| + builder.write(indentOld);
|
| + builder.write('}');
|
| + builder.selectHere();
|
| + builder.write(eol);
|
| + });
|
| + });
|
| + _addAssistFromBuilder(changeBuilder, DartAssistKind.SURROUND_WITH_FOR_IN);
|
| }
|
| // "for"
|
| {
|
| - int offset = statementsRange.offset;
|
| - SourceBuilder sb = new SourceBuilder(file, offset);
|
| - sb.append(indentOld);
|
| - sb.append('for (var ');
|
| - {
|
| - sb.startPosition('VAR');
|
| - sb.append('v');
|
| - sb.endPosition();
|
| - }
|
| - sb.append(' = ');
|
| - {
|
| - sb.startPosition('INIT');
|
| - sb.append('init');
|
| - sb.endPosition();
|
| - }
|
| - sb.append('; ');
|
| - {
|
| - sb.startPosition('CONDITION');
|
| - sb.append('condition');
|
| - sb.endPosition();
|
| - }
|
| - sb.append('; ');
|
| - {
|
| - sb.startPosition('INCREMENT');
|
| - sb.append('increment');
|
| - sb.endPosition();
|
| - }
|
| - sb.append(') {');
|
| - sb.append(eol);
|
| - sb.append(indentedCode);
|
| - sb.append(indentOld);
|
| - sb.append('}');
|
| - exitPosition = _newPosition(sb.offset + sb.length);
|
| - sb.append(eol);
|
| - _insertBuilder(sb, statementsRange.length);
|
| - // add proposal
|
| - _addAssist(DartAssistKind.SURROUND_WITH_FOR, []);
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + builder.addReplacement(statementsRange, (DartEditBuilder builder) {
|
| + builder.write(indentOld);
|
| + builder.write('for (var ');
|
| + builder.addSimpleLinkedEdit('VAR', 'v');
|
| + builder.write(' = ');
|
| + builder.addSimpleLinkedEdit('INIT', 'init');
|
| + builder.write('; ');
|
| + builder.addSimpleLinkedEdit('CONDITION', 'condition');
|
| + builder.write('; ');
|
| + builder.addSimpleLinkedEdit('INCREMENT', 'increment');
|
| + builder.write(') {');
|
| + builder.write(eol);
|
| + builder.write(indentedCode);
|
| + builder.write(indentOld);
|
| + builder.write('}');
|
| + builder.selectHere();
|
| + builder.write(eol);
|
| + });
|
| + });
|
| + _addAssistFromBuilder(changeBuilder, DartAssistKind.SURROUND_WITH_FOR);
|
| }
|
| // "do-while"
|
| {
|
| - int offset = statementsRange.offset;
|
| - SourceBuilder sb = new SourceBuilder(file, offset);
|
| - sb.append(indentOld);
|
| - sb.append('do {');
|
| - sb.append(eol);
|
| - sb.append(indentedCode);
|
| - sb.append(indentOld);
|
| - sb.append('} while (');
|
| - {
|
| - sb.startPosition('CONDITION');
|
| - sb.append('condition');
|
| - sb.endPosition();
|
| - }
|
| - sb.append(');');
|
| - exitPosition = _newPosition(sb.offset + sb.length);
|
| - sb.append(eol);
|
| - _insertBuilder(sb, statementsRange.length);
|
| - // add proposal
|
| - _addAssist(DartAssistKind.SURROUND_WITH_DO_WHILE, []);
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + builder.addReplacement(statementsRange, (DartEditBuilder builder) {
|
| + builder.write(indentOld);
|
| + builder.write('do {');
|
| + builder.write(eol);
|
| + builder.write(indentedCode);
|
| + builder.write(indentOld);
|
| + builder.write('} while (');
|
| + builder.addSimpleLinkedEdit('CONDITION', 'condition');
|
| + builder.write(');');
|
| + builder.selectHere();
|
| + builder.write(eol);
|
| + });
|
| + });
|
| + _addAssistFromBuilder(
|
| + changeBuilder, DartAssistKind.SURROUND_WITH_DO_WHILE);
|
| }
|
| // "try-catch"
|
| {
|
| - int offset = statementsRange.offset;
|
| - SourceBuilder sb = new SourceBuilder(file, offset);
|
| - sb.append(indentOld);
|
| - sb.append('try {');
|
| - sb.append(eol);
|
| - sb.append(indentedCode);
|
| - sb.append(indentOld);
|
| - sb.append('} on ');
|
| - {
|
| - sb.startPosition('EXCEPTION_TYPE');
|
| - sb.append('Exception');
|
| - sb.endPosition();
|
| - }
|
| - sb.append(' catch (');
|
| - {
|
| - sb.startPosition('EXCEPTION_VAR');
|
| - sb.append('e');
|
| - sb.endPosition();
|
| - }
|
| - sb.append(') {');
|
| - sb.append(eol);
|
| - //
|
| - sb.append(indentNew);
|
| - {
|
| - sb.startPosition('CATCH');
|
| - sb.append('// TODO');
|
| - sb.endPosition();
|
| - sb.setExitOffset();
|
| - }
|
| - sb.append(eol);
|
| - //
|
| - sb.append(indentOld);
|
| - sb.append('}');
|
| - sb.append(eol);
|
| - _insertBuilder(sb, statementsRange.length);
|
| - // add proposal
|
| - _addAssist(DartAssistKind.SURROUND_WITH_TRY_CATCH, []);
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + builder.addReplacement(statementsRange, (DartEditBuilder builder) {
|
| + builder.write(indentOld);
|
| + builder.write('try {');
|
| + builder.write(eol);
|
| + builder.write(indentedCode);
|
| + builder.write(indentOld);
|
| + builder.write('} on ');
|
| + builder.addSimpleLinkedEdit('EXCEPTION_TYPE', 'Exception');
|
| + builder.write(' catch (');
|
| + builder.addSimpleLinkedEdit('EXCEPTION_VAR', 'e');
|
| + builder.write(') {');
|
| + builder.write(eol);
|
| + //
|
| + builder.write(indentNew);
|
| + builder.addSimpleLinkedEdit('CATCH', '// TODO');
|
| + builder.selectHere();
|
| + builder.write(eol);
|
| + //
|
| + builder.write(indentOld);
|
| + builder.write('}');
|
| + builder.write(eol);
|
| + });
|
| + });
|
| + _addAssistFromBuilder(
|
| + changeBuilder, DartAssistKind.SURROUND_WITH_TRY_CATCH);
|
| }
|
| // "try-finally"
|
| {
|
| - int offset = statementsRange.offset;
|
| - SourceBuilder sb = new SourceBuilder(file, offset);
|
| - //
|
| - sb.append(indentOld);
|
| - sb.append('try {');
|
| - sb.append(eol);
|
| - //
|
| - sb.append(indentedCode);
|
| - //
|
| - sb.append(indentOld);
|
| - sb.append('} finally {');
|
| - sb.append(eol);
|
| - //
|
| - sb.append(indentNew);
|
| - {
|
| - sb.startPosition('FINALLY');
|
| - sb.append('// TODO');
|
| - sb.endPosition();
|
| - sb.setExitOffset();
|
| - }
|
| - sb.setExitOffset();
|
| - sb.append(eol);
|
| - //
|
| - sb.append(indentOld);
|
| - sb.append('}');
|
| - sb.append(eol);
|
| - //
|
| - _insertBuilder(sb, statementsRange.length);
|
| - // add proposal
|
| - _addAssist(DartAssistKind.SURROUND_WITH_TRY_FINALLY, []);
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + builder.addReplacement(statementsRange, (DartEditBuilder builder) {
|
| + builder.write(indentOld);
|
| + builder.write('try {');
|
| + builder.write(eol);
|
| + //
|
| + builder.write(indentedCode);
|
| + //
|
| + builder.write(indentOld);
|
| + builder.write('} finally {');
|
| + builder.write(eol);
|
| + //
|
| + builder.write(indentNew);
|
| + builder.addSimpleLinkedEdit('FINALLY', '// TODO');
|
| + builder.selectHere();
|
| + builder.write(eol);
|
| + //
|
| + builder.write(indentOld);
|
| + builder.write('}');
|
| + builder.write(eol);
|
| + });
|
| + });
|
| + _addAssistFromBuilder(
|
| + changeBuilder, DartAssistKind.SURROUND_WITH_TRY_FINALLY);
|
| }
|
| }
|
|
|
| /**
|
| - * Adds a new [Edit] to [edits].
|
| - */
|
| - void _addRemoveEdit(SourceRange range) {
|
| - _addReplaceEdit(range, '');
|
| - }
|
| -
|
| - /**
|
| - * Adds a new [SourceEdit] to [edits].
|
| - */
|
| - void _addReplaceEdit(SourceRange range, String text) {
|
| - SourceEdit edit = new SourceEdit(range.offset, range.length, text);
|
| - doSourceChange_addElementEdit(change, unitElement, edit);
|
| - }
|
| -
|
| - /**
|
| * Configures [utils] using given [target].
|
| */
|
| void _configureTargetLocation(Object target) {
|
| @@ -2353,16 +2410,47 @@ class AssistProcessor {
|
| }
|
| }
|
|
|
| - /**
|
| - * Returns an existing or just added [LinkedEditGroup] with [groupId].
|
| - */
|
| - LinkedEditGroup _getLinkedPosition(String groupId) {
|
| - LinkedEditGroup group = linkedPositionGroups[groupId];
|
| - if (group == null) {
|
| - group = new LinkedEditGroup.empty();
|
| - linkedPositionGroups[groupId] = group;
|
| + void _convertFlutterChildToChildren(
|
| + InstanceCreationExpression childArg,
|
| + NamedExpression namedExp,
|
| + String eol,
|
| + Function getNodeText,
|
| + Function getLinePrefix,
|
| + Function getIndent,
|
| + Function getText,
|
| + DartFileEditBuilder builder) {
|
| + int childLoc = namedExp.offset + 'child'.length;
|
| + builder.addSimpleInsertion(childLoc, 'ren');
|
| + int listLoc = childArg.offset;
|
| + String childArgSrc = getNodeText(childArg);
|
| + if (!childArgSrc.contains(eol)) {
|
| + builder.addSimpleInsertion(listLoc, '<Widget>[');
|
| + builder.addSimpleInsertion(listLoc + childArg.length, ']');
|
| + } else {
|
| + int newlineLoc = childArgSrc.lastIndexOf(eol);
|
| + if (newlineLoc == childArgSrc.length) {
|
| + newlineLoc -= 1;
|
| + }
|
| + String indentOld = getLinePrefix(childArg.offset + 1 + newlineLoc);
|
| + String indentNew = '$indentOld${getIndent(1)}';
|
| + // The separator includes 'child:' but that has no newlines.
|
| + String separator =
|
| + getText(namedExp.offset, childArg.offset - namedExp.offset);
|
| + String prefix = separator.contains(eol) ? "" : "$eol$indentNew";
|
| + if (prefix.isEmpty) {
|
| + builder.addSimpleInsertion(
|
| + namedExp.offset + 'child:'.length, ' <Widget>[');
|
| + int argOffset = childArg.offset;
|
| + builder
|
| + .addDeletion(range.startOffsetEndOffset(argOffset - 2, argOffset));
|
| + } else {
|
| + builder.addSimpleInsertion(listLoc, '<Widget>[');
|
| + }
|
| + String newChildArgSrc = childArgSrc.replaceAll(
|
| + new RegExp("^$indentOld", multiLine: true), "$indentNew");
|
| + newChildArgSrc = "$prefix$newChildArgSrc,$eol$indentOld]";
|
| + builder.addSimpleReplacement(range.node(childArg), newChildArgSrc);
|
| }
|
| - return group;
|
| }
|
|
|
| /**
|
| @@ -2379,34 +2467,6 @@ class AssistProcessor {
|
| return utils.getRangeText(range);
|
| }
|
|
|
| - /**
|
| - * Inserts the given [SourceBuilder] at its offset.
|
| - */
|
| - void _insertBuilder(SourceBuilder builder, [int length = 0]) {
|
| - {
|
| - SourceRange range = new SourceRange(builder.offset, length);
|
| - String text = builder.toString();
|
| - _addReplaceEdit(range, text);
|
| - }
|
| - // add linked positions
|
| - builder.linkedPositionGroups.forEach((String id, LinkedEditGroup group) {
|
| - LinkedEditGroup fixGroup = _getLinkedPosition(id);
|
| - group.positions.forEach((Position position) {
|
| - fixGroup.addPosition(position, group.length);
|
| - });
|
| - group.suggestions.forEach((LinkedEditSuggestion suggestion) {
|
| - fixGroup.addSuggestion(suggestion);
|
| - });
|
| - });
|
| - // add exit position
|
| - {
|
| - int exitOffset = builder.exitOffset;
|
| - if (exitOffset != null) {
|
| - exitPosition = _newPosition(exitOffset);
|
| - }
|
| - }
|
| - }
|
| -
|
| int _modificationStamp(String filePath) {
|
| // TODO(brianwilkerson) We have lost the ability for clients to know whether
|
| // it is safe to apply an edit.
|
| @@ -2417,87 +2477,93 @@ class AssistProcessor {
|
| return new Position(file, offset);
|
| }
|
|
|
| - void _swapFlutterWidgets(
|
| + Future<Null> _swapFlutterWidgets(
|
| InstanceCreationExpression exprGoingDown,
|
| InstanceCreationExpression exprGoingUp,
|
| NamedExpression stableChild,
|
| - AssistKind assistKind) {
|
| + AssistKind assistKind) async {
|
| String currentSource = unitElement.context.getContents(source).data;
|
| // TODO(messick) Find a better way to get LineInfo for the source.
|
| LineInfo lineInfo = new LineInfo.fromContent(currentSource);
|
| int currLn = lineInfo.getLocation(exprGoingUp.offset).lineNumber;
|
| int lnOffset = lineInfo.getOffsetOfLine(currLn);
|
| - SourceBuilder sb = new SourceBuilder(file, exprGoingDown.offset);
|
| - String argSrc =
|
| - utils.getText(exprGoingUp.offset, lnOffset - exprGoingUp.offset);
|
| - sb.append(argSrc); // Append child new-expr plus rest of line.
|
| -
|
| - String getSrc(Expression expr) {
|
| - int startLn = lineInfo.getLocation(expr.offset).lineNumber;
|
| - int startOffset = lineInfo.getOffsetOfLine(startLn - 1);
|
| - int endLn =
|
| - lineInfo.getLocation(expr.offset + expr.length).lineNumber + 1;
|
| - int curOffset = lineInfo.getOffsetOfLine(endLn - 1);
|
| - return utils.getText(startOffset, curOffset - startOffset);
|
| - }
|
| -
|
| - String outerIndent = utils.getNodePrefix(exprGoingDown.parent);
|
| - String innerIndent = utils.getNodePrefix(exprGoingUp.parent);
|
| - exprGoingUp.argumentList.arguments.forEach((arg) {
|
| - if (arg is NamedExpression && arg.name.label.name == 'child') {
|
| - if (stableChild != arg) {
|
| - _coverageMarker();
|
| - return;
|
| +
|
| + DartChangeBuilder changeBuilder = new DartChangeBuilder(driver);
|
| + await changeBuilder.addFileEdit(file, fileStamp,
|
| + (DartFileEditBuilder builder) {
|
| + builder.addReplacement(range.node(exprGoingDown),
|
| + (DartEditBuilder builder) {
|
| + String argSrc =
|
| + utils.getText(exprGoingUp.offset, lnOffset - exprGoingUp.offset);
|
| + builder.write(argSrc); // Append child new-expr plus rest of line.
|
| +
|
| + String getSrc(Expression expr) {
|
| + int startLn = lineInfo.getLocation(expr.offset).lineNumber;
|
| + int startOffset = lineInfo.getOffsetOfLine(startLn - 1);
|
| + int endLn =
|
| + lineInfo.getLocation(expr.offset + expr.length).lineNumber + 1;
|
| + int curOffset = lineInfo.getOffsetOfLine(endLn - 1);
|
| + return utils.getText(startOffset, curOffset - startOffset);
|
| }
|
| - // Insert exprGoingDown here.
|
| - // Copy from start of line to offset of exprGoingDown.
|
| - currLn = lineInfo.getLocation(stableChild.offset).lineNumber;
|
| - lnOffset = lineInfo.getOffsetOfLine(currLn - 1);
|
| - argSrc =
|
| - utils.getText(lnOffset, stableChild.expression.offset - lnOffset);
|
| - argSrc = argSrc.replaceAll(
|
| - new RegExp("^$innerIndent", multiLine: true), "$outerIndent");
|
| - sb.append(argSrc);
|
| - int nextLn = lineInfo.getLocation(exprGoingDown.offset).lineNumber;
|
| - lnOffset = lineInfo.getOffsetOfLine(nextLn);
|
| - argSrc = utils.getText(
|
| - exprGoingDown.offset, lnOffset - exprGoingDown.offset);
|
| - sb.append(argSrc);
|
| -
|
| - exprGoingDown.argumentList.arguments.forEach((val) {
|
| - if (val is NamedExpression && val.name.label.name == 'child') {
|
| - // Insert stableChild here at same indent level.
|
| - sb.append(utils.getNodePrefix(arg.name));
|
| - argSrc = utils.getNodeText(stableChild);
|
| - sb.append(argSrc);
|
| - if (assistKind == DartAssistKind.MOVE_FLUTTER_WIDGET_UP) {
|
| - sb.append(',$eol');
|
| +
|
| + String outerIndent = utils.getNodePrefix(exprGoingDown.parent);
|
| + String innerIndent = utils.getNodePrefix(exprGoingUp.parent);
|
| + exprGoingUp.argumentList.arguments.forEach((arg) {
|
| + if (arg is NamedExpression && arg.name.label.name == 'child') {
|
| + if (stableChild != arg) {
|
| + _coverageMarker();
|
| + return;
|
| }
|
| + // Insert exprGoingDown here.
|
| + // Copy from start of line to offset of exprGoingDown.
|
| + currLn = lineInfo.getLocation(stableChild.offset).lineNumber;
|
| + lnOffset = lineInfo.getOffsetOfLine(currLn - 1);
|
| + argSrc = utils.getText(
|
| + lnOffset, stableChild.expression.offset - lnOffset);
|
| + argSrc = argSrc.replaceAll(
|
| + new RegExp("^$innerIndent", multiLine: true), "$outerIndent");
|
| + builder.write(argSrc);
|
| + int nextLn = lineInfo.getLocation(exprGoingDown.offset).lineNumber;
|
| + lnOffset = lineInfo.getOffsetOfLine(nextLn);
|
| + argSrc = utils.getText(
|
| + exprGoingDown.offset, lnOffset - exprGoingDown.offset);
|
| + builder.write(argSrc);
|
| +
|
| + exprGoingDown.argumentList.arguments.forEach((val) {
|
| + if (val is NamedExpression && val.name.label.name == 'child') {
|
| + // Insert stableChild here at same indent level.
|
| + builder.write(utils.getNodePrefix(arg.name));
|
| + argSrc = utils.getNodeText(stableChild);
|
| + builder.write(argSrc);
|
| + if (assistKind == DartAssistKind.MOVE_FLUTTER_WIDGET_UP) {
|
| + builder.write(',$eol');
|
| + }
|
| + } else {
|
| + argSrc = getSrc(val);
|
| + argSrc = argSrc.replaceAll(
|
| + new RegExp("^$outerIndent", multiLine: true),
|
| + "$innerIndent");
|
| + builder.write(argSrc);
|
| + }
|
| + });
|
| + if (assistKind == DartAssistKind.MOVE_FLUTTER_WIDGET_DOWN) {
|
| + builder.write(',$eol');
|
| + }
|
| + builder.write(innerIndent);
|
| + builder.write('),$eol');
|
| } else {
|
| - argSrc = getSrc(val);
|
| + argSrc = getSrc(arg);
|
| argSrc = argSrc.replaceAll(
|
| - new RegExp("^$outerIndent", multiLine: true), "$innerIndent");
|
| - sb.append(argSrc);
|
| + new RegExp("^$innerIndent", multiLine: true), "$outerIndent");
|
| + builder.write(argSrc);
|
| }
|
| });
|
| - if (assistKind == DartAssistKind.MOVE_FLUTTER_WIDGET_DOWN) {
|
| - sb.append(',$eol');
|
| - }
|
| - sb.append(innerIndent);
|
| - sb.append('),$eol');
|
| - } else {
|
| - argSrc = getSrc(arg);
|
| - argSrc = argSrc.replaceAll(
|
| - new RegExp("^$innerIndent", multiLine: true), "$outerIndent");
|
| - sb.append(argSrc);
|
| - }
|
| + builder.write(outerIndent);
|
| + builder.write(')');
|
| + builder.selectHere();
|
| + });
|
| });
|
| - sb.append(outerIndent);
|
| - sb.append(')');
|
| -
|
| - exitPosition = _newPosition(sb.offset + sb.length);
|
| - _insertBuilder(sb, exprGoingDown.length);
|
| - _addAssist(assistKind, []);
|
| + _addAssistFromBuilder(changeBuilder, assistKind);
|
| }
|
|
|
| /**
|
|
|