public static boolean mustKeepAnnotations(@NotNull PsiModifierListOwner listOwner, @NotNull Set<String> runtimeAnnotationsToIgnore) {
    PsiModifierList modifierList = listOwner.getModifierList();
    if (modifierList == null) return false;
    PsiAnnotation[] annotations = modifierList.getAnnotations();
    for (PsiAnnotation annotation : annotations) {
      PsiJavaCodeReferenceElement ref = annotation.getNameReferenceElement();
      String fqn;
      if (ref != null &&
          ref.resolve() instanceof PsiClass annotationClass &&
          ((fqn = annotationClass.getQualifiedName()) == null ||
          !runtimeAnnotationsToIgnore.contains(fqn))) {
        final PsiAnnotation retentionAnno = AnnotationUtil.findAnnotation(annotationClass, Retention.class.getName());
        // Default retention is CLASS: keep it
        if (retentionAnno == null) return true;
        if (retentionAnno.findAttributeValue("value") instanceof PsiReferenceExpression retentionValue &&
            retentionValue.resolve() instanceof PsiField retentionField &&
            (RetentionPolicy.RUNTIME.name().equals(retentionField.getName()) ||
             RetentionPolicy.CLASS.name().equals(retentionField.getName()))) {
          final PsiClass containingClass = retentionField.getContainingClass();
          if (containingClass != null && RetentionPolicy.class.getName().equals(containingClass.getQualifiedName())) {
            return true;
          }
        }
      }
    }
    return false;
  }
public static boolean mustKeepAnnotations(@NotNull PsiModifierListOwner listOwner, @NotNull Set<String> runtimeAnnotationsToIgnore)