diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/NestedIfJoinLinesHandler.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/NestedIfJoinLinesHandler.java index 729de70c3e2a..b9b9d1e9459d 100644 --- a/java/java-impl/src/com/intellij/codeInsight/editorActions/NestedIfJoinLinesHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/NestedIfJoinLinesHandler.java @@ -6,6 +6,7 @@ import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.siyeh.ig.psiutils.ControlFlowUtils; import com.siyeh.ig.psiutils.ParenthesesUtils; +import one.util.streamex.StreamEx; import org.jetbrains.annotations.NotNull; import java.util.Objects; @@ -25,10 +26,16 @@ import static com.intellij.util.ObjectUtils.tryCast; * } * } */ -public class NestedIfJoinLinesHandler implements JoinLinesHandlerDelegate { +public class NestedIfJoinLinesHandler implements JoinRawLinesHandlerDelegate { @Override - public int tryJoinLines(@NotNull final Document document, @NotNull final PsiFile psiFile, final int start, final int end) { - PsiJavaToken elementAtStartLineEnd = tryCast(psiFile.findElementAt(start), PsiJavaToken.class); + public int tryJoinLines(@NotNull Document document, @NotNull PsiFile file, int start, int end) { + return CANNOT_JOIN; + } + + @Override + public int tryJoinRawLines(@NotNull Document document, @NotNull PsiFile psiFile, int start, int end) { + if (start == 0) return CANNOT_JOIN; + PsiJavaToken elementAtStartLineEnd = tryCast(psiFile.findElementAt(start-1), PsiJavaToken.class); PsiElement nextLineElement = psiFile.findElementAt(end); if (elementAtStartLineEnd == null || nextLineElement == null) return CANNOT_JOIN; PsiIfStatement outerIf = null; @@ -57,13 +64,37 @@ public class NestedIfJoinLinesHandler implements JoinLinesHandlerDelegate { PsiJavaToken rParenth = innerIf.getRParenth(); if (lParenth == null || rParenth == null) return CANNOT_JOIN; + String outerPrefix = "", innerPrefix = ""; + int outerIfOffset = outerIf.getTextRange().getStartOffset(); + int innerIfOffset = innerIf.getTextRange().getStartOffset(); + int outerIfLine = document.getLineNumber(outerIfOffset); + int innerIfLine = document.getLineNumber(innerIfOffset); + if (innerIfLine > outerIfLine) { + int outerLineStart = document.getLineStartOffset(outerIfLine); + int innerLineStart = document.getLineStartOffset(innerIfLine); + CharSequence sequence = document.getCharsSequence(); + outerPrefix = sequence.subSequence(outerLineStart, outerIfOffset).toString(); + innerPrefix = sequence.subSequence(innerLineStart, innerIfOffset).toString(); + if (!innerPrefix.startsWith(outerPrefix) || !innerPrefix.isBlank()) { + outerPrefix = innerPrefix = ""; + } + } + String childConditionText = ParenthesesUtils.getText(innerCondition, ParenthesesUtils.OR_PRECEDENCE); String parentConditionText = ParenthesesUtils.getText(outerCondition, ParenthesesUtils.OR_PRECEDENCE); PsiElementFactory factory = JavaPsiFacade.getElementFactory(psiFile.getProject()); String condition = parentConditionText + " && " + childConditionText; + String innerIfBody = innerIf.getText().substring(rParenth.getTextRangeInParent().getStartOffset()); + if (!innerPrefix.isEmpty()) { + String finalInnerPrefix = innerPrefix; + String finalOuterPrefix = outerPrefix; + innerIfBody = StreamEx.split(innerIfBody, '\n', false) + .map(s -> s.startsWith(finalInnerPrefix) ? finalOuterPrefix + s.substring(finalInnerPrefix.length()) : s) + .joining("\n"); + } String resultText = outerIf.getText().substring(0, lParenth.getTextRangeInParent().getEndOffset()) - + condition + innerIf.getText().substring(rParenth.getTextRangeInParent().getStartOffset()); + + condition + innerIfBody; PsiStatement statement = factory.createStatementFromText(resultText, outerIf); PsiIfStatement result = (PsiIfStatement)outerIf.replace(statement); return Objects.requireNonNull(result.getCondition()).getTextRange().getStartOffset() + diff --git a/java/java-tests/testData/codeInsight/joinLines/IfChainCorrectIndent.java b/java/java-tests/testData/codeInsight/joinLines/IfChainCorrectIndent.java new file mode 100644 index 000000000000..4664fade1110 --- /dev/null +++ b/java/java-tests/testData/codeInsight/joinLines/IfChainCorrectIndent.java @@ -0,0 +1,13 @@ +class Foo { + void test(int a, int b) { + if (a > 0) { + if (b > 0) { + System.out.println("A"); + System.out.println("B"); + System.out.println("C"); + System.out.println("Deeper"); + System.out.println("Wrong indent"); + } + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/joinLines/IfChainCorrectIndent_after.java b/java/java-tests/testData/codeInsight/joinLines/IfChainCorrectIndent_after.java new file mode 100644 index 000000000000..3f6d80432114 --- /dev/null +++ b/java/java-tests/testData/codeInsight/joinLines/IfChainCorrectIndent_after.java @@ -0,0 +1,11 @@ +class Foo { + void test(int a, int b) { + if (a > 0 && b > 0) { + System.out.println("A"); + System.out.println("B"); + System.out.println("C"); + System.out.println("Deeper"); + System.out.println("Wrong indent"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/joinLines/IfChain_after.java b/java/java-tests/testData/codeInsight/joinLines/IfChain_after.java index 27fab520c448..e2cb1bf4a3ff 100644 --- a/java/java-tests/testData/codeInsight/joinLines/IfChain_after.java +++ b/java/java-tests/testData/codeInsight/joinLines/IfChain_after.java @@ -1,7 +1,7 @@ class Foo { void test(int a, int b) { if(a > 0 && b < 0) { - System.out.println(a+b); - } + System.out.println(a+b); + } } } \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/JoinLinesTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/JoinLinesTest.java index f3b432afa350..e2773ea07c6a 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/JoinLinesTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/JoinLinesTest.java @@ -22,7 +22,6 @@ import com.intellij.lang.java.JavaLanguage; import com.intellij.openapi.actionSystem.IdeActions; import com.intellij.openapi.editor.actionSystem.EditorActionHandler; import com.intellij.openapi.editor.actionSystem.EditorActionManager; -import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.testFramework.LightJavaCodeInsightTestCase; import org.jdom.Element; @@ -59,6 +58,7 @@ public class JoinLinesTest extends LightJavaCodeInsightTestCase { public void testAssignmentAndReassignmentWithCall() { doTest(); } public void testIfChain() { doTest(); } + public void testIfChainCorrectIndent() { doTest(); } public void testIfChainPolyadic() { doTest(); } public void testIfChainNoBraces() { doTest(); } public void testIfChainElse() { doTest(); }