diff --git a/java/java-impl-refactorings/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java b/java/java-impl-refactorings/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java index cc942effbdaa..6eedca5be61e 100644 --- a/java/java-impl-refactorings/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java +++ b/java/java-impl-refactorings/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java @@ -1,4 +1,4 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.refactoring.introduceVariable; import com.intellij.codeInsight.CodeInsightUtil; @@ -55,6 +55,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.ExpressionUtils; import com.siyeh.ig.psiutils.VariableAccessUtils; import one.util.streamex.EntryStream; import one.util.streamex.StreamEx; @@ -293,6 +294,15 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase { showErrorMessage(project, editor, RefactoringBundle.getCannotRefactorMessage(errorMessage)); return false; } + PsiExpression topLevelExpression = ExpressionUtils.getTopLevelExpression(expr); + if (topLevelExpression.getParent() instanceof PsiField f) { + PsiClass containingClass = f.getContainingClass(); + if (containingClass != null && containingClass.isInterface()) { + String message = JavaRefactoringBundle.message("introduce.variable.message.cannot.extract.variable.in.interface"); + showErrorMessage(project, editor, RefactoringBundle.getCannotRefactorMessage(message)); + return false; + } + } } if (expr != null && expr.getParent() instanceof PsiExpressionStatement) { diff --git a/java/java-tests/testData/refactoring/introduceVariable/DisallowInInterface.java b/java/java-tests/testData/refactoring/introduceVariable/DisallowInInterface.java new file mode 100644 index 000000000000..83da513fb3b7 --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/DisallowInInterface.java @@ -0,0 +1,4 @@ +interface DisallowInInterface { + + int i = 10; +} \ 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 252c1827f0e9..5a41d9dab34b 100644 --- a/java/java-tests/testSrc/com/intellij/java/refactoring/IntroduceVariableTest.java +++ b/java/java-tests/testSrc/com/intellij/java/refactoring/IntroduceVariableTest.java @@ -393,6 +393,10 @@ public class IntroduceVariableTest extends LightJavaCodeInsightTestCase { doTestWithFailure("input", "Object", "The selected expression refers to pattern variable 's', which will be out of scope."); } + public void testDisallowInInterface() { + doTestWithFailure("", "", "Cannot extract variable in an interface."); + } + 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"); } public void testStatementsBeforeSuper() { diff --git a/java/openapi/resources/messages/JavaRefactoringBundle.properties b/java/openapi/resources/messages/JavaRefactoringBundle.properties index 545b162b67b9..30a9af787102 100644 --- a/java/openapi/resources/messages/JavaRefactoringBundle.properties +++ b/java/openapi/resources/messages/JavaRefactoringBundle.properties @@ -821,6 +821,7 @@ progress.title.collect.hierarchy=Collect ''{0}'' hierarchy introduce.variable.message.change.semantics.warning=Extracting the selected expression changes the semantics of the surrounding expression. introduce.variable.message.expression.refers.to.pattern.variable.declared.outside=The selected expression refers to pattern variable ''{0}'', which will be out of scope. introduce.variable.message.cannot.extract.in.implicit.class=Cannot extract in implicitly declared class. +introduce.variable.message.cannot.extract.variable.in.interface=Cannot extract variable in an interface. tooltip.cannot.inline.pattern.variable=Cannot inline pattern variable inline.popup.highlight=Highlight {0} conflicting {0, choice, 1#write|2#writes} inline.popup.ignore.conflicts=Ignore writes and continue