[java] NestedIfJoinLinesHandler: correct if body indent (IDEA-196385)

GitOrigin-RevId: 3b0cd48480f8f647c1e7f7dca33fb8bf961b58c5
This commit is contained in:
Tagir Valeev
2021-02-01 10:46:44 +00:00
committed by intellij-monorepo-bot
parent cdc59be4d7
commit ad99d7cd91
5 changed files with 62 additions and 7 deletions
@@ -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;
* }
* }</pre>
*/
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() +
@@ -0,0 +1,13 @@
class Foo {
void test(int a, int b) {
<caret> 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");
}
}
}
}
@@ -0,0 +1,11 @@
class Foo {
void test(int a, int b) {
if (a > 0 &<caret>& b > 0) {
System.out.println("A");
System.out.println("B");
System.out.println("C");
System.out.println("Deeper");
System.out.println("Wrong indent");
}
}
}
@@ -1,7 +1,7 @@
class Foo {
void test(int a, int b) {
if(a > 0 &<caret>& b < 0) {
System.out.println(a+b);
}
System.out.println(a+b);
}
}
}
@@ -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(); }