diff --git a/java/java-analysis-impl/src/META-INF/JavaAnalysisPlugin.xml b/java/java-analysis-impl/src/META-INF/JavaAnalysisPlugin.xml
index 6f6b2112d3e2..b3cf28eeb9f2 100644
--- a/java/java-analysis-impl/src/META-INF/JavaAnalysisPlugin.xml
+++ b/java/java-analysis-impl/src/META-INF/JavaAnalysisPlugin.xml
@@ -331,5 +331,6 @@
+
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/ex/EntryPointsManagerBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/ex/EntryPointsManagerBase.java
index 33911f31c468..e87d50294611 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/ex/EntryPointsManagerBase.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/ex/EntryPointsManagerBase.java
@@ -5,27 +5,29 @@ import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.MetaAnnotationUtil;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
import com.intellij.codeInsight.daemon.QuickFixBundle;
-import com.intellij.codeInsight.intention.IntentionAction;
-import com.intellij.codeInsight.intention.preview.IntentionPreviewInfo;
-import com.intellij.codeInspection.LocalQuickFix;
-import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.codeInsight.options.JavaClassValidator;
+import com.intellij.codeInspection.options.OptPane;
+import com.intellij.codeInspection.options.OptionContainer;
+import com.intellij.codeInspection.options.OptionController;
+import com.intellij.codeInspection.options.OptionControllerProvider;
import com.intellij.codeInspection.reference.*;
+import com.intellij.codeInspection.util.IntentionName;
import com.intellij.configurationStore.XmlSerializer;
+import com.intellij.java.JavaBundle;
+import com.intellij.modcommand.ActionContext;
+import com.intellij.modcommand.ModCommand;
+import com.intellij.modcommand.ModCommandAction;
+import com.intellij.modcommand.Presentation;
import com.intellij.openapi.application.ReadAction;
-import com.intellij.openapi.command.undo.BasicUndoableAction;
-import com.intellij.openapi.command.undo.UndoManager;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.State;
-import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.JDOMExternalizableStringList;
import com.intellij.openapi.util.NlsSafe;
-import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.profile.codeInspection.ProjectInspectionProfileManager;
import com.intellij.psi.*;
-import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.xmlb.annotations.Attribute;
import com.intellij.util.xmlb.annotations.Tag;
@@ -40,7 +42,8 @@ import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
@State(name = "EntryPointsManager")
-public abstract class EntryPointsManagerBase extends EntryPointsManager implements PersistentStateComponent {
+public abstract class EntryPointsManagerBase extends EntryPointsManager implements PersistentStateComponent,
+ OptionContainer {
@ApiStatus.Internal
public static final ExtensionPointName DEAD_CODE_EP_NAME = new ExtensionPointName<>("com.intellij.deadCode");
@@ -622,21 +625,31 @@ public abstract class EntryPointsManagerBase extends EntryPointsManager implemen
}
}
- public class AddImplicitlyWriteAnnotation implements IntentionAction, LocalQuickFix {
- @NotNull
- private final String myQualifiedName;
+ @Override
+ public @NotNull OptionController getOptionController() {
+ return OptionContainer.super.getOptionController()
+ .withRootPane(() -> OptPane.pane(
+ OptPane.stringList("myWriteAnnotations", JavaBundle.message("separator.mark.field.as.implicitly.written.if.annotated.by"),
+ new JavaClassValidator().annotationsOnly()),
+ OptPane.stringList("ADDITIONAL_ANNOTATIONS", JavaBundle.message("separator.mark.as.entry.point.if.annotated.by"),
+ new JavaClassValidator().annotationsOnly()))
+ );
+ }
- public AddImplicitlyWriteAnnotation(@NotNull String qualifiedName) {myQualifiedName = qualifiedName;}
+ private static class AddAnnotation implements ModCommandAction {
+ private final @NotNull String myQualifiedName;
+ private final @NotNull String myBindId;
+ private final @NotNull @IntentionName String myMessage;
- @Override
- @NotNull
- public String getText() {
- return QuickFixBundle.message("fix.add.write.annotation.text", myQualifiedName);
+ private AddAnnotation(@NotNull String qualifiedName, @NotNull String bindId, @NotNull @IntentionName String message) {
+ myQualifiedName = qualifiedName;
+ myBindId = bindId;
+ myMessage = message;
}
@Override
- public @NotNull String getName() {
- return getText();
+ public @NotNull Presentation getPresentation(@NotNull ActionContext context) {
+ return Presentation.of(myMessage);
}
@Override
@@ -646,59 +659,49 @@ public abstract class EntryPointsManagerBase extends EntryPointsManager implemen
}
@Override
- public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
- performAction(descriptor.getStartElement().getContainingFile());
- }
-
- @Override
- public @NotNull IntentionPreviewInfo generatePreview(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) {
- return new IntentionPreviewInfo.Html(QuickFixBundle.message("fix.add.write.annotation.description", myQualifiedName));
- }
-
- @Override
- public @NotNull IntentionPreviewInfo generatePreview(@NotNull Project project, @NotNull ProblemDescriptor previewDescriptor) {
- return new IntentionPreviewInfo.Html(QuickFixBundle.message("fix.add.write.annotation.description", myQualifiedName));
- }
-
- @Override
- public boolean isAvailable(@NotNull Project project1, Editor editor, PsiFile file) {
- return true;
- }
-
- @Override
- public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
- performAction(file);
- }
-
- private void performAction(@NotNull PsiFile file) {
- Project project = file.getProject();
- VirtualFile vFile = file.getVirtualFile();
- doAddAnnotation(project);
- UndoManager.getInstance(project).undoableActionPerformed(new BasicUndoableAction(vFile) {
- @Override
- public void undo() {
- if (myWriteAnnotations.removeAll(List.of(myQualifiedName))) {
- ProjectInspectionProfileManager.getInstance(project).fireProfileChanged();
- }
- }
-
- @Override
- public void redo() {
- doAddAnnotation(project);
- }
+ public @NotNull ModCommand perform(@NotNull ActionContext context) {
+ return ModCommand.updateOption(context.file(), myBindId, oldValue -> {
+ @SuppressWarnings("unchecked") List list = (List)oldValue;
+ list.add(myQualifiedName);
+ list.sort(null);
+ return list;
});
}
+ }
- private void doAddAnnotation(@NotNull Project project) {
- if (!myWriteAnnotations.contains(myQualifiedName)) {
- myWriteAnnotations.add(myQualifiedName);
- ProjectInspectionProfileManager.getInstance(project).fireProfileChanged();
- }
+ /**
+ * @param qualifiedName annotation qualified name
+ * @return an action that adds the specified annotation qualified name to the list of implicitly written fields annotations
+ */
+ public static @NotNull ModCommandAction createAddImplicitWriteAnnotation(@NotNull String qualifiedName) {
+ return new AddAnnotation(qualifiedName, "EntryPointsManager.myWriteAnnotations",
+ QuickFixBundle.message("fix.add.write.annotation.text", qualifiedName));
+ }
+
+ /**
+ * @param qualifiedName annotation qualified name
+ * @return an action that adds the specified annotation qualified name to the list of entry point annotations
+ */
+ public static @NotNull ModCommandAction createAddEntryPointAnnotation(@NotNull String qualifiedName) {
+ return new AddAnnotation(qualifiedName, "EntryPointsManager.ADDITIONAL_ANNOTATIONS",
+ QuickFixBundle.message("fix.unused.symbol.injection.text", qualifiedName));
+ }
+
+ /**
+ * Provides bindId = "EntryPointsManager.myWriteAnnotations" and "EntryPointsManager.ADDITIONAL_ANNOTATIONS"
+ * lists to control entry points
+ */
+ public static final class Provider implements OptionControllerProvider {
+ @Override
+ public @NotNull OptionController forContext(@NotNull PsiElement context) {
+ Project project = context.getProject();
+ return getInstance(project).getOptionController()
+ .onValueSet((bindId, value) -> ProjectInspectionProfileManager.getInstance(project).fireProfileChanged());
}
@Override
- public boolean startInWriteAction() {
- return false;
+ public @NotNull String name() {
+ return "EntryPointsManager";
}
}
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java
index 6e74e1b360ab..831cd0fb5989 100644
--- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java
+++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java
@@ -21,7 +21,6 @@ import com.intellij.codeInspection.dataFlow.fix.DeleteSwitchLabelFix;
import com.intellij.codeInspection.ex.EntryPointsManagerBase;
import com.intellij.codeInspection.ex.InspectionToolWrapper;
import com.intellij.codeInspection.util.IntentionName;
-import com.intellij.codeInspection.util.SpecialAnnotationsUtil;
import com.intellij.diagnostic.CoreAttachmentFactory;
import com.intellij.ide.scratch.ScratchUtil;
import com.intellij.java.JavaBundle;
@@ -746,18 +745,13 @@ public final class QuickFixFactoryImpl extends QuickFixFactory {
@Override
public IntentionAction createAddToDependencyInjectionAnnotationsFix(@NotNull Project project,
@NotNull String qualifiedName) {
- final EntryPointsManagerBase entryPointsManager = EntryPointsManagerBase.getInstance(project);
- return SpecialAnnotationsUtil.createAddToSpecialAnnotationsListIntentionAction(
- QuickFixBundle.message("fix.unused.symbol.injection.text", qualifiedName),
- QuickFixBundle.message("fix.unused.symbol.injection.family"),
- JavaBundle.message("separator.mark.as.entry.point.if.annotated.by"), entryPointsManager.ADDITIONAL_ANNOTATIONS, qualifiedName);
+ return EntryPointsManagerBase.createAddEntryPointAnnotation(qualifiedName).asIntention();
}
@NotNull
@Override
public IntentionAction createAddToImplicitlyWrittenFieldsFix(@NotNull Project project, @NotNull final String qualifiedName) {
- EntryPointsManagerBase entryPointsManagerBase = EntryPointsManagerBase.getInstance(project);
- return entryPointsManagerBase.new AddImplicitlyWriteAnnotation(qualifiedName);
+ return EntryPointsManagerBase.createAddImplicitWriteAnnotation(qualifiedName).asIntention();
}
@NotNull
diff --git a/java/java-impl/src/com/intellij/codeInspection/util/SpecialAnnotationsUtil.java b/java/java-impl/src/com/intellij/codeInspection/util/SpecialAnnotationsUtil.java
index 9ee142e4f920..4d980349c64c 100644
--- a/java/java-impl/src/com/intellij/codeInspection/util/SpecialAnnotationsUtil.java
+++ b/java/java-impl/src/com/intellij/codeInspection/util/SpecialAnnotationsUtil.java
@@ -2,8 +2,6 @@
package com.intellij.codeInspection.util;
-import com.intellij.codeInsight.intention.IntentionAction;
-import com.intellij.codeInsight.intention.preview.IntentionPreviewInfo;
import com.intellij.codeInspection.ui.InspectionOptionsPanel;
import com.intellij.ide.DataManager;
import com.intellij.ide.util.ClassFilter;
@@ -14,15 +12,11 @@ import com.intellij.openapi.actionSystem.ActionToolbarPosition;
import com.intellij.openapi.actionSystem.ActionUpdateThread;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.NlsContexts;
-import com.intellij.openapi.util.NlsSafe;
-import com.intellij.profile.codeInspection.ProjectInspectionProfileManager;
import com.intellij.psi.PsiClass;
-import com.intellij.psi.PsiFile;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.ui.AnActionButton;
import com.intellij.ui.AnActionButtonRunnable;
@@ -30,18 +24,14 @@ import com.intellij.ui.SortedListModel;
import com.intellij.ui.ToolbarDecorator;
import com.intellij.ui.components.JBList;
import com.intellij.util.IconUtil;
-import com.intellij.util.IncorrectOperationException;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UI;
-import one.util.streamex.StreamEx;
-import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import java.awt.*;
-import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.function.Predicate;
@@ -163,47 +153,4 @@ public final class SpecialAnnotationsUtil {
.resizeY(true)
.createPanel();
}
-
- public static IntentionAction createAddToSpecialAnnotationsListIntentionAction(final @IntentionName String text,
- final @IntentionFamilyName String family,
- final @Nls String listTitle,
- final List targetList,
- final String qualifiedName) {
- return new IntentionAction() {
- @Override
- @NotNull
- public String getText() {
- return text;
- }
-
- @Override
- @NotNull
- public String getFamilyName() {
- return family;
- }
-
- @Override
- public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
- return true;
- }
-
- @Override
- public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
- targetList.add(qualifiedName);
- Collections.sort(targetList);
- ProjectInspectionProfileManager.getInstance(project).fireProfileChanged();
- }
-
- @Override
- public boolean startInWriteAction() {
- return false;
- }
-
- @Override
- public @NotNull IntentionPreviewInfo generatePreview(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) {
- List<@NlsSafe String> prefixes = StreamEx.of(targetList).append(qualifiedName).sorted().toList();
- return IntentionPreviewInfo.addListOption(prefixes, qualifiedName, listTitle);
- }
- };
- }
}
diff --git a/java/java-impl/src/com/siyeh/ig/style/FieldMayBeFinalInspection.java b/java/java-impl/src/com/siyeh/ig/style/FieldMayBeFinalInspection.java
index 1ca039cd9048..7b53ee3e0f91 100644
--- a/java/java-impl/src/com/siyeh/ig/style/FieldMayBeFinalInspection.java
+++ b/java/java-impl/src/com/siyeh/ig/style/FieldMayBeFinalInspection.java
@@ -51,7 +51,7 @@ public class FieldMayBeFinalInspection extends BaseInspection implements Cleanup
PsiField field = (PsiField)infos[0];
fixes.add(MakeFieldFinalFix.buildFixUnconditional(field));
SpecialAnnotationsUtilBase.processUnknownAnnotations(field, annoName -> {
- fixes.add(EntryPointsManagerBase.getInstance(field.getProject()).new AddImplicitlyWriteAnnotation(annoName));
+ fixes.add(LocalQuickFix.from(EntryPointsManagerBase.createAddImplicitWriteAnnotation(annoName)));
return true;
});
return fixes.toArray(LocalQuickFix.EMPTY_ARRAY);
diff --git a/plugins/kotlin/idea/tests/testData/quickfix/unusedSuppressAnnotation/simple.kt b/plugins/kotlin/idea/tests/testData/quickfix/unusedSuppressAnnotation/simple.kt
index 84fc7e573342..ade59f33b6b5 100644
--- a/plugins/kotlin/idea/tests/testData/quickfix/unusedSuppressAnnotation/simple.kt
+++ b/plugins/kotlin/idea/tests/testData/quickfix/unusedSuppressAnnotation/simple.kt
@@ -6,4 +6,4 @@ annotation class XXX
@XXX
class UnusedClass
-// FUS_QUICKFIX_NAME: com.intellij.codeInspection.util.SpecialAnnotationsUtil$4
\ No newline at end of file
+// FUS_QUICKFIX_NAME: com.intellij.codeInspection.ex.EntryPointsManagerBase$AddAnnotation
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/quickfix/unusedSuppressAnnotation/simple.kt.after b/plugins/kotlin/idea/tests/testData/quickfix/unusedSuppressAnnotation/simple.kt.after
index 84fc7e573342..ade59f33b6b5 100644
--- a/plugins/kotlin/idea/tests/testData/quickfix/unusedSuppressAnnotation/simple.kt.after
+++ b/plugins/kotlin/idea/tests/testData/quickfix/unusedSuppressAnnotation/simple.kt.after
@@ -6,4 +6,4 @@ annotation class XXX
@XXX
class UnusedClass
-// FUS_QUICKFIX_NAME: com.intellij.codeInspection.util.SpecialAnnotationsUtil$4
\ No newline at end of file
+// FUS_QUICKFIX_NAME: com.intellij.codeInspection.ex.EntryPointsManagerBase$AddAnnotation
\ No newline at end of file