[mod-command] NullableNotNullManagerImpl: OptionController; used in ChangeNullableDefaultsFix

GitOrigin-RevId: 66d6128248cd06e81cb3ec7826265ea4a23b7dbf
This commit is contained in:
Tagir Valeev
2023-11-13 15:41:43 +01:00
committed by intellij-monorepo-bot
parent 4143fe4c0a
commit 17a223b66d
5 changed files with 78 additions and 36 deletions

View File

@@ -366,7 +366,6 @@ inspection.visibility.private.inner.members=Suggest 'private' for inner class me
instance.member.guarded.by.static.0.loc=Instance member guarded by static "{0}" #loc
instance.member.guarded.by.static.ref.loc=Instance member guarded by static #ref #loc
make.0.default.annotation=Make "{0}" default annotation
make.0.default.annotation.preview=Changes the default nullability annotation which is used for code generation.
make.default.the.last.case.family.name=Make 'default' the last case
make.final.and.annotate.as.safevarargs=Make final and annotate as '@SafeVarargs'
method.reference.mapped.to.comparator=Method reference mapped to 'Comparator' interface does not fulfill the 'Comparator' contract

View File

@@ -332,5 +332,6 @@
<projectService serviceInterface="com.intellij.java.analysis.OuterModelsModificationTrackerManager"
serviceImplementation="com.intellij.lang.OuterModelsModificationTrackerManagerImpl"/>
<optionController implementation="com.intellij.codeInspection.ex.EntryPointsManagerBase$Provider"/>
<optionController implementation="com.intellij.codeInsight.NullableNotNullManagerImpl$Provider"/>
</extensions>
</idea-plugin>

View File

