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.
This commit is contained in:
Alexey Kudravtsev
2017-08-10 18:16:46 +03:00
parent 0c90c6040f
commit 39117a9a23
3 changed files with 49 additions and 30 deletions
@@ -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
@@ -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;
}
}
}
@@ -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);
}