From 39117a9a23c27b4f5e3347be75cc7fccbfdee175 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 10 Aug 2017 18:14:33 +0300 Subject: [PATCH] When run "annotate all overridden methods", do not balk at stupid groovy or kotlin which plugins are too lazy to implement notnullability. Also, do not highlight "overridden methods not notnulled" for these cases. --- .../intention/AddAnnotationPsiFix.java | 17 +++++++--- .../AnnotateOverriddenMethodParameterFix.java | 32 ++++++++++++------- .../nullable/NullableStuffInspectionBase.java | 30 +++++++++-------- 3 files changed, 49 insertions(+), 30 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/intention/AddAnnotationPsiFix.java b/java/java-analysis-impl/src/com/intellij/codeInsight/intention/AddAnnotationPsiFix.java index f794d051f895..e52eb4049e08 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/intention/AddAnnotationPsiFix.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/intention/AddAnnotationPsiFix.java @@ -27,6 +27,7 @@ import com.intellij.openapi.command.undo.UndoUtil; import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; +import com.intellij.psi.impl.light.LightElement; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.util.ObjectUtils; @@ -109,13 +110,19 @@ public class AddAnnotationPsiFix extends LocalQuickFixOnPsiElement { @NotNull PsiFile file, @NotNull PsiElement startElement, @NotNull PsiElement endElement) { - if (!startElement.isValid()) return false; - if (!PsiUtil.isLanguageLevel5OrHigher(startElement)) return false; - final PsiModifierListOwner myModifierListOwner = (PsiModifierListOwner)startElement; + return isAvailable((PsiModifierListOwner)startElement, myAnnotation); + } + + public static boolean isAvailable(@NotNull PsiModifierListOwner modifierListOwner, @NotNull String annotationFQN) { + if (!modifierListOwner.isValid()) return false; + if (!PsiUtil.isLanguageLevel5OrHigher(modifierListOwner)) return false; // e.g. PsiTypeParameterImpl doesn't have modifier list - return myModifierListOwner.getModifierList() != null - && !AnnotationUtil.isAnnotated(myModifierListOwner, myAnnotation, false, false); + PsiModifierList modifierList = modifierListOwner.getModifierList(); + return modifierList != null + && !(modifierList instanceof LightElement) + && !(modifierListOwner instanceof LightElement) + && !AnnotationUtil.isAnnotated(modifierListOwner, annotationFQN, false, false, true); } @Override diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/AnnotateOverriddenMethodParameterFix.java b/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/AnnotateOverriddenMethodParameterFix.java index caf623fea615..e8f1fec0fc2e 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/AnnotateOverriddenMethodParameterFix.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/AnnotateOverriddenMethodParameterFix.java @@ -22,14 +22,12 @@ import com.intellij.codeInspection.InspectionsBundle; import com.intellij.codeInspection.LocalQuickFix; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiMethod; -import com.intellij.psi.PsiNameValuePair; -import com.intellij.psi.PsiParameter; +import com.intellij.psi.*; import com.intellij.psi.search.searches.OverridingMethodsSearch; import com.intellij.psi.util.ClassUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.ArrayUtilRt; +import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -38,12 +36,12 @@ import java.util.List; /** * @author cdr */ -public class AnnotateOverriddenMethodParameterFix implements LocalQuickFix { +class AnnotateOverriddenMethodParameterFix implements LocalQuickFix { private final String myAnnotation; private final String[] myAnnosToRemove; - public AnnotateOverriddenMethodParameterFix(final String fqn, String... annosToRemove) { - myAnnotation = fqn; + AnnotateOverriddenMethodParameterFix(@NotNull String annotationFQN, @NotNull String... annosToRemove) { + myAnnotation = annotationFQN; myAnnosToRemove = annosToRemove; } @@ -76,17 +74,29 @@ public class AnnotateOverriddenMethodParameterFix implements LocalQuickFix { PsiParameter[] psiParameters = psiMethod.getParameterList().getParameters(); if (index >= psiParameters.length) continue; PsiParameter psiParameter = psiParameters[index]; - if (!AnnotationUtil.isAnnotated(psiParameter, myAnnotation, false, false) && psiMethod.getManager().isInProject(psiMethod)) { + if (PsiManager.getInstance(project).isInProject(psiMethod) && AddAnnotationPsiFix.isAvailable(psiMethod, myAnnotation)) { toAnnotate.add(psiParameter); } } FileModificationService.getInstance().preparePsiElementsForWrite(toAnnotate); + RuntimeException exception = null; for (PsiParameter psiParam : toAnnotate) { assert psiParam != null : toAnnotate; - if (AnnotationUtil.isAnnotatingApplicable(psiParam, myAnnotation)) { - AddAnnotationPsiFix fix = new AddAnnotationPsiFix(myAnnotation, psiParam, PsiNameValuePair.EMPTY_ARRAY, myAnnosToRemove); - fix.invoke(project, psiParam.getContainingFile(), psiParam, psiParam); + try { + if (AnnotationUtil.isAnnotatingApplicable(psiParam, myAnnotation)) { + AddAnnotationPsiFix fix = new AddAnnotationPsiFix(myAnnotation, psiParam, PsiNameValuePair.EMPTY_ARRAY, myAnnosToRemove); + PsiFile containingFile = psiParam.getContainingFile(); + if (fix.isAvailable(project, containingFile, psiParam, psiParam)) { + fix.invoke(project, containingFile, psiParam, psiParam); + } + } + } + catch (PsiInvalidElementAccessException|IncorrectOperationException e) { + exception = e; + } + if (exception != null) { + throw exception; } } } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspectionBase.java index f574b292339d..31db87c104ca 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspectionBase.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspectionBase.java @@ -713,10 +713,10 @@ public class NullableStuffInspectionBase extends BaseJavaBatchLocalInspectionToo } } - private void checkOverriders(PsiMethod method, - ProblemsHolder holder, - Annotated annotated, - NullableNotNullManager nullableManager) { + private void checkOverriders(@NotNull PsiMethod method, + @NotNull ProblemsHolder holder, + @NotNull Annotated annotated, + @NotNull NullableNotNullManager nullableManager) { PsiParameter[] parameters = method.getParameterList().getParameters(); if (REPORT_ANNOTATION_NOT_PROPAGATED_TO_OVERRIDERS) { boolean[] parameterAnnotated = new boolean[parameters.length]; @@ -738,11 +738,13 @@ public class NullableStuffInspectionBase extends BaseJavaBatchLocalInspectionToo if (!manager.isInProject(overriding)) continue; final boolean applicable = AnnotationUtil.isAnnotatingApplicable(overriding, defaultNotNull); + boolean ableToAddNotNullAnnotation = AddAnnotationPsiFix.isAvailable(overriding, defaultNotNull); if (!methodQuickFixSuggested && annotated.isDeclaredNotNull && !isNotNullNotInferred(overriding, false, false) - && (isNullableNotInferred(overriding, false) || !isNullableNotInferred(overriding, true))) { - method.getNameIdentifier(); //load tree + && (isNullableNotInferred(overriding, false) || !isNullableNotInferred(overriding, true)) + && ableToAddNotNullAnnotation) { + PsiIdentifier identifier = method.getNameIdentifier();//load tree PsiAnnotation annotation = AnnotationUtil.findAnnotation(method, nullableManager.getNotNulls()); final String[] annotationsToRemove = ArrayUtil.toStringArray(nullableManager.getNullables()); @@ -756,7 +758,7 @@ public class NullableStuffInspectionBase extends BaseJavaBatchLocalInspectionToo PsiElement psiElement = annotation; if (!annotation.isPhysical()) { - psiElement = method.getNameIdentifier(); + psiElement = identifier; if (psiElement == null) continue; } holder.registerProblem(psiElement, InspectionsBundle.message("nullable.stuff.problems.overridden.methods.are.not.annotated"), @@ -764,26 +766,26 @@ public class NullableStuffInspectionBase extends BaseJavaBatchLocalInspectionToo fix); methodQuickFixSuggested = true; } - if (hasAnnotatedParameter) { + if (hasAnnotatedParameter && ableToAddNotNullAnnotation) { PsiParameter[] psiParameters = overriding.getParameterList().getParameters(); for (int i = 0; i < psiParameters.length; i++) { if (parameterQuickFixSuggested[i]) continue; PsiParameter parameter = psiParameters[i]; if (parameterAnnotated[i] && !isNotNullNotInferred(parameter, false, false) && !isNullableNotInferred(parameter, false)) { - parameters[i].getNameIdentifier(); //be sure that corresponding tree element available + PsiIdentifier identifier = parameters[i].getNameIdentifier(); //be sure that corresponding tree element available PsiAnnotation annotation = AnnotationUtil.findAnnotation(parameters[i], nullableManager.getNotNulls()); PsiElement psiElement = annotation; if (annotation == null || !annotation.isPhysical()) { - psiElement = parameters[i].getNameIdentifier(); + psiElement = identifier; if (psiElement == null) continue; } holder.registerProblem(psiElement, InspectionsBundle.message("nullable.stuff.problems.overridden.method.parameters.are.not.annotated"), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, !applicable - ? createChangeDefaultNotNullFix(nullableManager, parameters[i]) - : new AnnotateOverriddenMethodParameterFix(defaultNotNull, - nullableManager.getDefaultNullable())); + ? createChangeDefaultNotNullFix(nullableManager, parameters[i]) + : new AnnotateOverriddenMethodParameterFix(defaultNotNull, + nullableManager.getDefaultNullable())); parameterQuickFixSuggested[i] = true; } } @@ -824,7 +826,7 @@ public class NullableStuffInspectionBase extends BaseJavaBatchLocalInspectionToo return null; } - private AddAnnotationPsiFix createAnnotateMethodFix(String defaultNotNull, String[] annotationsToRemove, PsiMethod method) { + private static AddAnnotationPsiFix createAnnotateMethodFix(String defaultNotNull, String[] annotationsToRemove, PsiMethod method) { return new AddAnnotationPsiFix(defaultNotNull, method, PsiNameValuePair.EMPTY_ARRAY, annotationsToRemove); }