@Override
      public void visitAnnotation(@NotNull PsiAnnotation annotation) {
        String qualifiedName = annotation.getQualifiedName();
        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;
        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();
          // outer type/package
          if (context instanceof PsiJavaCodeReferenceElement outerCtx) {
            PsiElement parent = context.getParent();
            if (parent instanceof PsiJavaCodeReferenceElement) {
              if (outerCtx.resolve() instanceof PsiPackage) {
                ModCommandAction action = new MoveAnnotationOnStaticMemberQualifyingTypeFix(annotation);
                reportIncorrectLocation(holder, annotation, listOwner, "inspection.nullable.problems.applied.to.package",
                                        LocalQuickFix.from(action));
              }
              else {
                ModCommandAction action = new MoveAnnotationOnStaticMemberQualifyingTypeFix(annotation);
                reportIncorrectLocation(holder, annotation, listOwner, "inspection.nullable.problems.outer.type",
                                        LocalQuickFix.from(action));
              }
            }
            if (parent instanceof PsiReferenceList) {
              PsiElement firstChild = parent.getFirstChild();
              if ((PsiUtil.isJavaToken(firstChild, JavaTokenType.EXTENDS_KEYWORD) ||
                   PsiUtil.isJavaToken(firstChild, JavaTokenType.IMPLEMENTS_KEYWORD)) &&
                  !(parent.getParent() instanceof PsiTypeParameter)) {
                reportIncorrectLocation(holder, annotation, listOwner, "inspection.nullable.problems.at.reference.list");
              }
            }
          }
        }
        if (listOwner instanceof PsiMethod && ((PsiMethod)listOwner).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 (type instanceof PsiWildcardType && manager.isTypeUseAnnotationLocationRestricted(qualifiedName)) {
          reportIncorrectLocation(holder, annotation, listOwner, "inspection.nullable.problems.at.wildcard");
        }
        if (owner instanceof PsiTypeParameter && manager.isTypeUseAnnotationLocationRestricted(qualifiedName)) {
          reportIncorrectLocation(holder, annotation, listOwner, "inspection.nullable.problems.at.type.parameter");
        }
        if (listOwner instanceof PsiReceiverParameter && nullability != Nullability.NOT_NULL) {
          reportIncorrectLocation(holder, annotation, listOwner, "inspection.nullable.problems.receiver.annotation");
        }
        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 (psiClass != null && !hasStringConstructor(psiClass)) {
              reportProblem(holder, value, "custom.exception.class.should.have.a.constructor");
            }
          }
        }
      }
@Override
      public void visitAnnotation(@NotNull PsiAnnotation annotation)