ExpressionUtils#getTopLevelExpression; used in SurroundWithTryCatchFix

Fixes EA-131551 - NPE: EnsureCodeBlockImpl.splitIf
We need to avoid custom logic for processing && chains, etc. in RefactoringUtil#ensureCodeBlock.
This commit is contained in:
Tagir Valeev
2018-11-07 10:43:54 +07:00
parent 6caca4382a
commit 2c7124b0b0
4 changed files with 45 additions and 2 deletions

View File

@@ -28,6 +28,7 @@ import com.intellij.psi.*;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.ig.psiutils.ControlFlowUtils;
import com.siyeh.ig.psiutils.ExpressionUtils;
import org.jetbrains.annotations.NotNull;
/**
@@ -43,7 +44,7 @@ public class SurroundWithTryCatchFix implements IntentionAction {
element instanceof PsiResourceVariable ||
(element instanceof PsiExpression &&
!(element instanceof PsiMethodReferenceExpression) &&
ControlFlowUtils.canExtractStatement((PsiExpression)element, false))) {
ControlFlowUtils.canExtractStatement(ExpressionUtils.getTopLevelExpression((PsiExpression)element)))) {
myElement = element;
}
}
@@ -78,7 +79,7 @@ public class SurroundWithTryCatchFix implements IntentionAction {
editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(0, 0));
if (myElement instanceof PsiExpression) {
myElement = RefactoringUtil.ensureCodeBlock((PsiExpression)myElement);
myElement = RefactoringUtil.ensureCodeBlock(ExpressionUtils.getTopLevelExpression((PsiExpression)myElement));
}
myElement = RefactoringUtil.getParentStatement(myElement, false);
if (myElement == null) return;

View File

@@ -0,0 +1,13 @@
// "Surround with try/catch" "true"
class C {
native boolean foo() throws Exception;
void test() {
try {
if(foo() && foo())
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,9 @@
// "Surround with try/catch" "true"
class C {
native boolean foo() throws Exception;
void test() {
if(foo() && f<caret>oo())
}
}

View File

@@ -1394,4 +1394,24 @@ public class ExpressionUtils {
public static boolean isArrayCreationExpression(@NotNull PsiNewExpression expression) {
return expression.getArrayInitializer() != null || expression.getArrayDimensions().length > 0;
}
/**
* Returns ancestor expression for given subexpression which parent is not an expression anymore (except lambda)
*
* @param expression an expression to find its ancestor
* @return a top-level expression for given expression (may return an expression itself)
*/
@NotNull
public static PsiExpression getTopLevelExpression(@NotNull PsiExpression expression) {
while(true) {
PsiElement parent = expression.getParent();
if (parent instanceof PsiExpression && !(parent instanceof PsiLambdaExpression)) {
expression = (PsiExpression)parent;
} else if (parent instanceof PsiExpressionList && parent.getParent() instanceof PsiExpression) {
expression = (PsiExpression)parent.getParent();
} else {
return expression;
}
}
}
}