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 43a88ff220c8..739e0682c837 100644
--- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java
+++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java
@@ -589,6 +589,12 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
}
}
+ String enumInSwitchError = RefactoringUtil.checkEnumConstantInSwitchLabel(expr);
+ if (enumInSwitchError != null) {
+ showErrorMessage(project, editor, enumInSwitchError);
+ return false;
+ }
+
final PsiType originalType = RefactoringUtil.getTypeByExpressionWithExpectedType(expr);
if (originalType == null || LambdaUtil.notInferredType(originalType)) {
@@ -662,7 +668,7 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
getSettings(project, editor, expr, occurrences, typeSelectorManager, inFinalContext, hasWriteAccess, validator, chosenAnchor,
choice);
- final boolean cantChangeFinalModifier = (hasWriteAccess || inFinalContext) && allChoice;
+ final boolean cantChangeFinalModifier = (hasWriteAccess && allChoice) || inFinalContext;
PsiExpression[] allOccurrences = Arrays.stream(occurrences)
.filter(occurrence -> allChoice || (noWriteChoice && !PsiUtil.isAccessedForWriting(occurrence)) || expr.equals(occurrence))
diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/VariableExtractor.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/VariableExtractor.java
index 4f9a76a4fd88..d1e3ef068d41 100644
--- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/VariableExtractor.java
+++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/VariableExtractor.java
@@ -254,6 +254,12 @@ class VariableExtractor {
return firstOccurrence;
}
}
+ if (anchor instanceof PsiSwitchLabelStatement) {
+ PsiSwitchStatement statement = ((PsiSwitchLabelStatement)anchor).getEnclosingSwitchStatement();
+ if (statement != null) {
+ return statement;
+ }
+ }
if (RefactoringUtil.isLoopOrIf(anchor.getParent())) return anchor;
PsiElement child = locateAnchor(anchor);
if (IntroduceVariableBase.isFinalVariableOnLHS(expr)) {
diff --git a/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java b/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java
index 3c3dc8494461..27861da1d4ce 100644
--- a/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java
+++ b/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java
@@ -46,9 +46,11 @@ import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.*;
import com.intellij.refactoring.PackageWrapper;
+import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.introduceField.ElementToWorkOn;
import com.intellij.refactoring.introduceVariable.IntroduceVariableBase;
import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.ObjectUtils;
import com.intellij.util.text.UniqueNameGenerator;
import gnu.trove.THashMap;
import org.jetbrains.annotations.Contract;
@@ -1024,6 +1026,16 @@ public class RefactoringUtil {
return EnsureCodeBlockImpl.ensureCodeBlock(expression);
}
+ public static String checkEnumConstantInSwitchLabel(PsiExpression expr) {
+ if (PsiUtil.skipParenthesizedExprUp(expr.getParent()) instanceof PsiSwitchLabelStatement) {
+ PsiReferenceExpression ref = ObjectUtils.tryCast(PsiUtil.skipParenthesizedExprDown(expr), PsiReferenceExpression.class);
+ if (ref != null && ref.resolve() instanceof PsiEnumConstant) {
+ return RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("refactoring.introduce.variable.enum.in.label.message"));
+ }
+ }
+ return null;
+ }
+
public interface ImplicitConstructorUsageVisitor {
void visitConstructor(PsiMethod constructor, PsiMethod baseConstructor);
diff --git a/java/java-impl/src/com/intellij/refactoring/util/occurrences/BaseOccurrenceManager.java b/java/java-impl/src/com/intellij/refactoring/util/occurrences/BaseOccurrenceManager.java
index 4c240c2decc9..797b5c39566f 100644
--- a/java/java-impl/src/com/intellij/refactoring/util/occurrences/BaseOccurrenceManager.java
+++ b/java/java-impl/src/com/intellij/refactoring/util/occurrences/BaseOccurrenceManager.java
@@ -15,9 +15,7 @@
*/
package com.intellij.refactoring.util.occurrences;
-import com.intellij.psi.PsiClass;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiExpression;
+import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.introduceField.ElementToWorkOn;
import com.intellij.refactoring.util.RefactoringUtil;
@@ -87,11 +85,15 @@ public abstract class BaseOccurrenceManager implements OccurrenceManager {
PsiElement scopeToDeclare = null;
for (PsiExpression occurrence : occurrences) {
final PsiElement data = occurrence.getUserData(ElementToWorkOn.PARENT);
+ PsiElement element = data != null ? data : occurrence;
if (scopeToDeclare == null) {
- scopeToDeclare = data != null ? data : occurrence;
+ scopeToDeclare = element;
}
else {
- scopeToDeclare = PsiTreeUtil.findCommonParent(scopeToDeclare, data != null ? data : occurrence);
+ scopeToDeclare = PsiTreeUtil.findCommonParent(scopeToDeclare, element);
+ }
+ if (PsiTreeUtil.getParentOfType(element, PsiSwitchLabelStatement.class, true, PsiStatement.class) != null) {
+ return true;
}
}
if(scopeToDeclare == null) {
diff --git a/java/java-tests/testData/refactoring/introduceVariable/CaseLabel.after.java b/java/java-tests/testData/refactoring/introduceVariable/CaseLabel.after.java
new file mode 100644
index 000000000000..8c05ab174f12
--- /dev/null
+++ b/java/java-tests/testData/refactoring/introduceVariable/CaseLabel.after.java
@@ -0,0 +1,14 @@
+class A {
+ private void A() {
+ final int temp = 2;
+ switch (1) {
+ case 1:
+ System.out.println(1);
+ break;
+ case temp:
+ System.out.println(temp);
+ break;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/introduceVariable/CaseLabel.java b/java/java-tests/testData/refactoring/introduceVariable/CaseLabel.java
new file mode 100644
index 000000000000..7cb66dd6028a
--- /dev/null
+++ b/java/java-tests/testData/refactoring/introduceVariable/CaseLabel.java
@@ -0,0 +1,13 @@
+class A {
+ private void A() {
+ switch (1) {
+ case 1:
+ System.out.println(1);
+ break;
+ case 2:
+ System.out.println(2);
+ break;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/introduceVariable/CaseLabelEnum.java b/java/java-tests/testData/refactoring/introduceVariable/CaseLabelEnum.java
new file mode 100644
index 000000000000..7ba1668188ce
--- /dev/null
+++ b/java/java-tests/testData/refactoring/introduceVariable/CaseLabelEnum.java
@@ -0,0 +1,14 @@
+class A {
+ private void A(X x) {
+ switch (x) {
+ case A:
+ System.out.println(1);
+ break;
+ case B:
+ System.out.println(2);
+ break;
+ }
+
+ }
+}
+enum X {A,B,C}
\ 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 d01b2feb8fff..7e7c11d3c8e8 100644
--- a/java/java-tests/testSrc/com/intellij/java/refactoring/IntroduceVariableTest.java
+++ b/java/java-tests/testSrc/com/intellij/java/refactoring/IntroduceVariableTest.java
@@ -204,6 +204,21 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase {
doTest(new MockIntroduceVariableHandler("temp", true, false, false, "Node"));
}
+ public void testCaseLabel() {
+ doTest(new MockIntroduceVariableHandler("temp", true, false, false, "int"));
+ }
+
+ public void testCaseLabelEnum() {
+ try {
+ doTest(new MockIntroduceVariableHandler("temp", true, false, false, ""));
+ }
+ catch (RuntimeException e) {
+ assertEquals("Error message:Cannot perform refactoring.\nEnum constant in switch label cannot be extracted", e.getMessage());
+ return;
+ }
+ fail("Should not be able to perform refactoring");
+ }
+
public void testIfConditionAndChain() {
doTest(new MockIntroduceVariableHandler("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 bdf89ec77a2e..918d2ffb2d95 100644
--- a/platform/platform-resources-en/src/messages/RefactoringBundle.properties
+++ b/platform/platform-resources-en/src/messages/RefactoringBundle.properties
@@ -846,4 +846,6 @@ generate.module.descriptors.build.required.message=Couldn't generate module desc
generate.module.descriptors.scanning.message=Scanning Compiler Output
generate.module.descriptors.collecting.message=Collecting Dependencies
generate.module.descriptors.analysing.message=Analysing Dependencies
-generate.module.descriptors.preparing.message=Preparing Code
\ No newline at end of file
+generate.module.descriptors.preparing.message=Preparing Code
+
+refactoring.introduce.variable.enum.in.label.message=Enum constant in switch label cannot be extracted
\ No newline at end of file