| 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 a313eb7163be8bd9da47d0812de18fd4ba205db7..c343b17c1352041c672b0917a48610e11227a0d2 100644
|
| --- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
|
| +++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
|
| @@ -136,6 +136,8 @@ class AssistProcessor {
|
| _addProposal_joinIfStatementOuter();
|
| _addProposal_joinVariableDeclaration_onAssignment();
|
| _addProposal_joinVariableDeclaration_onDeclaration();
|
| + _addProposal_moveFlutterWidgetDown();
|
| + _addProposal_moveFlutterWidgetUp();
|
| _addProposal_removeTypeAnnotation();
|
| _addProposal_reparentFlutterList();
|
| _addProposal_reparentFlutterWidget();
|
| @@ -1564,6 +1566,73 @@ class AssistProcessor {
|
| _addAssist(DartAssistKind.JOIN_VARIABLE_DECLARATION, []);
|
| }
|
|
|
| + void _addProposal_moveFlutterWidgetDown() {
|
| + InstanceCreationExpression exprGoingDown = _identifyNewExpression();
|
| + if (exprGoingDown == null ||
|
| + !_isFlutterInstanceCreationExpression(exprGoingDown)) {
|
| + _coverageMarker();
|
| + return;
|
| + }
|
| + InstanceCreationExpression exprGoingUp = _findChildWidget(exprGoingDown);
|
| + if (exprGoingUp == null) {
|
| + _coverageMarker();
|
| + return;
|
| + }
|
| + NamedExpression stableChild = _findChildArgument(exprGoingUp);
|
| + if (stableChild == null || stableChild.expression == null) {
|
| + _coverageMarker();
|
| + return;
|
| + }
|
| + String exprGoingDownSrc = utils.getNodeText(exprGoingDown);
|
| + int dnNewlineIdx = exprGoingDownSrc.lastIndexOf(eol);
|
| + if (dnNewlineIdx < 0 || dnNewlineIdx == exprGoingDownSrc.length - 1) {
|
| + _coverageMarker();
|
| + return; // Outer new-expr needs to be in multi-line format already.
|
| + }
|
| + String exprGoingUpSrc = utils.getNodeText(exprGoingUp);
|
| + int upNewlineIdx = exprGoingUpSrc.lastIndexOf(eol);
|
| + if (upNewlineIdx < 0 || upNewlineIdx == exprGoingUpSrc.length - 1) {
|
| + _coverageMarker();
|
| + return; // Inner new-expr needs to be in multi-line format already.
|
| + }
|
| + _swapFlutterWidgets(exprGoingDown, exprGoingUp, stableChild,
|
| + DartAssistKind.MOVE_FLUTTER_WIDGET_DOWN);
|
| + }
|
| +
|
| + void _addProposal_moveFlutterWidgetUp() {
|
| + InstanceCreationExpression exprGoingUp = _identifyNewExpression();
|
| + if (exprGoingUp == null ||
|
| + !_isFlutterInstanceCreationExpression(exprGoingUp)) {
|
| + _coverageMarker();
|
| + return;
|
| + }
|
| + AstNode expr = exprGoingUp.parent?.parent?.parent;
|
| + if (expr == null || expr is! InstanceCreationExpression) {
|
| + _coverageMarker();
|
| + return;
|
| + }
|
| + InstanceCreationExpression exprGoingDown = expr;
|
| + NamedExpression stableChild = _findChildArgument(exprGoingUp);
|
| + if (stableChild == null || stableChild.expression == null) {
|
| + _coverageMarker();
|
| + return;
|
| + }
|
| + String exprGoingUpSrc = utils.getNodeText(exprGoingUp);
|
| + int upNewlineIdx = exprGoingUpSrc.lastIndexOf(eol);
|
| + if (upNewlineIdx < 0 || upNewlineIdx == exprGoingUpSrc.length - 1) {
|
| + _coverageMarker();
|
| + return; // Inner new-expr needs to be in multi-line format already.
|
| + }
|
| + String exprGoingDownSrc = utils.getNodeText(exprGoingDown);
|
| + int dnNewlineIdx = exprGoingDownSrc.lastIndexOf(eol);
|
| + if (dnNewlineIdx < 0 || dnNewlineIdx == exprGoingDownSrc.length - 1) {
|
| + _coverageMarker();
|
| + return; // Outer new-expr needs to be in multi-line format already.
|
| + }
|
| + _swapFlutterWidgets(exprGoingDown, exprGoingUp, stableChild,
|
| + DartAssistKind.MOVE_FLUTTER_WIDGET_UP);
|
| + }
|
| +
|
| void _addProposal_removeTypeAnnotation() {
|
| VariableDeclarationList declarationList =
|
| node.getAncestor((n) => n is VariableDeclarationList);
|
| @@ -1648,18 +1717,7 @@ class AssistProcessor {
|
| }
|
|
|
| void _addProposal_reparentFlutterWidget() {
|
| - InstanceCreationExpression newExpr;
|
| - if (node is SimpleIdentifier) {
|
| - if (node.parent is ConstructorName &&
|
| - node.parent.parent is InstanceCreationExpression) {
|
| - newExpr = node.parent.parent;
|
| - } else if (node.parent?.parent is ConstructorName &&
|
| - node.parent.parent?.parent is InstanceCreationExpression) {
|
| - newExpr = node.parent.parent.parent;
|
| - }
|
| - } else if (node is InstanceCreationExpression) {
|
| - newExpr = node;
|
| - }
|
| + InstanceCreationExpression newExpr = _identifyNewExpression();
|
| if (newExpr == null || !_isFlutterInstanceCreationExpression(newExpr)) {
|
| _coverageMarker();
|
| return;
|
| @@ -2242,6 +2300,29 @@ class AssistProcessor {
|
| }
|
| }
|
|
|
| + NamedExpression _findChildArgument(InstanceCreationExpression newExpr) =>
|
| + newExpr.argumentList.arguments.firstWhere(
|
| + (arg) => arg is NamedExpression && arg.name.label.name == 'child',
|
| + orElse: () => null);
|
| +
|
| + InstanceCreationExpression _findChildWidget(
|
| + InstanceCreationExpression newExpr) {
|
| + NamedExpression child = _findChildArgument(newExpr);
|
| + return _getChildWidget(child);
|
| + }
|
| +
|
| + InstanceCreationExpression _getChildWidget(NamedExpression child) {
|
| + if (child?.expression is InstanceCreationExpression) {
|
| + InstanceCreationExpression childNewExpr = child.expression;
|
| + if (_isFlutterInstanceCreationExpression(childNewExpr)) {
|
| + if (_findChildArgument(childNewExpr) != null) {
|
| + return childNewExpr;
|
| + }
|
| + }
|
| + }
|
| + return null;
|
| + }
|
| +
|
| /**
|
| * Returns an existing or just added [LinkedEditGroup] with [groupId].
|
| */
|
| @@ -2268,6 +2349,22 @@ class AssistProcessor {
|
| return utils.getRangeText(range);
|
| }
|
|
|
| + InstanceCreationExpression _identifyNewExpression() {
|
| + InstanceCreationExpression newExpr;
|
| + if (node is SimpleIdentifier) {
|
| + if (node.parent is ConstructorName &&
|
| + node.parent.parent is InstanceCreationExpression) {
|
| + newExpr = node.parent.parent;
|
| + } else if (node.parent?.parent is ConstructorName &&
|
| + node.parent.parent?.parent is InstanceCreationExpression) {
|
| + newExpr = node.parent.parent.parent;
|
| + }
|
| + } else if (node is InstanceCreationExpression) {
|
| + newExpr = node;
|
| + }
|
| + return newExpr;
|
| + }
|
| +
|
| /**
|
| * Inserts the given [SourceBuilder] at its offset.
|
| */
|
| @@ -2318,6 +2415,89 @@ class AssistProcessor {
|
| return new Position(file, offset);
|
| }
|
|
|
| + void _swapFlutterWidgets(
|
| + InstanceCreationExpression exprGoingDown,
|
| + InstanceCreationExpression exprGoingUp,
|
| + NamedExpression stableChild,
|
| + AssistKind assistKind) {
|
| + String currentSource = analysisContext.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;
|
| + }
|
| + // 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');
|
| + }
|
| + } else {
|
| + argSrc = getSrc(val);
|
| + argSrc = argSrc.replaceAll(
|
| + new RegExp("^$outerIndent", multiLine: true), "$innerIndent");
|
| + sb.append(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);
|
| + }
|
| + });
|
| + sb.append(outerIndent);
|
| + sb.append(')');
|
| +
|
| + exitPosition = _newPosition(sb.offset + sb.length);
|
| + _insertBuilder(sb, exprGoingDown.length);
|
| + _addAssist(assistKind, []);
|
| + }
|
| +
|
| /**
|
| * This method does nothing, but we invoke it in places where Dart VM
|
| * coverage agent fails to provide coverage information - such as almost
|
|
|