diff --git a/java/java-impl-refactorings/src/com/intellij/refactoring/introduceField/IntroduceFieldHandler.java b/java/java-impl-refactorings/src/com/intellij/refactoring/introduceField/IntroduceFieldHandler.java
index f9fe03e3f2d8..59a17349dd5a 100644
--- a/java/java-impl-refactorings/src/com/intellij/refactoring/introduceField/IntroduceFieldHandler.java
+++ b/java/java-impl-refactorings/src/com/intellij/refactoring/introduceField/IntroduceFieldHandler.java
@@ -7,6 +7,7 @@ import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.NlsContexts;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
@@ -17,6 +18,7 @@ import com.intellij.refactoring.introduce.inplace.AbstractInplaceIntroducer;
import com.intellij.refactoring.AbstractJavaInplaceIntroducer;
import com.intellij.refactoring.ui.TypeSelectorManagerImpl;
import com.intellij.refactoring.util.CommonRefactoringUtil;
+import com.intellij.refactoring.util.RefactoringUIUtil;
import com.intellij.refactoring.util.occurrences.*;
import com.intellij.util.JavaPsiConstructorUtil;
import org.jetbrains.annotations.NotNull;
@@ -38,13 +40,26 @@ public class IntroduceFieldHandler extends BaseExpressionToFieldHandler implemen
@Override
protected boolean validClass(PsiClass parentClass, PsiExpression selectedExpr, Editor editor) {
if (parentClass.isInterface()) {
- String message = RefactoringBundle.getCannotRefactorMessage(JavaRefactoringBundle.message("cannot.introduce.field.in.interface"));
- CommonRefactoringUtil.showErrorHint(parentClass.getProject(), editor, message, getRefactoringNameText(), getHelpID());
+ String message = JavaRefactoringBundle.message("cannot.introduce.field.in.interface");
+ showErrorMessage(parentClass.getProject(), editor, message);
+ return false;
+ }
+ PsiClass aClass = PsiUtil.resolveClassInClassTypeOnly(selectedExpr.getType());
+ if (aClass != null && PsiUtil.isLocalClass(aClass) && !PsiTreeUtil.isAncestor(aClass, parentClass, false)) {
+ String message = JavaRefactoringBundle.message("0.is.not.visible.to.members.of.1",
+ RefactoringUIUtil.getDescription(aClass, false),
+ RefactoringUIUtil.getDescription(parentClass, false));
+ showErrorMessage(aClass.getProject(), editor, StringUtil.capitalize(message));
return false;
}
return true;
}
+ private void showErrorMessage(@NotNull Project project, Editor editor, @NlsContexts.DialogMessage String message) {
+ message = RefactoringBundle.getCannotRefactorMessage(message);
+ CommonRefactoringUtil.showErrorHint(project, editor, message, getRefactoringNameText(), getHelpID());
+ }
+
@Override
protected String getHelpID() {
return HelpID.INTRODUCE_FIELD;
@@ -177,18 +192,17 @@ public class IntroduceFieldHandler extends BaseExpressionToFieldHandler implemen
protected boolean invokeImpl(final Project project, PsiLocalVariable localVariable, final Editor editor) {
final PsiElement parent = localVariable.getParent();
if (!(parent instanceof PsiDeclarationStatement)) {
- String message = RefactoringBundle.getCannotRefactorMessage(JavaRefactoringBundle.message("error.wrong.caret.position.local.or.expression.name"));
- CommonRefactoringUtil.showErrorHint(project, editor, message, getRefactoringNameText(), getHelpID());
+ showErrorMessage(project, editor, JavaRefactoringBundle.message("error.wrong.caret.position.local.or.expression.name"));
return false;
}
LocalToFieldHandler localToFieldHandler = new LocalToFieldHandler(project, false){
@Override
protected Settings showRefactoringDialog(PsiClass aClass,
PsiLocalVariable local,
- PsiExpression[] occurences,
+ PsiExpression[] occurrences,
boolean isStatic) {
final PsiStatement statement = PsiTreeUtil.getParentOfType(local, PsiStatement.class);
- return IntroduceFieldHandler.this.showRefactoringDialog(project, editor, aClass, local.getInitializer(), local.getType(), occurences, local, statement);
+ return IntroduceFieldHandler.this.showRefactoringDialog(project, editor, aClass, local.getInitializer(), local.getType(), occurrences, local, statement);
}
@Override
diff --git a/java/java-tests/testData/refactoring/introduceField/beforeRejectFieldFromLocal.java b/java/java-tests/testData/refactoring/introduceField/beforeRejectFieldFromLocal.java
new file mode 100644
index 000000000000..9728eb13e482
--- /dev/null
+++ b/java/java-tests/testData/refactoring/introduceField/beforeRejectFieldFromLocal.java
@@ -0,0 +1,8 @@
+class K {
+ void m() {
+ class Local {
+ void locally() {}
+ }
+ new Local().locally();
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/java/refactoring/IntroduceFieldInSameClassTest.java b/java/java-tests/testSrc/com/intellij/java/refactoring/IntroduceFieldInSameClassTest.java
index 6755acdc3c48..4b131c2e66f1 100644
--- a/java/java-tests/testSrc/com/intellij/java/refactoring/IntroduceFieldInSameClassTest.java
+++ b/java/java-tests/testSrc/com/intellij/java/refactoring/IntroduceFieldInSameClassTest.java
@@ -116,6 +116,18 @@ public class IntroduceFieldInSameClassTest extends LightJavaCodeInsightTestCase
}
}
+ public void testRejectFieldFromLocal() {
+ configureByFile("beforeRejectFieldFromLocal.java");
+ try {
+ performRefactoring(BaseExpressionToFieldHandler.InitializationPlace.IN_FIELD_DECLARATION, false);
+ fail("Should not proceed");
+ }
+ catch (CommonRefactoringUtil.RefactoringErrorHintException e) {
+ assertEquals("Cannot perform refactoring.\n" +
+ "Local class Local is not visible to members of class K", e.getMessage());
+ }
+ }
+
public void testStaticFieldInRecord() {
doTest(BaseExpressionToFieldHandler.InitializationPlace.IN_FIELD_DECLARATION, true);
}
diff --git a/java/openapi/resources/messages/JavaRefactoringBundle.properties b/java/openapi/resources/messages/JavaRefactoringBundle.properties
index 33cdba7a5482..678610008d3b 100644
--- a/java/openapi/resources/messages/JavaRefactoringBundle.properties
+++ b/java/openapi/resources/messages/JavaRefactoringBundle.properties
@@ -60,6 +60,7 @@ boolean.method.result=boolean method result
can.t.restore.context.for.method.extraction=Can't restore context for method extraction
cannot.find.or.create.destination.directory=Cannot find or create destination directory
cannot.introduce.field.in.interface=Non-constant fields are not allowed in an interface.
+0.is.not.visible.to.members.of.1={0} is not visible to members of {1}
cannot.move=Cannot Move
cannot.move.inner.class.0.into.itself=Cannot move inner class {0} into itself
cannot.move.package.into.itself=Cannot move package into itself