private static boolean isSuperEventListenerAllowed(
     PsiClass eventClass, PsiMethod method, MinecraftModule module) {
   final PsiClass[] supers = eventClass.getSupers();
   for (PsiClass aSuper : supers) {
     if (module.isEventClassValid(aSuper, method)) {
       return true;
     }
     if (isSuperEventListenerAllowed(aSuper, method, module)) {
       return true;
     }
   }
   return false;
 }
  private static boolean isValidInContext(@NotNull PsiElement element) {
    if (!(element instanceof PsiMethod)) {
      return false;
    }

    final Module module = ModuleUtilCore.findModuleForPsiElement(element);
    if (module == null) {
      return false;
    }

    final MinecraftModule minecraftModule = MinecraftModule.getInstance(module);
    if (minecraftModule == null) {
      return false;
    }

    if (!minecraftModule.isOfType(MixinModuleType.getInstance())) {
      return false;
    }

    final PsiMethod method = (PsiMethod) element;

    return AuthorInspection.shouldHaveAuthorTag(method);
  }
  @Override
  public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
    if (!MinecraftSettings.Companion.getInstance().isShowEventListenerGutterIcons()) {
      return;
    }

    // Since we want to line up with the method declaration, not the annotation
    // declaration, we need to target identifiers, not just PsiMethods.
    if (!(element instanceof PsiIdentifier && (element.getParent() instanceof PsiMethod))) {
      return;
    }
    // The PsiIdentifier is going to be a method of course!
    PsiMethod method = (PsiMethod) element.getParent();
    if (method.hasModifierProperty(PsiModifier.ABSTRACT)) {
      // I don't think any implementation allows for abstract
      return;
    }
    PsiModifierList modifierList = method.getModifierList();
    Module module = ModuleUtilCore.findModuleForPsiElement(element);
    if (module == null) {
      return;
    }
    MinecraftModule instance = MinecraftModule.getInstance(module);
    if (instance == null) {
      return;
    }
    // Since each platform has their own valid listener annotations,
    // some platforms may have multiple allowed annotations for various cases
    final Collection<AbstractModuleType<?>> moduleTypes = instance.getTypes();
    boolean contains = false;
    for (AbstractModuleType<?> moduleType : moduleTypes) {
      final List<String> listenerAnnotations = moduleType.getListenerAnnotations();
      for (String listenerAnnotation : listenerAnnotations) {
        if (modifierList.findAnnotation(listenerAnnotation) != null) {
          contains = true;
          break;
        }
      }
    }
    if (!contains) {
      return;
    }

    final PsiParameter[] parameters = method.getParameterList().getParameters();
    if (parameters.length < 1) {
      return;
    }
    final PsiParameter eventParameter = parameters[0];
    if (eventParameter == null) {
      // Listeners must have at least a single parameter
      return;
    }
    // Get the type of the parameter so we can start resolving it
    PsiTypeElement psiEventElement = eventParameter.getTypeElement();
    if (psiEventElement == null) {
      return;
    }
    final PsiType type = psiEventElement.getType();
    // Validate that it is a class reference type, I don't know if this will work with
    // other JVM languages such as Kotlin or Scala, but it might!
    if (!(type instanceof PsiClassReferenceType)) {
      return;
    }
    // And again, make sure that we can at least resolve the type, otherwise it's not a valid
    // class reference.
    final PsiClass eventClass = ((PsiClassReferenceType) type).resolve();
    if (eventClass == null) {
      return;
    }

    if (instance.isEventClassValid(eventClass, method)) {
      return;
    }

    if (!instance.isStaticListenerSupported(eventClass, method)
        && method.hasModifierProperty(PsiModifier.STATIC)) {
      if (method.getNameIdentifier() != null) {
        holder.createErrorAnnotation(
            method.getNameIdentifier(), "Event listener method must not be static");
      }
    }

    if (!isSuperEventListenerAllowed(eventClass, method, instance)) {
      holder.createErrorAnnotation(
          eventParameter, instance.writeErrorMessageForEvent(eventClass, method));
    }
  }