From eeed0d8a1f4c089a0bc6bc994edae50d79d4a3a1 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Thu, 9 Feb 2023 13:12:08 +0100 Subject: [PATCH] Java: allow introducing static field inside a record (IDEA-312819) GitOrigin-RevId: 0f71260012ef1e16f02c7203ab4ef6ed74179936 --- .../BaseExpressionToFieldHandler.java | 4 ++-- .../introduceField/IntroduceConstantHandler.java | 2 +- .../introduceField/IntroduceFieldHandler.java | 15 +++++++++++---- .../introduceField/afterStaticFieldInRecord.java | 6 ++++++ .../beforeDisallowFieldInRecord.java | 5 +++++ .../introduceField/beforeStaticFieldInRecord.java | 5 +++++ .../IntroduceFieldInSameClassTest.java | 15 +++++++++++++++ .../messages/JavaRefactoringBundle.properties | 4 ++-- 8 files changed, 47 insertions(+), 9 deletions(-) create mode 100644 java/java-tests/testData/refactoring/introduceField/afterStaticFieldInRecord.java create mode 100644 java/java-tests/testData/refactoring/introduceField/beforeDisallowFieldInRecord.java create mode 100644 java/java-tests/testData/refactoring/introduceField/beforeStaticFieldInRecord.java diff --git a/java/java-impl-refactorings/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java b/java/java-impl-refactorings/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java index 5ef0cc61e32e..d8decab47766 100644 --- a/java/java-impl-refactorings/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java +++ b/java/java-impl-refactorings/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java @@ -166,7 +166,7 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase } } - if (!validClass(myParentClass, editor)) { + if (!validClass(myParentClass, selectedExpr, editor)) { return true; } @@ -262,7 +262,7 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase return myParentClass; } - protected abstract boolean validClass(PsiClass parentClass, Editor editor); + protected abstract boolean validClass(PsiClass parentClass, PsiExpression selectedExpr, Editor editor); private static PsiElement getNormalizedAnchor(PsiElement anchorElement) { PsiElement child = anchorElement; diff --git a/java/java-impl-refactorings/src/com/intellij/refactoring/introduceField/IntroduceConstantHandler.java b/java/java-impl-refactorings/src/com/intellij/refactoring/introduceField/IntroduceConstantHandler.java index a3c16e868a03..a6c2313e6a31 100644 --- a/java/java-impl-refactorings/src/com/intellij/refactoring/introduceField/IntroduceConstantHandler.java +++ b/java/java-impl-refactorings/src/com/intellij/refactoring/introduceField/IntroduceConstantHandler.java @@ -257,7 +257,7 @@ public class IntroduceConstantHandler extends BaseExpressionToFieldHandler imple } @Override - protected boolean validClass(PsiClass parentClass, Editor editor) { + protected boolean validClass(PsiClass parentClass, PsiExpression selectedExpr, Editor editor) { return true; } 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 71ea3250c4fe..408b6f7833b7 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 @@ -35,10 +35,17 @@ public class IntroduceFieldHandler extends BaseExpressionToFieldHandler implemen } @Override - protected boolean validClass(PsiClass parentClass, Editor editor) { - if (parentClass.isInterface() || parentClass.isRecord()) { - String message = RefactoringBundle.getCannotRefactorMessage( - JavaRefactoringBundle.message(parentClass.isRecord() ? "cannot.introduce.field.in.record" : "cannot.introduce.field.in.interface")); + 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()); + return false; + } + else if (parentClass.isRecord()) { + final PsiModifierListOwner staticParentElement = PsiUtil.getEnclosingStaticElement(selectedExpr, parentClass); + boolean declareStatic = staticParentElement != null; + if (declareStatic) return true; + String message = RefactoringBundle.getCannotRefactorMessage(JavaRefactoringBundle.message("cannot.introduce.field.in.record")); CommonRefactoringUtil.showErrorHint(parentClass.getProject(), editor, message, getRefactoringNameText(), getHelpID()); return false; } diff --git a/java/java-tests/testData/refactoring/introduceField/afterStaticFieldInRecord.java b/java/java-tests/testData/refactoring/introduceField/afterStaticFieldInRecord.java new file mode 100644 index 000000000000..88a014314afb --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceField/afterStaticFieldInRecord.java @@ -0,0 +1,6 @@ +record R() { + public static final String string = ""; + + private static void x(int i) { + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/introduceField/beforeDisallowFieldInRecord.java b/java/java-tests/testData/refactoring/introduceField/beforeDisallowFieldInRecord.java new file mode 100644 index 000000000000..219aada97dce --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceField/beforeDisallowFieldInRecord.java @@ -0,0 +1,5 @@ +record R() { + private void x(int i) { + "" + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/introduceField/beforeStaticFieldInRecord.java b/java/java-tests/testData/refactoring/introduceField/beforeStaticFieldInRecord.java new file mode 100644 index 000000000000..9e04ca854bd8 --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceField/beforeStaticFieldInRecord.java @@ -0,0 +1,5 @@ +record R() { + private static void x(int i) { + "" + } +} \ 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 13480765146e..fa2dcb6b4662 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,21 @@ public class IntroduceFieldInSameClassTest extends LightJavaCodeInsightTestCase } } + public void testDisallowFieldInRecord() { + configureByFile("beforeDisallowFieldInRecord.java"); + try { + performRefactoring(BaseExpressionToFieldHandler.InitializationPlace.IN_FIELD_DECLARATION, false); + fail("Should not proceed"); + } + catch (CommonRefactoringUtil.RefactoringErrorHintException e) { + assertEquals("Cannot perform refactoring.\nInstance fields are not allowed in a record.", e.getMessage()); + } + } + + public void testStaticFieldInRecord() { + doTest(BaseExpressionToFieldHandler.InitializationPlace.IN_FIELD_DECLARATION, true); + } + public void testAcceptIntroduceFieldFromExprInThisCall() { doTest(BaseExpressionToFieldHandler.InitializationPlace.IN_FIELD_DECLARATION, true); } diff --git a/java/openapi/resources/messages/JavaRefactoringBundle.properties b/java/openapi/resources/messages/JavaRefactoringBundle.properties index 92ebacd97658..31953370878e 100644 --- a/java/openapi/resources/messages/JavaRefactoringBundle.properties +++ b/java/openapi/resources/messages/JavaRefactoringBundle.properties @@ -57,8 +57,8 @@ auto.rename.module.entity=Java Module 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=Instance fields are not allowed in the interface -cannot.introduce.field.in.record=Instance fields are not allowed in the record +cannot.introduce.field.in.interface=Non-constant fields are not allowed in an interface. +cannot.introduce.field.in.record=Instance fields are not allowed in a record. 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