[java-inspections] Properly report 'not applicable on locals' warnings

IDEA-355699 Warning when annotating array elements as nullable with JSpecify

GitOrigin-RevId: ca9a3e0ea2ef3aa01d31afcaff2f92193af14dbe
This commit is contained in:
Tagir Valeev
2024-09-25 10:51:33 +02:00
committed by intellij-monorepo-bot
parent 3efab5750c
commit ca9649997b
3 changed files with 54 additions and 23 deletions

View File

@@ -164,25 +164,25 @@ public class NullableStuffInspectionBase extends AbstractBaseJavaLocalInspection
@Override
public void visitAnnotation(@NotNull PsiAnnotation annotation) {
String qualifiedName = annotation.getQualifiedName();
if (qualifiedName == null) return;
Optional<Nullability> nullabilityOptional = manager.getAnnotationNullability(qualifiedName);
if (nullabilityOptional.isEmpty()) return;
Nullability nullability = nullabilityOptional.get();
PsiType type = AnnotationUtil.getRelatedType(annotation);
PsiAnnotationOwner owner = annotation.getOwner();
PsiModifierListOwner listOwner = owner instanceof PsiModifierList
? tryCast(((PsiModifierList)owner).getParent(), PsiModifierListOwner.class) : null;
PsiModifierListOwner listOwner = owner instanceof PsiModifierList modifierList
? tryCast(modifierList.getParent(), PsiModifierListOwner.class) : null;
PsiType targetType = listOwner instanceof PsiMethod method ? method.getReturnType() :
listOwner instanceof PsiVariable variable ? variable.getType() : null;
if (type instanceof PsiPrimitiveType) {
PsiType targetType = listOwner instanceof PsiMethod
? ((PsiMethod)listOwner).getReturnType()
: listOwner instanceof PsiVariable ? ((PsiVariable)listOwner).getType() : null;
LocalQuickFix additionalFix = null;
if (targetType instanceof PsiArrayType && targetType.getAnnotations().length == 0) {
additionalFix = new MoveAnnotationToArrayFix();
}
reportIncorrectLocation(holder, annotation, listOwner, "inspection.nullable.problems.primitive.type.annotation", LocalQuickFix.notNullElements(additionalFix));
}
if (type instanceof PsiClassType) {
PsiElement context = ((PsiClassType)type).getPsiContext();
if (type instanceof PsiClassType classType) {
PsiElement context = classType.getPsiContext();
// outer type/package
if (context instanceof PsiJavaCodeReferenceElement outerCtx) {
PsiElement parent = context.getParent();
@@ -208,16 +208,18 @@ public class NullableStuffInspectionBase extends AbstractBaseJavaLocalInspection
}
}
}
if (listOwner instanceof PsiMethod && ((PsiMethod)listOwner).isConstructor()) {
if (type instanceof PsiArrayType && annotation.getParent() instanceof PsiTypeElement parent &&
parent.getType().equals(type) && !manager.canAnnotateLocals(qualifiedName)) {
checkIllegalLocalAnnotation(annotation, parent.getParent());
}
if (listOwner instanceof PsiMethod method && method.isConstructor()) {
reportIncorrectLocation(holder, annotation, listOwner, "inspection.nullable.problems.at.constructor");
}
if (listOwner instanceof PsiEnumConstant) {
reportIncorrectLocation(holder, annotation, listOwner, "inspection.nullable.problems.at.enum.constant");
}
if ((listOwner instanceof PsiLocalVariable ||
listOwner instanceof PsiParameter && ((PsiParameter)listOwner).getDeclarationScope() instanceof PsiCatchSection)
&& !manager.canAnnotateLocals(qualifiedName)) {
reportIncorrectLocation(holder, annotation, listOwner, "inspection.nullable.problems.at.local.variable");
if (!manager.canAnnotateLocals(qualifiedName) && !(targetType instanceof PsiArrayType)) {
checkIllegalLocalAnnotation(annotation, listOwner);
}
if (type instanceof PsiWildcardType && manager.isTypeUseAnnotationLocationRestricted(qualifiedName)) {
reportIncorrectLocation(holder, annotation, listOwner, "inspection.nullable.problems.at.wildcard");
@@ -231,8 +233,8 @@ public class NullableStuffInspectionBase extends AbstractBaseJavaLocalInspection
checkOppositeAnnotationConflict(annotation, nullability);
if (AnnotationUtil.NOT_NULL.equals(qualifiedName)) {
PsiAnnotationMemberValue value = annotation.findDeclaredAttributeValue("exception");
if (value instanceof PsiClassObjectAccessExpression) {
PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(((PsiClassObjectAccessExpression)value).getOperand().getType());
if (value instanceof PsiClassObjectAccessExpression classObjectAccessExpression) {
PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(classObjectAccessExpression.getOperand().getType());
if (psiClass != null && !hasStringConstructor(psiClass)) {
reportProblem(holder, value, "custom.exception.class.should.have.a.constructor");
}
@@ -240,6 +242,14 @@ public class NullableStuffInspectionBase extends AbstractBaseJavaLocalInspection
}
}
private void checkIllegalLocalAnnotation(@NotNull PsiAnnotation annotation, @Nullable PsiElement owner) {
if (owner instanceof PsiLocalVariable ||
owner instanceof PsiParameter parameter &&
parameter.getDeclarationScope() instanceof PsiCatchSection) {
reportIncorrectLocation(holder, annotation, (PsiVariable)owner, "inspection.nullable.problems.at.local.variable");
}
}
private void checkOppositeAnnotationConflict(PsiAnnotation annotation, Nullability nullability) {
PsiAnnotationOwner owner = annotation.getOwner();
if (owner == null) return;