Fix moving of value parameters and arguments
This commit is contained in:
@@ -73,6 +73,13 @@ public class JetPsiFactory {
|
|||||||
return star;
|
return star;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static PsiElement createComma(Project project) {
|
||||||
|
PsiElement comma = createType(project, "T<X, Y>").findElementAt(3);
|
||||||
|
assert comma != null;
|
||||||
|
return comma;
|
||||||
|
}
|
||||||
|
|
||||||
//the pair contains the first and the last elements of a range
|
//the pair contains the first and the last elements of a range
|
||||||
public static Pair<PsiElement, PsiElement> createColonAndWhiteSpaces(Project project) {
|
public static Pair<PsiElement, PsiElement> createColonAndWhiteSpaces(Project project) {
|
||||||
JetProperty property = createProperty(project, "val x : Int");
|
JetProperty property = createProperty(project, "val x : Int");
|
||||||
|
|||||||
@@ -64,6 +64,11 @@ public abstract class AbstractJetUpDownMover extends LineMover {
|
|||||||
return firstNonWhiteElement(down ? lineRange.lastElement.getNextSibling() : lineRange.firstElement.getPrevSibling(), down);
|
return firstNonWhiteElement(down ? lineRange.lastElement.getNextSibling() : lineRange.firstElement.getPrevSibling(), down);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
protected static PsiElement firstNonWhiteSibling(@NotNull PsiElement element, boolean down) {
|
||||||
|
return firstNonWhiteElement(down ? element.getNextSibling() : element.getPrevSibling(), down);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkAvailable(@NotNull Editor editor, @NotNull PsiFile file, @NotNull MoveInfo info, boolean down) {
|
public boolean checkAvailable(@NotNull Editor editor, @NotNull PsiFile file, @NotNull MoveInfo info, boolean down) {
|
||||||
return (file instanceof JetFile) && super.checkAvailable(editor, file, info, down);
|
return (file instanceof JetFile) && super.checkAvailable(editor, file, info, down);
|
||||||
|
|||||||
@@ -5,10 +5,7 @@ import com.intellij.openapi.editor.Document;
|
|||||||
import com.intellij.openapi.editor.Editor;
|
import com.intellij.openapi.editor.Editor;
|
||||||
import com.intellij.openapi.util.Pair;
|
import com.intellij.openapi.util.Pair;
|
||||||
import com.intellij.openapi.util.TextRange;
|
import com.intellij.openapi.util.TextRange;
|
||||||
import com.intellij.psi.PsiComment;
|
import com.intellij.psi.*;
|
||||||
import com.intellij.psi.PsiElement;
|
|
||||||
import com.intellij.psi.PsiFile;
|
|
||||||
import com.intellij.psi.PsiWhiteSpace;
|
|
||||||
import com.intellij.psi.util.PsiTreeUtil;
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -20,7 +17,7 @@ public class JetExpressionMover extends AbstractJetUpDownMover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("FieldMayBeFinal")
|
@SuppressWarnings("FieldMayBeFinal")
|
||||||
private static Class[] MOVABLE_ELEMENT_CLASSES = {JetExpression.class, JetWhenEntry.class, PsiComment.class};
|
private static Class[] MOVABLE_ELEMENT_CLASSES = {JetExpression.class, JetWhenEntry.class, JetValueArgument.class, PsiComment.class};
|
||||||
|
|
||||||
@SuppressWarnings("FieldMayBeFinal")
|
@SuppressWarnings("FieldMayBeFinal")
|
||||||
private static Class[] BLOCKLIKE_ELEMENT_CLASSES =
|
private static Class[] BLOCKLIKE_ELEMENT_CLASSES =
|
||||||
@@ -231,12 +228,35 @@ public class JetExpressionMover extends AbstractJetUpDownMover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static LineRange getTargetRange(
|
private LineRange getValueParamOrArgTargetRange(@NotNull Editor editor, @NotNull PsiElement elementToCheck, @NotNull PsiElement sibling, boolean down) {
|
||||||
|
PsiElement next = sibling;
|
||||||
|
|
||||||
|
if (next.getNode().getElementType() == JetTokens.COMMA) {
|
||||||
|
next = firstNonWhiteSibling(next, down);
|
||||||
|
}
|
||||||
|
|
||||||
|
LineRange range = (next instanceof JetParameter || next instanceof JetValueArgument)
|
||||||
|
? new LineRange(next, next, editor.getDocument())
|
||||||
|
: null;
|
||||||
|
|
||||||
|
if (range != null) {
|
||||||
|
parametersOrArgsToMove = new Pair<PsiElement, PsiElement>(elementToCheck, next);
|
||||||
|
}
|
||||||
|
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private LineRange getTargetRange(
|
||||||
@NotNull Editor editor,
|
@NotNull Editor editor,
|
||||||
@Nullable PsiElement elementToCheck,
|
@Nullable PsiElement elementToCheck,
|
||||||
@NotNull PsiElement sibling,
|
@NotNull PsiElement sibling,
|
||||||
boolean down
|
boolean down
|
||||||
) {
|
) {
|
||||||
|
if (elementToCheck instanceof JetParameter || elementToCheck instanceof JetValueArgument) {
|
||||||
|
return getValueParamOrArgTargetRange(editor, elementToCheck, sibling, down);
|
||||||
|
}
|
||||||
|
|
||||||
if (elementToCheck instanceof JetExpression || elementToCheck instanceof PsiComment) {
|
if (elementToCheck instanceof JetExpression || elementToCheck instanceof PsiComment) {
|
||||||
return getExpressionTargetRange(editor, sibling, down);
|
return getExpressionTargetRange(editor, sibling, down);
|
||||||
}
|
}
|
||||||
@@ -276,19 +296,16 @@ public class JetExpressionMover extends AbstractJetUpDownMover {
|
|||||||
return movableElement;
|
return movableElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static enum MoveStatus {
|
private static boolean isLastOfItsKind(@NotNull PsiElement element, boolean down) {
|
||||||
DEFAULT,
|
return getSiblingOfType(element, down, element.getClass()) == null;
|
||||||
FORBIDDEN,
|
|
||||||
PERMITTED
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MoveStatus getMoveStatus(@NotNull PsiElement element, boolean down) {
|
private static boolean isForbiddenMove(@NotNull PsiElement element, boolean down) {
|
||||||
if (element instanceof JetParameter) {
|
if (element instanceof JetParameter || element instanceof JetValueArgument) {
|
||||||
PsiElement sibling = getSiblingOfType(element, down, element.getClass());
|
return isLastOfItsKind(element, down);
|
||||||
return (sibling != null) ? MoveStatus.DEFAULT : MoveStatus.FORBIDDEN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return MoveStatus.PERMITTED;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isBracelessBlock(@NotNull PsiElement element) {
|
private static boolean isBracelessBlock(@NotNull PsiElement element) {
|
||||||
@@ -348,6 +365,8 @@ public class JetExpressionMover extends AbstractJetUpDownMover {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkAvailable(@NotNull Editor editor, @NotNull PsiFile file, @NotNull MoveInfo info, boolean down) {
|
public boolean checkAvailable(@NotNull Editor editor, @NotNull PsiFile file, @NotNull MoveInfo info, boolean down) {
|
||||||
|
parametersOrArgsToMove = null;
|
||||||
|
|
||||||
if (!super.checkAvailable(editor, file, info, down)) return false;
|
if (!super.checkAvailable(editor, file, info, down)) return false;
|
||||||
|
|
||||||
switch (checkForMovableClosingBrace(editor, file, info, down)) {
|
switch (checkForMovableClosingBrace(editor, file, info, down)) {
|
||||||
@@ -370,16 +389,13 @@ public class JetExpressionMover extends AbstractJetUpDownMover {
|
|||||||
|
|
||||||
if (firstElement == null || lastElement == null) return false;
|
if (firstElement == null || lastElement == null) return false;
|
||||||
|
|
||||||
MoveStatus firstMoveStatus = getMoveStatus(firstElement, down);
|
if (isForbiddenMove(firstElement, down) || isForbiddenMove(lastElement, down)) {
|
||||||
MoveStatus lastMoveStatus = getMoveStatus(lastElement, down);
|
info.toMove2 = null;
|
||||||
|
|
||||||
if (firstMoveStatus == MoveStatus.DEFAULT || lastMoveStatus == MoveStatus.DEFAULT) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (firstMoveStatus == MoveStatus.FORBIDDEN || lastMoveStatus == MoveStatus.FORBIDDEN) {
|
if ((firstElement instanceof JetParameter || firstElement instanceof JetValueArgument) && PsiTreeUtil.isAncestor(lastElement, firstElement, false)) {
|
||||||
info.toMove2 = null;
|
lastElement = firstElement;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LineRange sourceRange = getSourceRange(firstElement, lastElement, editor, oldRange);
|
LineRange sourceRange = getSourceRange(firstElement, lastElement, editor, oldRange);
|
||||||
@@ -394,4 +410,39 @@ public class JetExpressionMover extends AbstractJetUpDownMover {
|
|||||||
info.toMove2 = getTargetRange(editor, sourceRange.firstElement, sibling, down);
|
info.toMove2 = getTargetRange(editor, sourceRange.firstElement, sibling, down);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private Pair<PsiElement, PsiElement> parametersOrArgsToMove;
|
||||||
|
|
||||||
|
private static PsiElement getComma(@NotNull PsiElement element) {
|
||||||
|
PsiElement sibling = firstNonWhiteSibling(element, true);
|
||||||
|
return sibling != null && (sibling.getNode().getElementType() == JetTokens.COMMA) ? sibling : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void fixCommaIfNeeded(@NotNull PsiElement element, boolean willBeLast) {
|
||||||
|
PsiElement comma = getComma(element);
|
||||||
|
if (willBeLast && comma != null) {
|
||||||
|
comma.delete();
|
||||||
|
}
|
||||||
|
else if (!willBeLast && comma == null) {
|
||||||
|
PsiElement parent = element.getParent();
|
||||||
|
assert parent != null;
|
||||||
|
|
||||||
|
parent.addAfter(JetPsiFactory.createComma(parent.getProject()), element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeMove(@NotNull Editor editor, @NotNull MoveInfo info, boolean down) {
|
||||||
|
if (parametersOrArgsToMove != null) {
|
||||||
|
PsiElement element1 = parametersOrArgsToMove.first;
|
||||||
|
PsiElement element2 = parametersOrArgsToMove.second;
|
||||||
|
|
||||||
|
fixCommaIfNeeded(element1, down && isLastOfItsKind(element2, true));
|
||||||
|
fixCommaIfNeeded(element2, !down && isLastOfItsKind(element1, true));
|
||||||
|
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
PsiDocumentManager.getInstance(editor.getProject()).doPostponedOperationsAndUnblockDocument(editor.getDocument());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
// MOVE: down
|
||||||
|
// MOVER_CLASS: org.jetbrains.jet.plugin.codeInsight.upDownMover.JetExpressionMover
|
||||||
|
val x = foo(
|
||||||
|
<caret>a,
|
||||||
|
b,
|
||||||
|
c
|
||||||
|
)
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
// MOVE: down
|
||||||
|
// MOVER_CLASS: org.jetbrains.jet.plugin.codeInsight.upDownMover.JetExpressionMover
|
||||||
|
val x = foo(
|
||||||
|
b,
|
||||||
|
<caret>a,
|
||||||
|
c
|
||||||
|
)
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
// MOVE: down
|
||||||
|
// MOVER_CLASS: org.jetbrains.jet.plugin.codeInsight.upDownMover.JetExpressionMover
|
||||||
|
val x = foo(
|
||||||
|
b,
|
||||||
|
<caret>a,
|
||||||
|
c
|
||||||
|
)
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
// MOVE: down
|
||||||
|
// MOVER_CLASS: org.jetbrains.jet.plugin.codeInsight.upDownMover.JetExpressionMover
|
||||||
|
val x = foo(
|
||||||
|
b,
|
||||||
|
c,
|
||||||
|
<caret>a
|
||||||
|
)
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
// MOVE: down
|
||||||
|
// MOVER_CLASS: org.jetbrains.jet.plugin.codeInsight.upDownMover.JetExpressionMover
|
||||||
|
// IS_APPLICABLE: false
|
||||||
|
val x = foo(
|
||||||
|
b,
|
||||||
|
c,
|
||||||
|
<caret>a
|
||||||
|
)
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
// MOVE: up
|
||||||
|
// MOVER_CLASS: org.jetbrains.jet.plugin.codeInsight.upDownMover.JetExpressionMover
|
||||||
|
val x = foo(
|
||||||
|
b,
|
||||||
|
c,
|
||||||
|
<caret>a
|
||||||
|
)
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
// MOVE: up
|
||||||
|
// MOVER_CLASS: org.jetbrains.jet.plugin.codeInsight.upDownMover.JetExpressionMover
|
||||||
|
val x = foo(
|
||||||
|
b,
|
||||||
|
<caret>a,
|
||||||
|
c
|
||||||
|
)
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
// MOVE: up
|
||||||
|
// MOVER_CLASS: org.jetbrains.jet.plugin.codeInsight.upDownMover.JetExpressionMover
|
||||||
|
val x = foo(
|
||||||
|
b,
|
||||||
|
<caret>a,
|
||||||
|
c
|
||||||
|
)
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
// MOVE: up
|
||||||
|
// MOVER_CLASS: org.jetbrains.jet.plugin.codeInsight.upDownMover.JetExpressionMover
|
||||||
|
val x = foo(
|
||||||
|
<caret>a,
|
||||||
|
b,
|
||||||
|
c
|
||||||
|
)
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
// MOVE: up
|
||||||
|
// MOVER_CLASS: org.jetbrains.jet.plugin.codeInsight.upDownMover.JetExpressionMover
|
||||||
|
// IS_APPLICABLE: false
|
||||||
|
val x = foo(
|
||||||
|
<caret>a,
|
||||||
|
b,
|
||||||
|
c
|
||||||
|
)
|
||||||
+3
-3
@@ -5,9 +5,9 @@ class A {
|
|||||||
U,
|
U,
|
||||||
W>(
|
W>(
|
||||||
b: Int,
|
b: Int,
|
||||||
c: Int
|
c: Int,
|
||||||
<caret>a: Int,
|
<caret>a: Int
|
||||||
) {
|
) {
|
||||||
|
|
||||||
}
|
}
|
||||||
class B {
|
class B {
|
||||||
|
|||||||
+10
-3
@@ -19,9 +19,11 @@ package org.jetbrains.jet.plugin.codeInsight.moveUpDown;
|
|||||||
import com.intellij.codeInsight.editorActions.moveUpDown.MoveStatementDownAction;
|
import com.intellij.codeInsight.editorActions.moveUpDown.MoveStatementDownAction;
|
||||||
import com.intellij.codeInsight.editorActions.moveUpDown.MoveStatementUpAction;
|
import com.intellij.codeInsight.editorActions.moveUpDown.MoveStatementUpAction;
|
||||||
import com.intellij.codeInsight.editorActions.moveUpDown.StatementUpDownMover;
|
import com.intellij.codeInsight.editorActions.moveUpDown.StatementUpDownMover;
|
||||||
|
import com.intellij.openapi.application.ApplicationManager;
|
||||||
import com.intellij.openapi.editor.actionSystem.EditorAction;
|
import com.intellij.openapi.editor.actionSystem.EditorAction;
|
||||||
import com.intellij.openapi.extensions.Extensions;
|
import com.intellij.openapi.extensions.Extensions;
|
||||||
import com.intellij.openapi.util.io.FileUtil;
|
import com.intellij.openapi.util.io.FileUtil;
|
||||||
|
import com.intellij.psi.PsiDocumentManager;
|
||||||
import com.intellij.testFramework.LightCodeInsightTestCase;
|
import com.intellij.testFramework.LightCodeInsightTestCase;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.InTextDirectivesUtils;
|
import org.jetbrains.jet.InTextDirectivesUtils;
|
||||||
@@ -83,9 +85,14 @@ public abstract class AbstractCodeMoverTest extends LightCodeInsightTestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void invokeAndCheck(@NotNull String path, boolean down) {
|
private void invokeAndCheck(@NotNull String path, final boolean down) {
|
||||||
EditorAction action = down ? new MoveStatementDownAction() : new MoveStatementUpAction();
|
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||||
action.actionPerformed(getEditor(), getCurrentEditorDataContext());
|
@Override
|
||||||
|
public void run() {
|
||||||
|
EditorAction action = down ? new MoveStatementDownAction() : new MoveStatementUpAction();
|
||||||
|
action.actionPerformed(getEditor(), getCurrentEditorDataContext());
|
||||||
|
}
|
||||||
|
});
|
||||||
checkResultByFile(path + ".after");
|
checkResultByFile(path + ".after");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+30
@@ -385,6 +385,36 @@ public class CodeMoverTestGenerated extends AbstractCodeMoverTest {
|
|||||||
doTestClassBodyDeclaration("idea/testData/codeInsight/moveUpDown/classBodyDeclarations/functionAnchors/typeParams3.kt");
|
doTestClassBodyDeclaration("idea/testData/codeInsight/moveUpDown/classBodyDeclarations/functionAnchors/typeParams3.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("valueArgs1.kt")
|
||||||
|
public void testValueArgs1() throws Exception {
|
||||||
|
doTestClassBodyDeclaration("idea/testData/codeInsight/moveUpDown/classBodyDeclarations/functionAnchors/valueArgs1.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("valueArgs2.kt")
|
||||||
|
public void testValueArgs2() throws Exception {
|
||||||
|
doTestClassBodyDeclaration("idea/testData/codeInsight/moveUpDown/classBodyDeclarations/functionAnchors/valueArgs2.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("valueArgs3.kt")
|
||||||
|
public void testValueArgs3() throws Exception {
|
||||||
|
doTestClassBodyDeclaration("idea/testData/codeInsight/moveUpDown/classBodyDeclarations/functionAnchors/valueArgs3.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("valueArgs4.kt")
|
||||||
|
public void testValueArgs4() throws Exception {
|
||||||
|
doTestClassBodyDeclaration("idea/testData/codeInsight/moveUpDown/classBodyDeclarations/functionAnchors/valueArgs4.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("valueArgs5.kt")
|
||||||
|
public void testValueArgs5() throws Exception {
|
||||||
|
doTestClassBodyDeclaration("idea/testData/codeInsight/moveUpDown/classBodyDeclarations/functionAnchors/valueArgs5.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("valueArgs6.kt")
|
||||||
|
public void testValueArgs6() throws Exception {
|
||||||
|
doTestClassBodyDeclaration("idea/testData/codeInsight/moveUpDown/classBodyDeclarations/functionAnchors/valueArgs6.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("valueParams1.kt")
|
@TestMetadata("valueParams1.kt")
|
||||||
public void testValueParams1() throws Exception {
|
public void testValueParams1() throws Exception {
|
||||||
doTestClassBodyDeclaration("idea/testData/codeInsight/moveUpDown/classBodyDeclarations/functionAnchors/valueParams1.kt");
|
doTestClassBodyDeclaration("idea/testData/codeInsight/moveUpDown/classBodyDeclarations/functionAnchors/valueParams1.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user