surround with try-catch: expand expression lambda to perform operation (IDEA-134500)

This commit is contained in:
Anna Kozlova
2015-03-26 12:07:12 +01:00
parent 282d32939e
commit 2e736c18fe
6 changed files with 70 additions and 25 deletions
@@ -28,6 +28,7 @@ import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.util.RefactoringChangeUtil;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
@@ -38,14 +39,16 @@ import org.jetbrains.annotations.NotNull;
public class SurroundWithTryCatchFix implements IntentionAction {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.quickfix.SurroundWithTryCatchFix");
private PsiStatement myStatement = null;
private PsiElement myStatement = null;
public SurroundWithTryCatchFix(@NotNull PsiElement element) {
final PsiFunctionalExpression functionalExpression = PsiTreeUtil.getParentOfType(element, PsiFunctionalExpression.class, false);
if (functionalExpression == null ||
(functionalExpression instanceof PsiLambdaExpression && ((PsiLambdaExpression)functionalExpression).getBody() instanceof PsiCodeBlock)) {
final PsiFunctionalExpression functionalExpression = PsiTreeUtil.getParentOfType(element, PsiFunctionalExpression.class, false, PsiStatement.class);
if (functionalExpression == null) {
myStatement = PsiTreeUtil.getNonStrictParentOfType(element, PsiStatement.class);
}
else if (functionalExpression instanceof PsiLambdaExpression) {
myStatement = functionalExpression;
}
}
@Override
@@ -82,6 +85,20 @@ public class SurroundWithTryCatchFix implements IntentionAction {
myStatement = forStatement;
}
}
if (myStatement instanceof PsiLambdaExpression) {
PsiElement body = ((PsiLambdaExpression)myStatement).getBody();
if (body instanceof PsiExpression) {
myStatement = RefactoringUtil.expandExpressionLambdaToCodeBlock(body);
}
body = ((PsiLambdaExpression)myStatement).getBody();
LOG.assertTrue(body instanceof PsiCodeBlock);
final PsiStatement[] statements = ((PsiCodeBlock)body).getStatements();
LOG.assertTrue(statements.length == 1);
myStatement = statements[0];
}
TextRange range = null;
try{
@@ -56,6 +56,7 @@ import com.intellij.refactoring.introduceVariable.IntroduceVariableBase;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.HashSet;
import com.siyeh.ipp.types.ExpandOneLineLambda2CodeBlockIntention;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -936,6 +937,21 @@ public class RefactoringUtil {
return element instanceof PsiLoopStatement || element instanceof PsiIfStatement;
}
public static PsiElement expandExpressionLambdaToCodeBlock(@NotNull PsiElement element) {
final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(element, PsiLambdaExpression.class);
LOG.assertTrue(lambdaExpression != null);
final PsiElement body = lambdaExpression.getBody();
LOG.assertTrue(body instanceof PsiExpression);
String blockText = "{";
blockText += PsiType.VOID.equals(LambdaUtil.getFunctionalInterfaceReturnType(lambdaExpression)) ? "" : "return ";
blockText += body.getText() + ";}";
final String resultedLambdaText = lambdaExpression.getParameterList().getText() + "->" + blockText;
final PsiExpression expressionFromText =
JavaPsiFacade.getElementFactory(element.getProject()).createExpressionFromText(resultedLambdaText, lambdaExpression);
return CodeStyleManager.getInstance(element.getProject()).reformat(lambdaExpression.replace(expressionFromText));
}
public interface ImplicitConstructorUsageVisitor {
void visitConstructor(PsiMethod constructor, PsiMethod baseConstructor);
@@ -0,0 +1,26 @@
// "Surround with try/catch" "true"
public class ExTest {
public static void maybeThrow(String data) throws Ex {
throw new Ex(data);
}
{
Block<String> b = (t) -> {
try {
ExTest.maybeThrow(t);
} catch (Ex ex) {
ex.printStackTrace();
}
};
}
private static class Ex extends Throwable {
public Ex(String s) {
}
}
}
interface Block<T> {
public void accept(T t);
}
@@ -1,4 +1,4 @@
// "Surround with try/catch" "false"
// "Surround with try/catch" "true"
public class ExTest {
public static void maybeThrow(String data) throws Ex {
throw new Ex(data);
@@ -50,12 +50,10 @@ public class ReplaceConditionalWithIfIntention extends Intention {
private static void replaceConditionalWithIf(PsiConditionalExpression expression) throws IncorrectOperationException {
final PsiElement expressionParent = expression.getParent();
if (expressionParent instanceof PsiLambdaExpression) {
String blockText = "{";
blockText += PsiType.VOID.equals(LambdaUtil.getFunctionalInterfaceReturnType((PsiLambdaExpression)expressionParent)) ? "" : "return ";
blockText += expression.getText() + ";}";
final PsiCodeBlock codeBlock = (PsiCodeBlock)expression.replace(
JavaPsiFacade.getElementFactory(expression.getProject()).createCodeBlockFromText(blockText, expression));
final PsiStatement statement = codeBlock.getStatements()[0];
final PsiElement codeBlock =
((PsiLambdaExpression)RefactoringUtil.expandExpressionLambdaToCodeBlock(expression)).getBody();
LOG.assertTrue(codeBlock instanceof PsiCodeBlock, codeBlock);
final PsiStatement statement = ((PsiCodeBlock)codeBlock).getStatements()[0];
expression = (PsiConditionalExpression)(statement instanceof PsiReturnStatement ? ((PsiReturnStatement)statement).getReturnValue()
: ((PsiExpressionStatement)statement).getExpression());
}
@@ -17,8 +17,8 @@ package com.siyeh.ipp.types;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
@@ -40,21 +40,9 @@ public class ExpandOneLineLambda2CodeBlockIntention extends Intention {
@Override
protected void processIntention(@NotNull PsiElement element) throws IncorrectOperationException {
final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(element, PsiLambdaExpression.class);
LOG.assertTrue(lambdaExpression != null);
final PsiElement body = lambdaExpression.getBody();
LOG.assertTrue(body instanceof PsiExpression);
String blockText = "{";
blockText += PsiType.VOID.equals(LambdaUtil.getFunctionalInterfaceReturnType(lambdaExpression)) ? "" : "return ";
blockText += body.getText() + ";}";
final String resultedLambdaText = lambdaExpression.getParameterList().getText() + "->" + blockText;
final PsiExpression expressionFromText =
JavaPsiFacade.getElementFactory(element.getProject()).createExpressionFromText(resultedLambdaText, lambdaExpression);
CodeStyleManager.getInstance(element.getProject()).reformat(lambdaExpression.replace(expressionFromText));
RefactoringUtil.expandExpressionLambdaToCodeBlock(element);
}
private static class LambdaExpressionPredicate implements PsiElementPredicate {
@Override