diff --git a/idea/src/org/jetbrains/jet/plugin/codeInsight/upDownMover/AbstractJetUpDownMover.java b/idea/src/org/jetbrains/jet/plugin/codeInsight/upDownMover/AbstractJetUpDownMover.java index c752befc5e4..9605c588294 100644 --- a/idea/src/org/jetbrains/jet/plugin/codeInsight/upDownMover/AbstractJetUpDownMover.java +++ b/idea/src/org/jetbrains/jet/plugin/codeInsight/upDownMover/AbstractJetUpDownMover.java @@ -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 type) { return down ? PsiTreeUtil.getNextSiblingOfType(element, type) : PsiTreeUtil.getPrevSiblingOfType(element, type); diff --git a/idea/src/org/jetbrains/jet/plugin/codeInsight/upDownMover/JetExpressionMover.java b/idea/src/org/jetbrains/jet/plugin/codeInsight/upDownMover/JetExpressionMover.java index 3f6b65a0a93..5909b1ba488 100644 --- a/idea/src/org/jetbrains/jet/plugin/codeInsight/upDownMover/JetExpressionMover.java +++ b/idea/src/org/jetbrains/jet/plugin/codeInsight/upDownMover/JetExpressionMover.java @@ -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; diff --git a/idea/testData/codeInsight/moveUpDown/expressions/lambda1.kt b/idea/testData/codeInsight/moveUpDown/expressions/lambda1.kt new file mode 100644 index 00000000000..26b312d0bac --- /dev/null +++ b/idea/testData/codeInsight/moveUpDown/expressions/lambda1.kt @@ -0,0 +1,9 @@ +// MOVE: down +val t = baz( + a, + b, + c +) { + val v = "" + val w = "" +} \ No newline at end of file diff --git a/idea/testData/codeInsight/moveUpDown/expressions/lambda1.kt.after b/idea/testData/codeInsight/moveUpDown/expressions/lambda1.kt.after new file mode 100644 index 00000000000..da4389c585a --- /dev/null +++ b/idea/testData/codeInsight/moveUpDown/expressions/lambda1.kt.after @@ -0,0 +1,9 @@ +// MOVE: down +val t = baz( + a, + b, + c +) { + val w = "" + val v = "" +} \ No newline at end of file diff --git a/idea/testData/codeInsight/moveUpDown/expressions/lambda2.kt b/idea/testData/codeInsight/moveUpDown/expressions/lambda2.kt new file mode 100644 index 00000000000..f7acc8c8ac8 --- /dev/null +++ b/idea/testData/codeInsight/moveUpDown/expressions/lambda2.kt @@ -0,0 +1,10 @@ +// MOVE: up +// IS_APPLICABLE: false +val t = baz( + a, + b, + c +) { + val v = "" + val w = "" +} \ No newline at end of file diff --git a/idea/testData/codeInsight/moveUpDown/expressions/lambda3.kt b/idea/testData/codeInsight/moveUpDown/expressions/lambda3.kt new file mode 100644 index 00000000000..ad70ab1e36b --- /dev/null +++ b/idea/testData/codeInsight/moveUpDown/expressions/lambda3.kt @@ -0,0 +1,10 @@ +// MOVE: up +val t = baz( + a, + b, + c +) { + + val v = "" + val w = "" +} \ No newline at end of file diff --git a/idea/testData/codeInsight/moveUpDown/expressions/lambda3.kt.after b/idea/testData/codeInsight/moveUpDown/expressions/lambda3.kt.after new file mode 100644 index 00000000000..dfcb8d8ba87 --- /dev/null +++ b/idea/testData/codeInsight/moveUpDown/expressions/lambda3.kt.after @@ -0,0 +1,10 @@ +// MOVE: up +val t = baz( + a, + b, + c +) { + val v = "" + + val w = "" +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/plugin/codeInsight/moveUpDown/CodeMoverTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/codeInsight/moveUpDown/CodeMoverTestGenerated.java index c7c96ca17f1..8172b77ac32 100644 --- a/idea/tests/org/jetbrains/jet/plugin/codeInsight/moveUpDown/CodeMoverTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/codeInsight/moveUpDown/CodeMoverTestGenerated.java @@ -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");