[java-analysis] CodeBlockSurrounder: workaround google-java-format problem (IDEA-340109)

(cherry picked from commit ff8a2a9d628140942ccb11d84c4aa4c2ced2df47)

IJ-CR-147066

GitOrigin-RevId: 404efbcd84a9c45c34ed0039559de2c8d111a19e
This commit is contained in:
Tagir Valeev
2024-10-17 11:01:56 +02:00
committed by intellij-monorepo-bot
parent a03d329be5
commit c49291c780

View File

@@ -41,8 +41,8 @@ import static com.intellij.util.ObjectUtils.tryCast;
* <li>Inside the read action call {@link #forExpression(PsiExpression)} passing the expression you want to process.</li>
* <li>If it returns null, then there's no suitable code block and it cannot be added due to complex control-flow, language limitations, etc.</li>
* <li>Otherwise create a write action and call the {@link #surround()}. It's guaranteed to be successful.</li>
* <li>Use {@link SurroundResult#getAnchor()} to insert new statement before it. Use {@link SurroundResult#getExpression()} to find the
* copy of original expression that appears in the resulting code. Note that the original expression itself may become invalid after
* <li>Use {@link SurroundResult#getAnchor()} to insert new statement before it. Use {@link SurroundResult#getExpression()} to find the
* copy of original expression that appears in the resulting code. Note that the original expression itself may become invalid after
* the {@link #surround()} call.</li>
* </ol>
* Note that {@link #forExpression(PsiExpression)} and {@link #surround()} should be called within the same read action.
@@ -50,7 +50,7 @@ import static com.intellij.util.ObjectUtils.tryCast;
public abstract class CodeBlockSurrounder {
private enum ParentContext {
/**
* The execution will terminate abruptly returning/throwing this expression as a result
* The execution will terminate abruptly returning/throwing this expression as a result
* (return/yield/throw statement)
*/
RETURN,
@@ -148,7 +148,7 @@ public abstract class CodeBlockSurrounder {
// operand should be kept. If the subsequent conditions in else branches are mutually exclusive with this one,
// then it's still safe to split.
// TODO: support splitting at other operand, not only at 0
if (!(PsiUtil.skipParenthesizedExprDown(myExpression) instanceof PsiPolyadicExpression polyadic) ||
if (!(PsiUtil.skipParenthesizedExprDown(myExpression) instanceof PsiPolyadicExpression polyadic) ||
!polyadic.getOperationTokenType().equals(JavaTokenType.ANDAND)) {
return ParentContext.UNKNOWN;
}
@@ -232,10 +232,10 @@ public abstract class CodeBlockSurrounder {
/**
* Creates a surrounder for given expression.
*
*
* @param expression an expression to surround.
* @return a new surrounder that is definitely capable to produce a code block around given expression
* where it's safe to place new statements. Returns null if it's impossible to surround given expression
* @return a new surrounder that is definitely capable to produce a code block around given expression
* where it's safe to place new statements. Returns null if it's impossible to surround given expression
* with a code block.
*/
public static @Nullable CodeBlockSurrounder forExpression(@NotNull PsiExpression expression) {
@@ -304,7 +304,7 @@ public abstract class CodeBlockSurrounder {
PsiElement declParent = decl.getParent();
if (declParent instanceof PsiForStatement forStatement && forStatement.getInitialization() == decl) {
if (hasNameCollision(decl, declParent.getParent())) {
// There's another var with the same name as one declared in for initialization
// There's another var with the same name as one declared in for initialization
return new SimpleSurrounder(expression, forStatement);
}
return forStatement((PsiStatement)declParent, expression);
@@ -317,7 +317,7 @@ public abstract class CodeBlockSurrounder {
PsiResourceList list = tryCast(parent.getParent(), PsiResourceList.class);
if (list != null && list.getParent() instanceof PsiTryStatement tryStatement) {
Iterator<PsiResourceListElement> iterator = list.iterator();
if (iterator.hasNext() && iterator.next() == parent && tryStatement.getCatchBlocks().length == 0
if (iterator.hasNext() && iterator.next() == parent && tryStatement.getCatchBlocks().length == 0
&& tryStatement.getFinallyBlock() == null) {
return forStatement(tryStatement, expression);
}
@@ -880,8 +880,14 @@ public abstract class CodeBlockSurrounder {
PsiStatement thenBranch = Objects.requireNonNull(outerIf.getThenBranch());
Objects.requireNonNull(((PsiIfStatement)newThenBranch.getCodeBlock().getStatements()[0]).getThenBranch()).replace(thenBranch);
newThenBranch = (PsiBlockStatement)thenBranch.replace(newThenBranch);
// The google-java-format plugin breaks the reformat() contract and returns a wrong element (not the one supplied but its child)
// The exact reason is unclear.
// See https://youtrack.jetbrains.com/issue/IDEA-340109 and https://github.com/google/google-java-format/issues/1101
// A workaround is applied here to find a parent element to avoid exception
PsiIfStatement innerIf =
(PsiIfStatement)CodeStyleManager.getInstance(project).reformat(newThenBranch.getCodeBlock().getStatements()[0]);
Objects.requireNonNull(PsiTreeUtil.getNonStrictParentOfType(
CodeStyleManager.getInstance(project).reformat(newThenBranch.getCodeBlock().getStatements()[0]),
PsiIfStatement.class));
Objects.requireNonNull(innerIf.getCondition()).replace(rOperands);
andChain.replace(lOperands);
return innerIf;