Add support of "braceless" blocks

This commit is contained in:
Alexey Sedunov
2013-06-03 17:03:24 +04:00
parent 30e333c670
commit cda940f415
8 changed files with 134 additions and 48 deletions
@@ -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 = ""
}
@@ -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");