[java-refactoring] Introduce variable: disable if pattern declared outside is used, and we cannot surround

Fixes IDEA-303133 Extract variable from expression should be disabled when it uses a pattern variable declared earlier

GitOrigin-RevId: 360e6eadd89a047e0699fa077e9a1417bfed4340
This commit is contained in:
Tagir Valeev
2022-10-10 11:51:11 +02:00
committed by intellij-monorepo-bot
parent 4038e6f185
commit 9ddaefc198
4 changed files with 33 additions and 3 deletions

View File

@@ -30,14 +30,16 @@ import com.intellij.psi.*;
import com.intellij.psi.impl.PsiDiamondTypeUtil;
import com.intellij.psi.impl.source.tree.java.ReplaceExpressionUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.refactoring.introduceField.ElementToWorkOn;
import com.intellij.util.ArrayUtil;
import com.intellij.util.CommonJavaRefactoringUtil;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.ig.psiutils.CodeBlockSurrounder;
import com.siyeh.ig.psiutils.CommentTracker;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.siyeh.ig.psiutils.VariableAccessUtils;
import com.siyeh.ipp.psiutils.ErrorUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
@@ -255,9 +257,20 @@ public class IntroduceVariableUtil {
if (needParenthesis != null && needParenthesis.booleanValue()) {
return JavaBundle.message("introduce.variable.change.semantics.warning");
}
if (expr instanceof PsiClassObjectAccessExpression && PsiUtil.hasErrorElementChild(expr)) {
if (expr instanceof PsiClassObjectAccessExpression && PsiUtilCore.hasErrorElementChild(expr)) {
return JavaRefactoringBundle.message("selected.block.should.represent.an.expression");
}
if (!CodeBlockSurrounder.canSurround(expr)) {
PsiExpression topLevelExpression = ExpressionUtils.getTopLevelExpression(expr);
if (topLevelExpression != expr) {
for (PsiVariable variable : VariableAccessUtils.collectUsedVariables(expr)) {
if (variable instanceof PsiPatternVariable && PsiTreeUtil.isAncestor(topLevelExpression, variable, true) &&
!PsiTreeUtil.isAncestor(expr, variable, true)) {
return JavaRefactoringBundle.message("introduce.variable.message.expression.refers.to.pattern.variable.declared.outside", variable.getName());
}
}
}
}
return null;
}

View File

@@ -0,0 +1,5 @@
public class PatternUsedInSubsequentConditionCannotExtract {
void x(Object o) {
if (o instanceof String s ? <selection>s.equals("")</selection> : false) {}
}
}

View File

@@ -414,6 +414,17 @@ public class IntroduceVariableTest extends LightJavaCodeInsightTestCase {
fail("Should not be able to perform refactoring");
}
public void testPatternUsedInSubsequentConditionCannotExtract() {
try {
doTest("input", false, false, false, "Object", false);
}
catch (Exception e) {
assertEquals("Error message:Cannot perform refactoring.\nThe expression refers to the pattern variable 's' declared outside", e.getMessage());
return;
}
fail("Should not be able to perform refactoring");
}
public void testOneLineLambdaVoidCompatible() {UiInterceptors.register(new ChooserInterceptor(null, Pattern.quote("Runnable: () -> {...}"))); doTest("c", false, false, false, JAVA_LANG_STRING); }
public void testOneLineLambdaValueCompatible() { doTest("c", false, false, false, "int"); }

View File

@@ -801,4 +801,5 @@ move.label.text=Move:
dialog.title.move.directory.to.source.root=Move Directory to Source Root
dialog.title.confirm.move=Confirm Move
dialog.message.moving.directories.to=Moving directories to ''{0}''
progress.title.collect.hierarchy=Collect ''{0}'' hierarchy
progress.title.collect.hierarchy=Collect ''{0}'' hierarchy
introduce.variable.message.expression.refers.to.pattern.variable.declared.outside=The expression refers to the pattern variable ''{0}'' declared outside