diff --git a/java/java-analysis-impl/src/messages/QuickFixBundle.properties b/java/java-analysis-impl/src/messages/QuickFixBundle.properties index db82b74f175e..4abf27f90a61 100644 --- a/java/java-analysis-impl/src/messages/QuickFixBundle.properties +++ b/java/java-analysis-impl/src/messages/QuickFixBundle.properties @@ -120,7 +120,7 @@ create.method.body=Create Method Body create.method.from.usage.text=Create method ''{0}'' create.type.parameter.from.usage.family=Create type parameter from usage create.type.parameter.from.usage.text=Create type parameter ''{0}'' -create.type.parameter.from.usage.chooser.title=Place to add type parameter +create.type.parameter.from.usage.chooser.title=Place to Add Type Parameter create.parameter.from.usage.family=Create parameter from Usage create.property.from.usage.family=Create property From Usage create.property.from.usage.text=Create property ''{0}'' diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateTypeParameterFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateTypeParameterFromUsageFix.java index fab72e61f1e8..de3a79bdb0a7 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateTypeParameterFromUsageFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateTypeParameterFromUsageFix.java @@ -1,40 +1,27 @@ // Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.codeInsight.daemon.impl.quickfix; -import com.intellij.codeInsight.FileModificationService; import com.intellij.codeInsight.daemon.QuickFixBundle; -import com.intellij.codeInsight.intention.impl.BaseIntentionAction; import com.intellij.ide.highlighter.JavaFileType; -import com.intellij.openapi.application.Application; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.command.WriteCommandAction; -import com.intellij.openapi.editor.Editor; +import com.intellij.modcommand.*; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Pass; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; -import com.intellij.refactoring.IntroduceTargetChooser; -import com.intellij.util.IncorrectOperationException; import com.intellij.util.SmartList; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; +import java.util.Objects; import static com.intellij.util.ObjectUtils.tryCast; -public class CreateTypeParameterFromUsageFix extends BaseIntentionAction { - private final SmartPsiElementPointer myRef; - +public class CreateTypeParameterFromUsageFix extends PsiBasedModCommandAction { public CreateTypeParameterFromUsageFix(PsiJavaCodeReferenceElement refElement) { - myRef = SmartPointerManager.getInstance(refElement.getProject()).createSmartPsiElementPointer(refElement); - } - - @Nullable - private PsiJavaCodeReferenceElement getElement() { - return myRef.getElement(); + super(refElement); } @Nls(capitalization = Nls.Capitalization.Sentence) @@ -45,77 +32,47 @@ public class CreateTypeParameterFromUsageFix extends BaseIntentionAction { } @Override - public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - PsiJavaCodeReferenceElement element = getElement(); - if (element == null) return false; + protected @Nullable Presentation getPresentation(@NotNull ActionContext actionContext, @NotNull PsiJavaCodeReferenceElement element) { Context context = Context.from(element, true); - boolean available = context != null; - if (available) { - setText(QuickFixBundle.message("create.type.parameter.from.usage.text", context.typeName)); - } - return available; + if (context == null) return null; + return Presentation.of(QuickFixBundle.message("create.type.parameter.from.usage.text", context.typeName)); } @Override - public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - PsiJavaCodeReferenceElement element = getElement(); - if (element == null) return; + protected @NotNull ModCommand perform(@NotNull ActionContext actionContext, @NotNull PsiJavaCodeReferenceElement element) { Context context = Context.from(element, false); - if (context == null) return; + if (context == null) return ModCommand.nop(); List placesToAdd = context.placesToAdd; - Application application = ApplicationManager.getApplication(); - if (placesToAdd.size() == 1 || application.isUnitTestMode() || editor == null) { - PsiElement first = placesToAdd.get(0); - createTypeParameter(first, context.typeName); - } - else { - IntroduceTargetChooser.showChooser( - editor, - placesToAdd, - new Pass<>() { - @Override - public void pass(PsiNameIdentifierOwner owner) { - createTypeParameter(owner, context.typeName); - } - }, - PsiNamedElement::getName, - QuickFixBundle.message("create.type.parameter.from.usage.chooser.title") - ); - } - } - - @Override - public boolean startInWriteAction() { - return false; + return new ModChooseAction(QuickFixBundle.message("create.type.parameter.from.usage.chooser.title"), + ContainerUtil.map(placesToAdd, place -> + ModCommand.psiUpdateStep(place, Objects.requireNonNull(place.getName()), + (owner, updater) -> createTypeParameter(owner, context.typeName)))); } private static void createTypeParameter(@NotNull PsiElement methodOrClass, @NotNull String name) { Project project = methodOrClass.getProject(); - if (!FileModificationService.getInstance().preparePsiElementsForWrite(methodOrClass)) return; - WriteCommandAction.runWriteCommandAction(project, QuickFixBundle.message("create.type.parameter.from.usage.family"), null, () -> { - PsiTypeParameterListOwner typeParameterListOwner = tryCast(methodOrClass, PsiTypeParameterListOwner.class); - if (typeParameterListOwner == null) { - throw new IllegalStateException("Only methods and classes allowed here, but was: " + methodOrClass.getClass()); - } - PsiTypeParameterList typeParameterList = typeParameterListOwner.getTypeParameterList(); - final String typeParameterListText; - if (typeParameterList == null) { + PsiTypeParameterListOwner typeParameterListOwner = tryCast(methodOrClass, PsiTypeParameterListOwner.class); + if (typeParameterListOwner == null) { + throw new IllegalStateException("Only methods and classes allowed here, but was: " + methodOrClass.getClass()); + } + PsiTypeParameterList typeParameterList = typeParameterListOwner.getTypeParameterList(); + final String typeParameterListText; + if (typeParameterList == null) { + typeParameterListText = "<" + name + ">"; + } + else { + String existingTypeParameterText = typeParameterList.getText(); + if (typeParameterList.getTypeParameters().length == 0) { typeParameterListText = "<" + name + ">"; } else { - String existingTypeParameterText = typeParameterList.getText(); - if (typeParameterList.getTypeParameters().length == 0) { - typeParameterListText = "<" + name + ">"; - } - else { - String prefix = existingTypeParameterText.substring(0, existingTypeParameterText.length() - 1); - typeParameterListText = prefix + ", " + name + ">"; - } + String prefix = existingTypeParameterText.substring(0, existingTypeParameterText.length() - 1); + typeParameterListText = prefix + ", " + name + ">"; } - PsiTypeParameterList newTypeParameterList = createTypeParameterList(typeParameterListText, project); - replaceOrAddTypeParameterList(methodOrClass, typeParameterList, newTypeParameterList); - }); + } + PsiTypeParameterList newTypeParameterList = createTypeParameterList(typeParameterListText, project); + replaceOrAddTypeParameterList(methodOrClass, typeParameterList, newTypeParameterList); } private static void replaceOrAddTypeParameterList(@NotNull PsiElement methodOrClass, diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefaultQuickFixProvider.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefaultQuickFixProvider.java index 8c2203a19d73..19250ef8d325 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefaultQuickFixProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefaultQuickFixProvider.java @@ -74,7 +74,7 @@ public class DefaultQuickFixProvider extends UnresolvedReferenceQuickFixProvider SurroundWithQuotesAnnotationParameterValueFix.register(registrar, ref); if (PsiUtil.isLanguageLevel5OrHigher(ref)) { - registrar.register(new CreateTypeParameterFromUsageFix(ref)); + registrar.register(new CreateTypeParameterFromUsageFix(ref).asIntention()); } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/afterClass.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/afterClass.java index 4322704ddd4c..bd7fe317a01d 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/afterClass.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/afterClass.java @@ -1,4 +1,4 @@ -// "Create type parameter 'T'" "true" +// "Create type parameter 'T'" "true-preview" import java.util.concurrent.Callable; public class Test extends Callable { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/afterClassEmptyTypeParamList.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/afterClassEmptyTypeParamList.java index 4322704ddd4c..bd7fe317a01d 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/afterClassEmptyTypeParamList.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/afterClassEmptyTypeParamList.java @@ -1,4 +1,4 @@ -// "Create type parameter 'T'" "true" +// "Create type parameter 'T'" "true-preview" import java.util.concurrent.Callable; public class Test extends Callable { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/afterClassExistingParameter.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/afterClassExistingParameter.java index b57dee2b10d8..48944c2ca75d 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/afterClassExistingParameter.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/afterClassExistingParameter.java @@ -1,4 +1,4 @@ -// "Create type parameter 'T'" "true" +// "Create type parameter 'T'" "true-preview" import java.util.concurrent.Callable; public class Test extends Callable { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/afterInMethod1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/afterInMethod1.java new file mode 100644 index 000000000000..529433ad1931 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/afterInMethod1.java @@ -0,0 +1,7 @@ +// "Create type parameter 'T'|->foo" "true-preview" + +public class InMethod { + void foo(T t) { + + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/afterInMethod2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/afterInMethod2.java new file mode 100644 index 000000000000..abe6750fee0f --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/afterInMethod2.java @@ -0,0 +1,7 @@ +// "Create type parameter 'T'|->InMethod" "true-preview" + +public class InMethod { + void foo(T t) { + + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/afterInstanceMethod.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/afterInstanceMethod.java index b53182527480..f0ceda601f56 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/afterInstanceMethod.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/afterInstanceMethod.java @@ -1,4 +1,4 @@ -// "Create type parameter 'T'" "true" +// "Create type parameter 'T'" "true-preview" public class Test { T foo() { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/afterRecord.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/afterRecord.java index fa4f22e43e07..66d82f55e673 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/afterRecord.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/afterRecord.java @@ -1,4 +1,4 @@ -// "Create type parameter 'T'" "true" +// "Create type parameter 'T'" "true-preview" record Point(T x, T y) { } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/afterTypeParameter.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/afterTypeParameter.java index d26409fc34e0..0a1c1f9d36ea 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/afterTypeParameter.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/afterTypeParameter.java @@ -1,4 +1,4 @@ -// "Create type parameter 'U'" "true" +// "Create type parameter 'U'" "true-preview" public class Helpers { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/beforeClass.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/beforeClass.java index ce95d40482a2..7be5b123124f 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/beforeClass.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/beforeClass.java @@ -1,4 +1,4 @@ -// "Create type parameter 'T'" "true" +// "Create type parameter 'T'" "true-preview" import java.util.concurrent.Callable; public class Test extends Callable> { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/beforeClassEmptyTypeParamList.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/beforeClassEmptyTypeParamList.java index ce62fb9304a7..8d95166f8b86 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/beforeClassEmptyTypeParamList.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/beforeClassEmptyTypeParamList.java @@ -1,4 +1,4 @@ -// "Create type parameter 'T'" "true" +// "Create type parameter 'T'" "true-preview" import java.util.concurrent.Callable; public class Test<> extends Callable> { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/beforeClassExistingParameter.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/beforeClassExistingParameter.java index 5db873a0a0c8..f2ebaf3e69a3 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/beforeClassExistingParameter.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/beforeClassExistingParameter.java @@ -1,4 +1,4 @@ -// "Create type parameter 'T'" "true" +// "Create type parameter 'T'" "true-preview" import java.util.concurrent.Callable; public class Test extends Callable> { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/beforeInMethod1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/beforeInMethod1.java new file mode 100644 index 000000000000..7696a12c5a87 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/beforeInMethod1.java @@ -0,0 +1,7 @@ +// "Create type parameter 'T'|->foo" "true-preview" + +public class InMethod { + void foo(T t) { + + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/beforeInMethod2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/beforeInMethod2.java new file mode 100644 index 000000000000..963d12ee5098 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/beforeInMethod2.java @@ -0,0 +1,7 @@ +// "Create type parameter 'T'|->InMethod" "true-preview" + +public class InMethod { + void foo(T t) { + + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/beforeInstanceMethod.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/beforeInstanceMethod.java index be1a7ff778e2..18027be1a464 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/beforeInstanceMethod.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/beforeInstanceMethod.java @@ -1,4 +1,4 @@ -// "Create type parameter 'T'" "true" +// "Create type parameter 'T'" "true-preview" public class Test { T foo() { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/beforeRecord.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/beforeRecord.java index ce0ca5cfaca1..3f616a99e8ee 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/beforeRecord.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/beforeRecord.java @@ -1,4 +1,4 @@ -// "Create type parameter 'T'" "true" +// "Create type parameter 'T'" "true-preview" record Point(T x, T y) { } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/beforeTypeParameter.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/beforeTypeParameter.java index 8a76a96210ca..0740977b692a 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/beforeTypeParameter.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createTypeParameterFromUsage/beforeTypeParameter.java @@ -1,4 +1,4 @@ -// "Create type parameter 'U'" "true" +// "Create type parameter 'U'" "true-preview" public class Helpers {