From 6cb3ca00458e5ccd022fa2353a4031b9a6a020d6 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Thu, 12 Jun 2025 15:56:29 +0200 Subject: [PATCH] [java-inspections] CreateLocalFromUsageFix: remove external annotations Fixes IDEA-367190 NotNull annotation when creating local variable references library which is not in the project Also: do not resolve reference for writing to a package GitOrigin-RevId: 31f996515323e250d487bf9b7d343f101d788907 --- .../daemon/impl/quickfix/CreateLocalFromUsageFix.java | 4 ++++ .../source/tree/java/PsiReferenceExpressionImpl.java | 3 ++- .../afterNoExternalTypeAnnos.java | 10 ++++++++++ .../afterSwitchPatternGeneric.java | 4 ++-- .../beforeNoExternalTypeAnnos.java | 9 +++++++++ .../beforeSwitchPatternGeneric.java | 4 ++-- .../impl/quickfix/CreateLocalFromUsageTest.java | 11 +++++++++-- 7 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/afterNoExternalTypeAnnos.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/beforeNoExternalTypeAnnos.java diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalFromUsageFix.java index 9f65c7591c75..86d68ea58655 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalFromUsageFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalFromUsageFix.java @@ -19,9 +19,11 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; +import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.codeStyle.JavaCodeStyleSettings; import com.intellij.psi.util.JavaElementKind; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiTypesUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.refactoring.IntroduceVariableUtil; import com.intellij.refactoring.ui.TypeSelectorManagerImpl; @@ -88,6 +90,7 @@ public class CreateLocalFromUsageFix extends CreateVarFromUsageFix { final SmartTypePointer defaultType = SmartTypePointerManager.getInstance(project).createSmartTypePointer(expectedTypes[0]); final PsiType preferredType = TypeSelectorManagerImpl.getPreferredType(expectedTypes, expectedTypes[0]); PsiType type = preferredType != null ? preferredType : expectedTypes[0]; + type = PsiTypesUtil.removeExternalAnnotations(type); if (LambdaUtil.notInferredType(type)) { type = PsiType.getJavaLangObject(element.getManager(), psiFile.getResolveScope()); } @@ -122,6 +125,7 @@ public class CreateLocalFromUsageFix extends CreateVarFromUsageFix { } PsiVariable var = (PsiVariable)decl.getDeclaredElements()[0]; + var = (PsiVariable)JavaCodeStyleManager.getInstance(project).shortenClassReferences(var); boolean isFinal = JavaCodeStyleSettings.getInstance(psiFile).GENERATE_FINAL_LOCALS && !CreateFromUsageUtils.isAccessedForWriting(expressions); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java index 340d062cf5b1..720244d34e28 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java @@ -194,7 +194,8 @@ public class PsiReferenceExpressionImpl extends ExpressionPsiElement implements List qualifiers = resolveAllQualifiers(expression, containingFile); JavaResolveResult[] result = expression.resolve(parentType, containingFile); - if (result.length == 0 && incompleteCode && parentType != JavaElementType.REFERENCE_EXPRESSION) { + if (result.length == 0 && incompleteCode && parentType != JavaElementType.REFERENCE_EXPRESSION && + !PsiUtil.isAccessedForWriting(expression)) { result = expression.resolve(JavaElementType.REFERENCE_EXPRESSION, containingFile); } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/afterNoExternalTypeAnnos.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/afterNoExternalTypeAnnos.java new file mode 100644 index 000000000000..3c94aa69e629 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/afterNoExternalTypeAnnos.java @@ -0,0 +1,10 @@ +// "Create local variable 'set'" "true-preview" +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +class X { + void test() { + Set set = Stream.of(1, 2, 3).collect(Collectors.toSet()); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/afterSwitchPatternGeneric.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/afterSwitchPatternGeneric.java index 190ba8539569..7506129b2050 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/afterSwitchPatternGeneric.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/afterSwitchPatternGeneric.java @@ -14,9 +14,9 @@ class A { sealed interface BaseInterface permits BaseInterface.Record1, BaseInterface.Record2{ - record Record1() implements BaseInterface { + final class Record1 implements BaseInterface { } - record Record2() implements BaseInterface { + final class Record2 implements BaseInterface { } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/beforeNoExternalTypeAnnos.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/beforeNoExternalTypeAnnos.java new file mode 100644 index 000000000000..d011be48f474 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/beforeNoExternalTypeAnnos.java @@ -0,0 +1,9 @@ +// "Create local variable 'set'" "true-preview" +import java.util.stream.Collectors; +import java.util.stream.Stream; + +class X { + void test() { + set = Stream.of(1, 2, 3).collect(Collectors.toSet()); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/beforeSwitchPatternGeneric.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/beforeSwitchPatternGeneric.java index c6d746927576..de6694321565 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/beforeSwitchPatternGeneric.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/beforeSwitchPatternGeneric.java @@ -13,9 +13,9 @@ class A { sealed interface BaseInterface permits BaseInterface.Record1, BaseInterface.Record2{ - record Record1() implements BaseInterface { + final class Record1 implements BaseInterface { } - record Record2() implements BaseInterface { + final class Record2 implements BaseInterface { } } \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalFromUsageTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalFromUsageTest.java index cd57785cef92..e06c1098cca0 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalFromUsageTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalFromUsageTest.java @@ -2,8 +2,11 @@ package com.intellij.codeInsight.daemon.impl.quickfix; import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase; -import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.codeStyle.JavaCodeStyleSettings; +import com.intellij.testFramework.LightProjectDescriptor; +import org.jetbrains.annotations.NotNull; + +import static com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase.JAVA_21_ANNOTATED; public class CreateLocalFromUsageTest extends LightQuickFixParameterizedTestCase { @Override @@ -11,10 +14,14 @@ public class CreateLocalFromUsageTest extends LightQuickFixParameterizedTestCase return "/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage"; } + @Override + protected @NotNull LightProjectDescriptor getProjectDescriptor() { + return JAVA_21_ANNOTATED; + } + @Override protected void setUp() throws Exception { super.setUp(); - setLanguageLevel(LanguageLevel.JDK_21); JavaCodeStyleSettings.getInstance(getProject()).GENERATE_FINAL_LOCALS = getTestName(true).contains("final"); } }