diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java index 48b6ade974af..d55e80c94b49 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java @@ -61,6 +61,7 @@ import com.intellij.util.IncorrectOperationException; import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; +import com.siyeh.ig.psiutils.VariableAccessUtils; import com.siyeh.ipp.psiutils.ErrorUtil; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NonNls; @@ -610,6 +611,16 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase { return false; } + for (PsiPatternVariable variable : JavaPsiPatternUtil.getExposedPatternVariables(expr)) { + if (VariableAccessUtils.getVariableReferences(variable, variable.getDeclarationScope()).stream() + .anyMatch(ref -> !PsiTreeUtil.isAncestor(expr, ref, true))) { + String message = RefactoringBundle.getCannotRefactorMessage( + RefactoringBundle.message("selected.expression.introduces.pattern.variable", variable.getName())); + showErrorMessage(project, editor, message); + return false; + } + } + final PsiElement physicalElement = expr.getUserData(ElementToWorkOn.PARENT); diff --git a/java/java-tests/testData/refactoring/introduceVariable/PatternVariableNotUsedAfterwards.after.java b/java/java-tests/testData/refactoring/introduceVariable/PatternVariableNotUsedAfterwards.after.java new file mode 100644 index 000000000000..044082eff97b --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/PatternVariableNotUsedAfterwards.after.java @@ -0,0 +1,8 @@ +class A { + void test(Object obj) { + boolean temp = obj instanceof String s && s.trim().isEmpty(); + if (temp) { + System.out.println("Found"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/introduceVariable/PatternVariableNotUsedAfterwards.java b/java/java-tests/testData/refactoring/introduceVariable/PatternVariableNotUsedAfterwards.java new file mode 100644 index 000000000000..6d4358a3c289 --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/PatternVariableNotUsedAfterwards.java @@ -0,0 +1,7 @@ +class A { + void test(Object obj) { + if (obj instanceof String s && s.trim().isEmpty()) { + System.out.println("Found"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/introduceVariable/PatternVariableUsedAfterwards.java b/java/java-tests/testData/refactoring/introduceVariable/PatternVariableUsedAfterwards.java new file mode 100644 index 000000000000..7e84efd9e502 --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/PatternVariableUsedAfterwards.java @@ -0,0 +1,7 @@ +class A { + void test(Object obj) { + if (obj instanceof String s && s.trim().isEmpty()) { + System.out.println(s.length()); + } + } +} \ No newline at end of file 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 9a61db917741..de52cf999fa7 100644 --- a/java/java-tests/testSrc/com/intellij/java/refactoring/IntroduceVariableTest.java +++ b/java/java-tests/testSrc/com/intellij/java/refactoring/IntroduceVariableTest.java @@ -113,7 +113,21 @@ public class IntroduceVariableTest extends LightJavaCodeInsightTestCase { } fail("Should not be able to perform refactoring"); } - + + public void testPatternVariableUsedAfterwards() { + try { + doTest("temp", true, false, false, ""); + } + catch (RuntimeException e) { + assertEquals("Error message:Cannot perform refactoring.\nSelected expression introduces pattern variable 's'", e.getMessage()); + return; + } + fail("Should not be able to perform refactoring"); + } + public void testPatternVariableNotUsedAfterwards() { + doTest("temp", true, false, false, "boolean"); + } + public void testTernaryBothBranches() { doTest("temp", true, false, false, "int"); } public void testIfConditionAndChain() { doTest("temp", true, false, false, CommonClassNames.JAVA_LANG_STRING); } public void testReturnAndChain() { doTest("temp", true, false, false, CommonClassNames.JAVA_LANG_STRING); } diff --git a/platform/platform-resources-en/src/messages/RefactoringBundle.properties b/platform/platform-resources-en/src/messages/RefactoringBundle.properties index 11f82e6be58b..815f986f7c9a 100644 --- a/platform/platform-resources-en/src/messages/RefactoringBundle.properties +++ b/platform/platform-resources-en/src/messages/RefactoringBundle.properties @@ -200,6 +200,7 @@ selected.block.should.represent.an.expression=Selected block should represent an is.not.supported.in.the.current.context={0} is not supported in current context type.of.the.selected.expression.cannot.be.determined=Type of selected expression cannot be determined. selected.expression.has.void.type=Selected expression has void type. +selected.expression.introduces.pattern.variable=Selected expression introduces pattern variable ''{0}'' to.rename=to rename to.delete.with.usage.search=to delete (with usage search) unknown.expression.type=Unknown expression type.