Add support of "braceless" blocks
This commit is contained in:
@@ -2,12 +2,9 @@ package org.jetbrains.jet.plugin.codeInsight.upDownMover;
|
||||
|
||||
import com.intellij.codeInsight.editorActions.moveUpDown.LineMover;
|
||||
import com.intellij.codeInsight.editorActions.moveUpDown.LineRange;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiWhiteSpace;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -17,41 +14,6 @@ public abstract class AbstractJetUpDownMover extends LineMover {
|
||||
protected AbstractJetUpDownMover() {
|
||||
}
|
||||
|
||||
protected static PsiElement adjustWhiteSpaceSibling(
|
||||
@NotNull Editor editor,
|
||||
@NotNull LineRange sourceRange,
|
||||
@NotNull MoveInfo info,
|
||||
boolean down
|
||||
) {
|
||||
PsiElement sibling = down ? sourceRange.lastElement.getNextSibling() : sourceRange.firstElement.getPrevSibling();
|
||||
|
||||
if (sibling instanceof PsiWhiteSpace) {
|
||||
Document doc = editor.getDocument();
|
||||
TextRange spaceRange = sibling.getTextRange();
|
||||
|
||||
int startLine = doc.getLineNumber(spaceRange.getStartOffset());
|
||||
int endLine = doc.getLineNumber(spaceRange.getEndOffset());
|
||||
|
||||
if (endLine - startLine > 1) {
|
||||
int nearLine = down ? sourceRange.endLine : sourceRange.startLine - 1;
|
||||
|
||||
info.toMove = sourceRange;
|
||||
info.toMove2 = new LineRange(nearLine, nearLine + 1);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
sibling = firstNonWhiteElement(sibling, down);
|
||||
}
|
||||
|
||||
if (sibling == null) {
|
||||
info.toMove2 = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
return sibling;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected static PsiElement getSiblingOfType(@NotNull PsiElement element, boolean down, @NotNull Class<? extends PsiElement> type) {
|
||||
return down ? PsiTreeUtil.getNextSiblingOfType(element, type) : PsiTreeUtil.getPrevSiblingOfType(element, type);
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiComment;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiWhiteSpace;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -181,15 +182,13 @@ public class JetExpressionMover extends AbstractJetUpDownMover {
|
||||
// moving out of code block
|
||||
if (sibling.getNode().getElementType() == (down ? JetTokens.RBRACE : JetTokens.LBRACE)) {
|
||||
PsiElement parent = sibling.getParent();
|
||||
if (!(parent instanceof JetBlockExpression)) return null;
|
||||
|
||||
JetBlockExpression block = (JetBlockExpression) parent;
|
||||
if (!(parent instanceof JetBlockExpression || parent instanceof JetFunctionLiteral)) return null;
|
||||
|
||||
JetBlockExpression newBlock = findClosestBlock(sibling, down);
|
||||
if (newBlock == null) return null;
|
||||
|
||||
if (PsiTreeUtil.isAncestor(newBlock, block, true)) {
|
||||
PsiElement outermostParent = JetPsiUtil.getOutermostParent(block, newBlock, true);
|
||||
if (PsiTreeUtil.isAncestor(newBlock, parent, true)) {
|
||||
PsiElement outermostParent = JetPsiUtil.getOutermostParent(parent, newBlock, true);
|
||||
|
||||
if (down) {
|
||||
end = outermostParent;
|
||||
@@ -212,7 +211,7 @@ public class JetExpressionMover extends AbstractJetUpDownMover {
|
||||
//noinspection unchecked
|
||||
JetElement blockLikeElement = JetPsiUtil.getOutermostJetElement(sibling, down, JetBlockExpression.class, JetWhenExpression.class, JetClassBody.class);
|
||||
if (blockLikeElement != null &&
|
||||
!(PsiTreeUtil.instanceOf(blockLikeElement, FUNCTIONLIKE_ELEMENT_CLASSES))) {
|
||||
!(PsiTreeUtil.instanceOf(blockLikeElement.getParent(), FUNCTIONLIKE_ELEMENT_CLASSES))) {
|
||||
if (blockLikeElement instanceof JetWhenExpression) {
|
||||
//noinspection unchecked
|
||||
blockLikeElement = JetPsiUtil.getOutermostJetElement(blockLikeElement, down, JetBlockExpression.class);
|
||||
@@ -299,8 +298,15 @@ public class JetExpressionMover extends AbstractJetUpDownMover {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiElement getMovableElement(@NotNull PsiElement element) {
|
||||
return PsiTreeUtil.getNonStrictParentOfType(element, MOVABLE_ELEMENT_CLASSES);
|
||||
private static PsiElement getMovableElement(@NotNull PsiElement element, boolean lookRight) {
|
||||
PsiElement movableElement = PsiTreeUtil.getNonStrictParentOfType(element, MOVABLE_ELEMENT_CLASSES);
|
||||
if (movableElement == null) return null;
|
||||
|
||||
if (isBracelessBlock(movableElement)) {
|
||||
movableElement = firstNonWhiteElement(lookRight ? movableElement.getLastChild() : movableElement.getFirstChild(), !lookRight);
|
||||
}
|
||||
|
||||
return movableElement;
|
||||
}
|
||||
|
||||
private static enum MoveStatus {
|
||||
@@ -318,6 +324,61 @@ public class JetExpressionMover extends AbstractJetUpDownMover {
|
||||
return MoveStatus.PERMITTED;
|
||||
}
|
||||
|
||||
private static boolean isBracelessBlock(@NotNull PsiElement element) {
|
||||
if (!(element instanceof JetBlockExpression)) return false;
|
||||
|
||||
JetBlockExpression block = (JetBlockExpression) element;
|
||||
|
||||
return block.getLBrace() == null && block.getRBrace() == null;
|
||||
}
|
||||
|
||||
protected static PsiElement adjustWhiteSpaceSibling(
|
||||
@NotNull Editor editor,
|
||||
@NotNull LineRange sourceRange,
|
||||
@NotNull MoveInfo info,
|
||||
boolean down
|
||||
) {
|
||||
PsiElement element = down ? sourceRange.lastElement : sourceRange.firstElement;
|
||||
PsiElement sibling = down ? element.getNextSibling() : element.getPrevSibling();
|
||||
|
||||
PsiElement whiteSpaceTestSubject = sibling;
|
||||
if (sibling == null) {
|
||||
PsiElement parent = element.getParent();
|
||||
if (parent != null && isBracelessBlock(parent)) {
|
||||
whiteSpaceTestSubject = down ? parent.getNextSibling() : parent.getPrevSibling();
|
||||
}
|
||||
}
|
||||
|
||||
if (whiteSpaceTestSubject instanceof PsiWhiteSpace) {
|
||||
Document doc = editor.getDocument();
|
||||
TextRange spaceRange = whiteSpaceTestSubject.getTextRange();
|
||||
|
||||
int startLine = doc.getLineNumber(spaceRange.getStartOffset());
|
||||
int endLine = doc.getLineNumber(spaceRange.getEndOffset());
|
||||
|
||||
if (endLine - startLine > 1) {
|
||||
int nearLine = down ? sourceRange.endLine : sourceRange.startLine - 1;
|
||||
|
||||
info.toMove = sourceRange;
|
||||
info.toMove2 = new LineRange(nearLine, nearLine + 1);
|
||||
info.indentTarget = false;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (sibling != null) {
|
||||
sibling = firstNonWhiteElement(sibling, down);
|
||||
}
|
||||
}
|
||||
|
||||
if (sibling == null) {
|
||||
info.toMove2 = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
return sibling;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkAvailable(@NotNull Editor editor, @NotNull PsiFile file, @NotNull MoveInfo info, boolean down) {
|
||||
if (!super.checkAvailable(editor, file, info, down)) return false;
|
||||
@@ -337,8 +398,8 @@ public class JetExpressionMover extends AbstractJetUpDownMover {
|
||||
if (psiRange == null) return false;
|
||||
|
||||
//noinspection unchecked
|
||||
PsiElement firstElement = getMovableElement(psiRange.getFirst());
|
||||
PsiElement lastElement = getMovableElement(psiRange.getSecond());
|
||||
PsiElement firstElement = getMovableElement(psiRange.getFirst(), false);
|
||||
PsiElement lastElement = getMovableElement(psiRange.getSecond(), true);
|
||||
|
||||
if (firstElement == null || lastElement == null) return false;
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
// MOVE: down
|
||||
val t = baz(
|
||||
a,
|
||||
b,
|
||||
c
|
||||
) {
|
||||
<caret>val v = ""
|
||||
val w = ""
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// MOVE: down
|
||||
val t = baz(
|
||||
a,
|
||||
b,
|
||||
c
|
||||
) {
|
||||
val w = ""
|
||||
<caret>val v = ""
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// MOVE: up
|
||||
// IS_APPLICABLE: false
|
||||
val t = baz(
|
||||
a,
|
||||
b,
|
||||
c
|
||||
) {
|
||||
<caret>val v = ""
|
||||
val w = ""
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// MOVE: up
|
||||
val t = baz(
|
||||
a,
|
||||
b,
|
||||
c
|
||||
) {
|
||||
|
||||
<caret>val v = ""
|
||||
val w = ""
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// MOVE: up
|
||||
val t = baz(
|
||||
a,
|
||||
b,
|
||||
c
|
||||
) {
|
||||
<caret>val v = ""
|
||||
|
||||
val w = ""
|
||||
}
|
||||
+15
@@ -728,6 +728,21 @@ public class CodeMoverTestGenerated extends AbstractCodeMoverTest {
|
||||
doTestExpression("idea/testData/codeInsight/moveUpDown/expressions/if4.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lambda1.kt")
|
||||
public void testLambda1() throws Exception {
|
||||
doTestExpression("idea/testData/codeInsight/moveUpDown/expressions/lambda1.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lambda2.kt")
|
||||
public void testLambda2() throws Exception {
|
||||
doTestExpression("idea/testData/codeInsight/moveUpDown/expressions/lambda2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lambda3.kt")
|
||||
public void testLambda3() throws Exception {
|
||||
doTestExpression("idea/testData/codeInsight/moveUpDown/expressions/lambda3.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("when1.kt")
|
||||
public void testWhen1() throws Exception {
|
||||
doTestExpression("idea/testData/codeInsight/moveUpDown/expressions/when1.kt");
|
||||
|
||||
Reference in New Issue
Block a user