From d75e2fb2d59d5590534affef85b2a3a8a2572870 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Sun, 18 Nov 2018 16:58:19 +0700 Subject: [PATCH] EnsureCodeBlock: support ternary in variable declaration (also fixes IDEA-202048) --- .../refactoring/util/EnsureCodeBlockImpl.java | 16 +++++++++++++++- .../introduceVariable/DeclareTernary.after.java | 13 +++++++++++++ .../introduceVariable/DeclareTernary.java | 6 ++++++ .../java/refactoring/IntroduceVariableTest.java | 4 ++++ .../com/siyeh/ig/psiutils/ControlFlowUtils.java | 3 +++ 5 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/refactoring/introduceVariable/DeclareTernary.after.java create mode 100644 java/java-tests/testData/refactoring/introduceVariable/DeclareTernary.java diff --git a/java/java-impl/src/com/intellij/refactoring/util/EnsureCodeBlockImpl.java b/java/java-impl/src/com/intellij/refactoring/util/EnsureCodeBlockImpl.java index ec1d26fbf413..51eb01211624 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/EnsureCodeBlockImpl.java +++ b/java/java-impl/src/com/intellij/refactoring/util/EnsureCodeBlockImpl.java @@ -3,6 +3,7 @@ package com.intellij.refactoring.util; import com.intellij.codeInsight.BlockUtils; import com.intellij.codeInsight.intention.impl.SplitConditionUtil; +import com.intellij.codeInsight.intention.impl.SplitDeclarationAction; import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; @@ -189,7 +190,20 @@ class EnsureCodeBlockImpl { return newParent; } private static PsiElement replaceTernaryWithIf(PsiStatement statement, PsiConditionalExpression ternary) { - PsiElementFactory factory = JavaPsiFacade.getElementFactory(statement.getProject()); + Project project = statement.getProject(); + PsiElementFactory factory = JavaPsiFacade.getElementFactory(project); + PsiElement parent = PsiUtil.skipParenthesizedExprUp(ternary.getParent()); + if (parent instanceof PsiLocalVariable) { + PsiLocalVariable variable = (PsiLocalVariable)parent; + variable.normalizeDeclaration(); + PsiDeclarationStatement declaration = (PsiDeclarationStatement)variable.getParent(); + PsiAssignmentExpression assignment = + SplitDeclarationAction.invokeOnDeclarationStatement(declaration, PsiManager.getInstance(project), project); + if (assignment != null) { + ternary = (PsiConditionalExpression)Objects.requireNonNull(PsiUtil.skipParenthesizedExprDown(assignment.getRExpression())); + statement = (PsiStatement)assignment.getParent(); + } + } PsiIfStatement ifStatement = (PsiIfStatement)factory.createStatementFromText("if(" + ternary.getCondition().getText() + ") {} else {}", statement); Object mark = new Object(); diff --git a/java/java-tests/testData/refactoring/introduceVariable/DeclareTernary.after.java b/java/java-tests/testData/refactoring/introduceVariable/DeclareTernary.after.java new file mode 100644 index 000000000000..a4db7c43f59a --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/DeclareTernary.after.java @@ -0,0 +1,13 @@ +class Test { + void test(String s) { + final String x; + if (s == null) { + x = ""; + } else { + String temp = s.trim(); + x = temp.substring(1); + } + final String y = x.replace("foo", "bar"); + System.out.println(x); + } +} diff --git a/java/java-tests/testData/refactoring/introduceVariable/DeclareTernary.java b/java/java-tests/testData/refactoring/introduceVariable/DeclareTernary.java new file mode 100644 index 000000000000..b93ea881b686 --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/DeclareTernary.java @@ -0,0 +1,6 @@ +class Test { + void test(String s) { + final String x = s == null ? "" : s.trim().substring(1), y = x.replace("foo", "bar"); + System.out.println(x); + } +} diff --git a/java/java-tests/testSrc/com/intellij/java/refactoring/IntroduceVariableTest.java b/java/java-tests/testSrc/com/intellij/java/refactoring/IntroduceVariableTest.java index a570b0200cce..f0fc48339c22 100644 --- a/java/java-tests/testSrc/com/intellij/java/refactoring/IntroduceVariableTest.java +++ b/java/java-tests/testSrc/com/intellij/java/refactoring/IntroduceVariableTest.java @@ -247,6 +247,10 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase { doTest(new MockIntroduceVariableHandler("temp", true, false, false, CommonClassNames.JAVA_LANG_STRING)); } + public void testDeclareTernary() { + doTest(new MockIntroduceVariableHandler("temp", true, false, false, CommonClassNames.JAVA_LANG_STRING)); + } + public void testLambdaAndChain() { doTest(new MockIntroduceVariableHandler("temp", true, false, false, CommonClassNames.JAVA_LANG_STRING)); } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ControlFlowUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ControlFlowUtils.java index 3d4440049a31..c2e7e13db47e 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ControlFlowUtils.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ControlFlowUtils.java @@ -930,6 +930,9 @@ public class ControlFlowUtils { if (parent instanceof PsiConditionalExpression && ((PsiConditionalExpression)parent).getCondition() != cur) { PsiElement ternaryParent = PsiUtil.skipParenthesizedExprUp(parent.getParent()); return ternaryParent instanceof PsiReturnStatement || + (ternaryParent instanceof PsiLocalVariable && + (!((PsiLocalVariable)ternaryParent).getTypeElement().isInferredType() || + PsiTypesUtil.isDenotableType(((PsiLocalVariable)ternaryParent).getType(), ternaryParent))) || (ternaryParent instanceof PsiAssignmentExpression && ternaryParent.getParent() instanceof PsiExpressionStatement && PsiUtil.skipParenthesizedExprDown(((PsiAssignmentExpression)ternaryParent).getRExpression()) == parent); }