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); }