From 4a19d4f77b216bd2f351d03371fc008b4a69246d Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Fri, 5 Jul 2013 15:30:03 +0400 Subject: [PATCH] Fix "Move statement" for the cases when nested closure is used (KT-3735) --- .../jetbrains/jet/lang/psi/JetPsiUtil.java | 10 +-- .../upDownMover/JetExpressionMover.java | 64 ++++++++++++------- .../expressions/closureInDoWhile1.kt | 8 +++ .../expressions/closureInDoWhile1.kt.after | 8 +++ .../expressions/closureInDoWhile2.kt | 8 +++ .../expressions/closureInDoWhile2.kt.after | 8 +++ .../moveUpDown/expressions/closureInFor1.kt | 7 ++ .../expressions/closureInFor1.kt.after | 7 ++ .../moveUpDown/expressions/closureInFor2.kt | 7 ++ .../expressions/closureInFor2.kt.after | 7 ++ .../moveUpDown/expressions/closureInIf1.kt | 7 ++ .../expressions/closureInIf1.kt.after | 7 ++ .../moveUpDown/expressions/closureInIf2.kt | 7 ++ .../expressions/closureInIf2.kt.after | 7 ++ .../moveUpDown/expressions/closureInWhile1.kt | 8 +++ .../expressions/closureInWhile1.kt.after | 8 +++ .../moveUpDown/expressions/closureInWhile2.kt | 8 +++ .../expressions/closureInWhile2.kt.after | 8 +++ .../moveUpDown/CodeMoverTestGenerated.java | 40 ++++++++++++ 19 files changed, 206 insertions(+), 28 deletions(-) create mode 100644 idea/testData/codeInsight/moveUpDown/expressions/closureInDoWhile1.kt create mode 100644 idea/testData/codeInsight/moveUpDown/expressions/closureInDoWhile1.kt.after create mode 100644 idea/testData/codeInsight/moveUpDown/expressions/closureInDoWhile2.kt create mode 100644 idea/testData/codeInsight/moveUpDown/expressions/closureInDoWhile2.kt.after create mode 100644 idea/testData/codeInsight/moveUpDown/expressions/closureInFor1.kt create mode 100644 idea/testData/codeInsight/moveUpDown/expressions/closureInFor1.kt.after create mode 100644 idea/testData/codeInsight/moveUpDown/expressions/closureInFor2.kt create mode 100644 idea/testData/codeInsight/moveUpDown/expressions/closureInFor2.kt.after create mode 100644 idea/testData/codeInsight/moveUpDown/expressions/closureInIf1.kt create mode 100644 idea/testData/codeInsight/moveUpDown/expressions/closureInIf1.kt.after create mode 100644 idea/testData/codeInsight/moveUpDown/expressions/closureInIf2.kt create mode 100644 idea/testData/codeInsight/moveUpDown/expressions/closureInIf2.kt.after create mode 100644 idea/testData/codeInsight/moveUpDown/expressions/closureInWhile1.kt create mode 100644 idea/testData/codeInsight/moveUpDown/expressions/closureInWhile1.kt.after create mode 100644 idea/testData/codeInsight/moveUpDown/expressions/closureInWhile2.kt create mode 100644 idea/testData/codeInsight/moveUpDown/expressions/closureInWhile2.kt.after diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java index 1aa0917c074..a5505b3783a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java @@ -779,22 +779,22 @@ public class JetPsiUtil { } @Nullable - public static T getOutermostJetElement( + public static JetElement getOutermostDescendantElement( @Nullable PsiElement root, boolean first, - @NotNull final Class... elementTypes + final @NotNull Predicate predicate ) { if (!(root instanceof JetElement)) return null; - final List results = Lists.newArrayList(); + final List results = Lists.newArrayList(); ((JetElement) root).accept( new JetVisitorVoid() { @Override public void visitJetElement(JetElement element) { - if (PsiTreeUtil.instanceOf(element, elementTypes)) { + if (predicate.apply(element)) { //noinspection unchecked - results.add((T) element); + results.add(element); } else { element.acceptChildren(this); 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 438622f1c8b..1b3a968d083 100644 --- a/idea/src/org/jetbrains/jet/plugin/codeInsight/upDownMover/JetExpressionMover.java +++ b/idea/src/org/jetbrains/jet/plugin/codeInsight/upDownMover/JetExpressionMover.java @@ -1,5 +1,6 @@ package org.jetbrains.jet.plugin.codeInsight.upDownMover; +import com.google.common.base.Predicate; import com.intellij.codeInsight.editorActions.moveUpDown.LineRange; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; @@ -13,10 +14,12 @@ import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lexer.JetTokens; public class JetExpressionMover extends AbstractJetUpDownMover { + public JetExpressionMover() { } - private final static Class[] MOVABLE_ELEMENT_CLASSES = {JetExpression.class, JetWhenEntry.class, JetValueArgument.class, PsiComment.class}; + private final static Class[] MOVABLE_ELEMENT_CLASSES = + {JetExpression.class, JetWhenEntry.class, JetValueArgument.class, PsiComment.class}; private final static Class[] BLOCKLIKE_ELEMENT_CLASSES = {JetBlockExpression.class, JetWhenExpression.class, JetClassBody.class, JetFile.class}; @@ -24,6 +27,21 @@ public class JetExpressionMover extends AbstractJetUpDownMover { private final static Class[] FUNCTIONLIKE_ELEMENT_CLASSES = {JetFunction.class, JetPropertyAccessor.class, JetClassInitializer.class}; + private static final Predicate CHECK_BLOCK_LIKE_ELEMENT = new Predicate() { + @Override + public boolean apply(@Nullable JetElement input) { + return (input instanceof JetBlockExpression || input instanceof JetClassBody) + && !PsiTreeUtil.instanceOf(input.getParent(), FUNCTIONLIKE_ELEMENT_CLASSES); + } + }; + + private static final Predicate CHECK_BLOCK = new Predicate() { + @Override + public boolean apply(@Nullable JetElement input) { + return input instanceof JetBlockExpression && !PsiTreeUtil.instanceOf(input.getParent(), FUNCTIONLIKE_ELEMENT_CLASSES); + } + }; + @Nullable private static PsiElement getStandaloneClosingBrace(@NotNull PsiFile file, @NotNull Editor editor) { LineRange range = getLineRangeFromSelection(editor); @@ -137,7 +155,7 @@ public class JetExpressionMover extends AbstractJetUpDownMover { PsiElement parent = current.getParent(); if (parent instanceof JetClassBody || parent instanceof JetClassInitializer || - parent instanceof JetFunction || + parent instanceof JetNamedFunction || parent instanceof JetProperty) { return null; } @@ -147,7 +165,7 @@ public class JetExpressionMover extends AbstractJetUpDownMover { PsiElement sibling = down ? current.getNextSibling() : current.getPrevSibling(); if (sibling != null) { //noinspection unchecked - JetBlockExpression block = JetPsiUtil.getOutermostJetElement(sibling, down, JetBlockExpression.class); + JetBlockExpression block = (JetBlockExpression) JetPsiUtil.getOutermostDescendantElement(sibling, down, CHECK_BLOCK); if (block != null) return block; current = sibling; @@ -195,21 +213,13 @@ public class JetExpressionMover extends AbstractJetUpDownMover { else { // moving into code block //noinspection unchecked - JetElement blockLikeElement = JetPsiUtil.getOutermostJetElement(sibling, down, JetBlockExpression.class, JetWhenExpression.class, JetClassBody.class); - if (blockLikeElement != null && - !(PsiTreeUtil.instanceOf(blockLikeElement.getParent(), FUNCTIONLIKE_ELEMENT_CLASSES))) { - if (blockLikeElement instanceof JetWhenExpression) { - //noinspection unchecked - blockLikeElement = JetPsiUtil.getOutermostJetElement(blockLikeElement, down, JetBlockExpression.class); + JetElement blockLikeElement = JetPsiUtil.getOutermostDescendantElement(sibling, down, CHECK_BLOCK_LIKE_ELEMENT); + if (blockLikeElement != null) { + if (down) { + end = JetPsiUtil.findChildByType(blockLikeElement, JetTokens.LBRACE); } - - if (blockLikeElement != null) { - if (down) { - end = JetPsiUtil.findChildByType(blockLikeElement, JetTokens.LBRACE); - } - else { - start = JetPsiUtil.findChildByType(blockLikeElement, JetTokens.RBRACE); - } + else { + start = JetPsiUtil.findChildByType(blockLikeElement, JetTokens.RBRACE); } } } @@ -228,7 +238,12 @@ public class JetExpressionMover extends AbstractJetUpDownMover { } @Nullable - private LineRange getValueParamOrArgTargetRange(@NotNull Editor editor, @NotNull PsiElement elementToCheck, @NotNull PsiElement sibling, boolean down) { + private LineRange getValueParamOrArgTargetRange( + @NotNull Editor editor, + @NotNull PsiElement elementToCheck, + @NotNull PsiElement sibling, + boolean down + ) { PsiElement next = sibling; if (next.getNode().getElementType() == JetTokens.COMMA) { @@ -236,8 +251,8 @@ public class JetExpressionMover extends AbstractJetUpDownMover { } LineRange range = (next instanceof JetParameter || next instanceof JetValueArgument) - ? new LineRange(next, next, editor.getDocument()) - : null; + ? new LineRange(next, next, editor.getDocument()) + : null; if (range != null) { parametersOrArgsToMove = new Pair(elementToCheck, next); @@ -374,8 +389,10 @@ public class JetExpressionMover extends AbstractJetUpDownMover { info.toMove2 = null; return true; } - case MOVABLE: return true; - default: break; + case MOVABLE: + return true; + default: + break; } LineRange oldRange = info.toMove; @@ -394,7 +411,8 @@ public class JetExpressionMover extends AbstractJetUpDownMover { return true; } - if ((firstElement instanceof JetParameter || firstElement instanceof JetValueArgument) && PsiTreeUtil.isAncestor(lastElement, firstElement, false)) { + if ((firstElement instanceof JetParameter || firstElement instanceof JetValueArgument) && + PsiTreeUtil.isAncestor(lastElement, firstElement, false)) { lastElement = firstElement; } diff --git a/idea/testData/codeInsight/moveUpDown/expressions/closureInDoWhile1.kt b/idea/testData/codeInsight/moveUpDown/expressions/closureInDoWhile1.kt new file mode 100644 index 00000000000..6be71feebc9 --- /dev/null +++ b/idea/testData/codeInsight/moveUpDown/expressions/closureInDoWhile1.kt @@ -0,0 +1,8 @@ +// MOVE: down +fun foo(i: Int) { + do { + println(i) + run { + } + } while (i in run { 1..2 }) +} \ No newline at end of file diff --git a/idea/testData/codeInsight/moveUpDown/expressions/closureInDoWhile1.kt.after b/idea/testData/codeInsight/moveUpDown/expressions/closureInDoWhile1.kt.after new file mode 100644 index 00000000000..264ae2ffccc --- /dev/null +++ b/idea/testData/codeInsight/moveUpDown/expressions/closureInDoWhile1.kt.after @@ -0,0 +1,8 @@ +// MOVE: down +fun foo(i: Int) { + do { + println(i) + } while (i in run { 1..2 }) + run { + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/moveUpDown/expressions/closureInDoWhile2.kt b/idea/testData/codeInsight/moveUpDown/expressions/closureInDoWhile2.kt new file mode 100644 index 00000000000..205672e74e1 --- /dev/null +++ b/idea/testData/codeInsight/moveUpDown/expressions/closureInDoWhile2.kt @@ -0,0 +1,8 @@ +// MOVE: up +fun foo(i: Int) { + do { + println(i) + } while (i in run { 1..2 }) + run { + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/moveUpDown/expressions/closureInDoWhile2.kt.after b/idea/testData/codeInsight/moveUpDown/expressions/closureInDoWhile2.kt.after new file mode 100644 index 00000000000..93ef156659a --- /dev/null +++ b/idea/testData/codeInsight/moveUpDown/expressions/closureInDoWhile2.kt.after @@ -0,0 +1,8 @@ +// MOVE: up +fun foo(i: Int) { + do { + println(i) + run { + } + } while (i in run { 1..2 }) +} \ No newline at end of file diff --git a/idea/testData/codeInsight/moveUpDown/expressions/closureInFor1.kt b/idea/testData/codeInsight/moveUpDown/expressions/closureInFor1.kt new file mode 100644 index 00000000000..a83aaadfe3b --- /dev/null +++ b/idea/testData/codeInsight/moveUpDown/expressions/closureInFor1.kt @@ -0,0 +1,7 @@ +// MOVE: down +fun foo() { + run { + } + for (i in run { 1..2 }) { + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/moveUpDown/expressions/closureInFor1.kt.after b/idea/testData/codeInsight/moveUpDown/expressions/closureInFor1.kt.after new file mode 100644 index 00000000000..ee92e89d50b --- /dev/null +++ b/idea/testData/codeInsight/moveUpDown/expressions/closureInFor1.kt.after @@ -0,0 +1,7 @@ +// MOVE: down +fun foo() { + for (i in run { 1..2 }) { + run { + } + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/moveUpDown/expressions/closureInFor2.kt b/idea/testData/codeInsight/moveUpDown/expressions/closureInFor2.kt new file mode 100644 index 00000000000..a5f140d5191 --- /dev/null +++ b/idea/testData/codeInsight/moveUpDown/expressions/closureInFor2.kt @@ -0,0 +1,7 @@ +// MOVE: up +fun foo() { + for (i in run { 1..2 }) { + run { + } + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/moveUpDown/expressions/closureInFor2.kt.after b/idea/testData/codeInsight/moveUpDown/expressions/closureInFor2.kt.after new file mode 100644 index 00000000000..523e6803e76 --- /dev/null +++ b/idea/testData/codeInsight/moveUpDown/expressions/closureInFor2.kt.after @@ -0,0 +1,7 @@ +// MOVE: up +fun foo() { + run { + } + for (i in run { 1..2 }) { + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/moveUpDown/expressions/closureInIf1.kt b/idea/testData/codeInsight/moveUpDown/expressions/closureInIf1.kt new file mode 100644 index 00000000000..e239ea463e1 --- /dev/null +++ b/idea/testData/codeInsight/moveUpDown/expressions/closureInIf1.kt @@ -0,0 +1,7 @@ +// MOVE: down +fun foo(i: Int) { + run { + } + if (i in run { 1..2 }) { + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/moveUpDown/expressions/closureInIf1.kt.after b/idea/testData/codeInsight/moveUpDown/expressions/closureInIf1.kt.after new file mode 100644 index 00000000000..67cccf2c4b9 --- /dev/null +++ b/idea/testData/codeInsight/moveUpDown/expressions/closureInIf1.kt.after @@ -0,0 +1,7 @@ +// MOVE: down +fun foo(i: Int) { + if (i in run { 1..2 }) { + run { + } + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/moveUpDown/expressions/closureInIf2.kt b/idea/testData/codeInsight/moveUpDown/expressions/closureInIf2.kt new file mode 100644 index 00000000000..9a4edcd4190 --- /dev/null +++ b/idea/testData/codeInsight/moveUpDown/expressions/closureInIf2.kt @@ -0,0 +1,7 @@ +// MOVE: up +fun foo(i: Int) { + if (i in run { 1..2 }) { + run { + } + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/moveUpDown/expressions/closureInIf2.kt.after b/idea/testData/codeInsight/moveUpDown/expressions/closureInIf2.kt.after new file mode 100644 index 00000000000..dae5857c1c4 --- /dev/null +++ b/idea/testData/codeInsight/moveUpDown/expressions/closureInIf2.kt.after @@ -0,0 +1,7 @@ +// MOVE: up +fun foo(i: Int) { + run { + } + if (i in run { 1..2 }) { + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/moveUpDown/expressions/closureInWhile1.kt b/idea/testData/codeInsight/moveUpDown/expressions/closureInWhile1.kt new file mode 100644 index 00000000000..c17d44fb62a --- /dev/null +++ b/idea/testData/codeInsight/moveUpDown/expressions/closureInWhile1.kt @@ -0,0 +1,8 @@ +// MOVE: down +fun foo(i: Int) { + run { + } + while (i in run { 1..2 }) { + println(i) + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/moveUpDown/expressions/closureInWhile1.kt.after b/idea/testData/codeInsight/moveUpDown/expressions/closureInWhile1.kt.after new file mode 100644 index 00000000000..ff095512df8 --- /dev/null +++ b/idea/testData/codeInsight/moveUpDown/expressions/closureInWhile1.kt.after @@ -0,0 +1,8 @@ +// MOVE: down +fun foo(i: Int) { + while (i in run { 1..2 }) { + run { + } + println(i) + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/moveUpDown/expressions/closureInWhile2.kt b/idea/testData/codeInsight/moveUpDown/expressions/closureInWhile2.kt new file mode 100644 index 00000000000..1d6c5219f2e --- /dev/null +++ b/idea/testData/codeInsight/moveUpDown/expressions/closureInWhile2.kt @@ -0,0 +1,8 @@ +// MOVE: up +fun foo(i: Int) { + while (i in run { 1..2 }) { + run { + } + println(i) + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/moveUpDown/expressions/closureInWhile2.kt.after b/idea/testData/codeInsight/moveUpDown/expressions/closureInWhile2.kt.after new file mode 100644 index 00000000000..d284ce877d3 --- /dev/null +++ b/idea/testData/codeInsight/moveUpDown/expressions/closureInWhile2.kt.after @@ -0,0 +1,8 @@ +// MOVE: up +fun foo(i: Int) { + run { + } + while (i in run { 1..2 }) { + println(i) + } +} \ 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 ecd5afbec5c..6979a50b0b2 100644 --- a/idea/tests/org/jetbrains/jet/plugin/codeInsight/moveUpDown/CodeMoverTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/codeInsight/moveUpDown/CodeMoverTestGenerated.java @@ -777,6 +777,46 @@ public class CodeMoverTestGenerated extends AbstractCodeMoverTest { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/codeInsight/moveUpDown/expressions"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("closureInDoWhile1.kt") + public void testClosureInDoWhile1() throws Exception { + doTestExpression("idea/testData/codeInsight/moveUpDown/expressions/closureInDoWhile1.kt"); + } + + @TestMetadata("closureInDoWhile2.kt") + public void testClosureInDoWhile2() throws Exception { + doTestExpression("idea/testData/codeInsight/moveUpDown/expressions/closureInDoWhile2.kt"); + } + + @TestMetadata("closureInFor1.kt") + public void testClosureInFor1() throws Exception { + doTestExpression("idea/testData/codeInsight/moveUpDown/expressions/closureInFor1.kt"); + } + + @TestMetadata("closureInFor2.kt") + public void testClosureInFor2() throws Exception { + doTestExpression("idea/testData/codeInsight/moveUpDown/expressions/closureInFor2.kt"); + } + + @TestMetadata("closureInIf1.kt") + public void testClosureInIf1() throws Exception { + doTestExpression("idea/testData/codeInsight/moveUpDown/expressions/closureInIf1.kt"); + } + + @TestMetadata("closureInIf2.kt") + public void testClosureInIf2() throws Exception { + doTestExpression("idea/testData/codeInsight/moveUpDown/expressions/closureInIf2.kt"); + } + + @TestMetadata("closureInWhile1.kt") + public void testClosureInWhile1() throws Exception { + doTestExpression("idea/testData/codeInsight/moveUpDown/expressions/closureInWhile1.kt"); + } + + @TestMetadata("closureInWhile2.kt") + public void testClosureInWhile2() throws Exception { + doTestExpression("idea/testData/codeInsight/moveUpDown/expressions/closureInWhile2.kt"); + } + @TestMetadata("declaration1.kt") public void testDeclaration1() throws Exception { doTestExpression("idea/testData/codeInsight/moveUpDown/expressions/declaration1.kt");