@@ -15,32 +15,30 @@
*/
package com.intellij.codeInspection.nullable;
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.codeInsight.intention.preview.IntentionPreviewInfo;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.java.analysis.JavaAnalysisBundle;
import com.intellij.modcommand.ModCommand;
import com.intellij.modcommand.ModCommandQuickFix;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiAnnotation;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
class ChangeNullableDefaultsFix implements LocalQuickFix {
private final NullableNotNullManager myManager;
import static com.intellij.modcommand.ModCommand.nop;
import static com.intellij.modcommand.ModCommand.updateOption;
class ChangeNullableDefaultsFix extends ModCommandQuickFix {
private final String myNotNullName;
private final String myNullableName;
ChangeNullableDefaultsFix(@Nullable PsiAnnotation notNull, @Nullable PsiAnnotation nullable, @NotNull NullableNotNullManager manager) {
ChangeNullableDefaultsFix(@Nullable PsiAnnotation notNull, @Nullable PsiAnnotation nullable) {
myNotNullName = notNull != null ? notNull.getQualifiedName() : null;
myNullableName = nullable != null ? nullable.getQualifiedName() : null;
myManager = manager;
}
ChangeNullableDefaultsFix(String notNull, String nullable, NullableNotNullManager manager) {
myManager = manager;
ChangeNullableDefaultsFix(String notNull, String nullable) {
myNotNullName = notNull;
myNullableName = nullable;
}
@@ -52,30 +50,30 @@ class ChangeNullableDefaultsFix implements LocalQuickFix {
}
@Override
public boolean startInWriteAction() {
return false;
}
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
public @NotNull ModCommand perform(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
ModCommand command = nop();
if (myNotNullName != null) {
List<String> notNulls = myManager.getNotNulls();
if (!notNulls.contains(myNotNullName)) {
myManager.setNotNulls(ArrayUtil.append(ArrayUtil.toStringArray(notNulls), myNotNullName));
}
myManager.setDefaultNotNull(myNotNullName);
command = command.andThen(
updateOption(descriptor.getPsiElement(), "NullableNotNullManager.myNotNulls", old -> {
@SuppressWarnings("unchecked") List<String> list = (List<String>)old;
if (!list.contains(myNotNullName)) {
list.add(myNotNullName);
}
return list;
})).andThen(
updateOption(descriptor.getPsiElement(), "NullableNotNullManager.myDefaultNotNull", old -> myNotNullName));
}
else {
List<String> nullables = myManager.getNullables();
if (!nullables.contains(myNullableName)) {
myManager.setNullables(ArrayUtil.append(ArrayUtil.toStringArray(nullables), myNullableName));
}
myManager.setDefaultNullable(myNullableName);
command = command.andThen(
updateOption(descriptor.getPsiElement(), "NullableNotNullManager.myNullables", old -> {
@SuppressWarnings("unchecked") List<String> list = (List<String>)old;
if (!list.contains(myNullableName)) {
list.add(myNullableName);
}
return list;
})).andThen(
updateOption(descriptor.getPsiElement(), "NullableNotNullManager.myDefaultNullable", old -> myNotNullName));
}
}
@Override
public @NotNull IntentionPreviewInfo generatePreview(@NotNull Project project, @NotNull ProblemDescriptor previewDescriptor) {
return new IntentionPreviewInfo.Html(JavaAnalysisBundle.message("make.0.default.annotation.preview"));
return command;
}
}

View File

@@ -140,7 +140,7 @@ public class NullableStuffInspectionBase extends AbstractBaseJavaLocalInspection
final String anno = annotated.isDeclaredNotNull ? manager.getDefaultNotNull() : manager.getDefaultNullable();
final List<String> annoToRemove = annotated.isDeclaredNotNull ? nullables : notNulls;
if (!checkNonStandardAnnotations(field, annotated, manager, anno, holder)) return;
if (!checkNonStandardAnnotations(field, annotated, anno, holder)) return;
checkAccessors(field, annotated, project, manager, anno, annoToRemove, holder);
@@ -508,7 +508,7 @@ public class NullableStuffInspectionBase extends AbstractBaseJavaLocalInspection
private static boolean checkNonStandardAnnotations(PsiField field,
Annotated annotated,
NullableNotNullManager manager, String anno, @NotNull ProblemsHolder holder) {
String anno, @NotNull ProblemsHolder holder) {
if (!AnnotationUtil.isAnnotatingApplicable(field, anno)) {
PsiAnnotation annotation = Objects.requireNonNull(annotated.isDeclaredNullable ? annotated.nullable : annotated.notNull);
String message = JavaAnalysisBundle.message("inspection.message.code.generation.different.nullability.annotation.will.be.used",
@@ -517,7 +517,7 @@ public class NullableStuffInspectionBase extends AbstractBaseJavaLocalInspection
holder.registerProblem(annotationNameReferenceElement != null && annotationNameReferenceElement.isPhysical() ? annotationNameReferenceElement : field.getNameIdentifier(),
message,
ProblemHighlightType.WEAK_WARNING,
new ChangeNullableDefaultsFix(annotated.notNull, annotated.nullable, manager));
new ChangeNullableDefaultsFix(annotated.notNull, annotated.nullable));
return false;
}
return true;
@@ -1064,7 +1064,7 @@ public class NullableStuffInspectionBase extends AbstractBaseJavaLocalInspection
if (resolveResult.getElement() != null &&
resolveResult.isValidResult() &&
!nullableManager.getDefaultNotNull().equals(annotation.getQualifiedName())) {
return new ChangeNullableDefaultsFix(annotation.getQualifiedName(), null, nullableManager);
return new ChangeNullableDefaultsFix(annotation.getQualifiedName(), null);
}
}
}

View File

@@ -4,10 +4,14 @@ package com.intellij.codeInsight;
import com.intellij.codeInsight.annoPackages.AnnotationPackageSupport;
import com.intellij.codeInsight.annoPackages.Jsr305Support;
import com.intellij.codeInsight.daemon.impl.analysis.JavaModuleGraphUtil;
import com.intellij.codeInsight.options.JavaClassValidator;
import com.intellij.codeInspection.dataFlow.HardcodedContracts;
import com.intellij.codeInspection.options.OptionController;
import com.intellij.codeInspection.options.OptionControllerProvider;
import com.intellij.ide.highlighter.JavaFileType;
import com.intellij.ide.plugins.DynamicPluginListener;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
import com.intellij.java.JavaBundle;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.State;
import com.intellij.openapi.fileTypes.FileTypeRegistry;
@@ -17,6 +21,7 @@ import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.profile.codeInspection.ProjectInspectionProfileManager;
import com.intellij.psi.*;
import com.intellij.psi.impl.java.stubs.index.JavaAnnotationIndex;
import com.intellij.psi.search.DelegatingGlobalSearchScope;
@@ -36,6 +41,7 @@ import java.util.function.Function;
import static com.intellij.codeInsight.AnnotationUtil.NOT_NULL;
import static com.intellij.codeInsight.AnnotationUtil.NULLABLE;
import static com.intellij.codeInspection.options.OptPane.*;
@State(name = "NullableNotNullManager")
public class NullableNotNullManagerImpl extends NullableNotNullManager implements PersistentStateComponent<Element>, ModificationTracker {
@@ -424,4 +430,42 @@ public class NullableNotNullManagerImpl extends NullableNotNullManager implement
}
return null;
}
public @NotNull OptionController getOptionController() {
return OptionController.fieldsOf(this)
.withRootPane(() -> pane(
tabs(
tab(NullableNotNullDialog.NULLABLE,
string("myDefaultNullable", JavaBundle.message("nullable.notnull.annotation.used.label")),
stringList("myNullables", JavaBundle.message("nullable.notnull.annotations.panel.title", "Nullable"),
new JavaClassValidator().annotationsOnly())),
tab(NullableNotNullDialog.NOT_NULL,
string("myDefaultNotNull", JavaBundle.message("nullable.notnull.annotation.used.label")),
stringList("myNotNulls", JavaBundle.message("nullable.notnull.annotations.panel.title", "NotNull"),
new JavaClassValidator().annotationsOnly())
))));
}
/**
* Provides options to setup nullability annotations:
* <ul>
* <li>NullableNotNullManager.myNullables - list of nullable annotation fqns</li>
* <li>NullableNotNullManager.myNotNulls - list of notnull annotation fqns</li>
* <li>NullableNotNullManager.myDefaultNullable - default nullable annotation fqn</li>
* <li>NullableNotNullManager.myDefaultNotNull - default notnull annotation fqn</li>
* </ul>
*/
public static class Provider implements OptionControllerProvider {
@Override
public @NotNull OptionController forContext(@NotNull PsiElement context) {
Project project = context.getProject();
return ((NullableNotNullManagerImpl)getInstance(project)).getOptionController()
.onValueSet((bindId, value) -> ProjectInspectionProfileManager.getInstance(project).fireProfileChanged());
}
@Override
public @NotNull String name() {
return "NullableNotNullManager";
}
}
}