[java-completion] MissingLoopBodyFixer: wrap body only when it's indented

Fixes IDEA-294142 Complete Current Statement action can affect the next independent statement

GitOrigin-RevId: cf6c81b5b62997a8925c2d68bf14533abb135d2c
This commit is contained in:
Tagir Valeev
2022-05-17 09:21:23 +02:00
committed by intellij-monorepo-bot
parent 56a60c2688
commit c1d6bd977f
4 changed files with 57 additions and 24 deletions

View File

@@ -20,6 +20,9 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.ObjectUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class MissingLoopBodyFixer implements Fixer {
@Override
@@ -29,7 +32,7 @@ public class MissingLoopBodyFixer implements Fixer {
final Document doc = editor.getDocument();
PsiElement body = loopStatement.getBody();
PsiStatement body = loopStatement.getBody();
if (body instanceof PsiBlockStatement) return;
if (body != null && startLine(doc, body) == startLine(doc, loopStatement)) return;
@@ -94,31 +97,46 @@ public class MissingLoopBodyFixer implements Fixer {
return doc.getLineNumber(psiElement.getTextRange().getStartOffset());
}
static void fixLoopBody(Editor editor,
JavaSmartEnterProcessor processor,
PsiLoopStatement loop,
Document doc,
PsiElement body,
PsiElement eltToInsertAfter) {
static void fixLoopBody(@NotNull Editor editor,
@NotNull JavaSmartEnterProcessor processor,
@NotNull PsiLoopStatement loop,
@NotNull Document doc,
@Nullable PsiStatement body,
@Nullable PsiElement eltToInsertAfter) {
if (body != null && eltToInsertAfter != null) {
int endOffset = body.getTextRange().getEndOffset();
doc.insertString(endOffset, "\n}");
int offset = eltToInsertAfter.getTextRange().getEndOffset();
doc.insertString(offset, "{");
editor.getCaretModel().moveToOffset(endOffset + "{".length());
processor.setSkipEnter(true);
processor.reformat(loop);
}
else {
String prefix = "{}";
String text = prefix;
if (eltToInsertAfter == null) {
eltToInsertAfter = loop;
text = ")" + text;
if (bodyIsIndented(loop, body)) {
int endOffset = body.getTextRange().getEndOffset();
doc.insertString(endOffset, "\n}");
int offset = eltToInsertAfter.getTextRange().getEndOffset();
doc.insertString(offset, "{");
editor.getCaretModel().moveToOffset(endOffset + "{".length());
processor.setSkipEnter(true);
processor.reformat(loop);
return;
}
int offset = eltToInsertAfter.getTextRange().getEndOffset();
doc.insertString(offset, text);
editor.getCaretModel().moveToOffset(offset + text.length() - prefix.length());
}
String prefix = "{}";
String text = prefix;
if (eltToInsertAfter == null) {
eltToInsertAfter = loop;
text = ")" + text;
}
int offset = eltToInsertAfter.getTextRange().getEndOffset();
doc.insertString(offset, text);
editor.getCaretModel().moveToOffset(offset + text.length() - prefix.length());
}
private static boolean bodyIsIndented(@NotNull PsiLoopStatement loop, @NotNull PsiElement body) {
PsiWhiteSpace beforeBody = ObjectUtils.tryCast(body.getPrevSibling(), PsiWhiteSpace.class);
if (beforeBody == null) return false;
PsiWhiteSpace beforeLoop = ObjectUtils.tryCast(loop.getPrevSibling(), PsiWhiteSpace.class);
if (beforeLoop == null) return false;
String beforeBodyText = beforeBody.getText();
String beforeLoopText = beforeLoop.getText();
int beforeBodyLineBreak = beforeBodyText.lastIndexOf('\n');
if (beforeBodyLineBreak == -1) return false;
int beforeLoopLineBreak = beforeLoopText.lastIndexOf('\n');
if (beforeLoopLineBreak == -1) return false;
return beforeBodyText.length() - beforeBodyLineBreak > beforeLoopText.length() - beforeLoopLineBreak;
}
}

View File

@@ -0,0 +1,6 @@
class X {{
int[] a = new int[3];
long res = 0;
for (int val : a)<caret>
System.out.println(res);
}}

View File

@@ -0,0 +1,8 @@
class X {{
int[] a = new int[3];
long res = 0;
for (int val : a) {
<caret>
}
System.out.println(res);
}}

View File

@@ -77,6 +77,7 @@ public class CompleteStatementTest extends EditorActionTestCase {
public void testBeforeFor() { doTest(); }
public void testForSingleStatementInBody() { doTest(); }
public void testForEachSingleStatementInBody() { doTest(); }
public void testForEachNextStatementNotIndented() { doTest(); }
public void testAtBlockEnd() { doTest(); }
public void testForceBlock() { doTest(); }
public void testElseIf() { doTest(); }