From e3c16dc16d12c9a920c798aec9b590a513e873cf Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Sun, 6 Apr 2025 17:10:17 +0800 Subject: [PATCH] Add support for getting annotation from parent class/method/parameter --- .../java/co/aikar/commands/Annotations.java | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/core/src/main/java/co/aikar/commands/Annotations.java b/core/src/main/java/co/aikar/commands/Annotations.java index 8a14724c..f0f80ae7 100644 --- a/core/src/main/java/co/aikar/commands/Annotations.java +++ b/core/src/main/java/co/aikar/commands/Annotations.java @@ -27,6 +27,8 @@ import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.lang.reflect.Parameter; +import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.IdentityHashMap; @@ -52,6 +54,16 @@ class Annotations extends AnnotationLookups { String getAnnotationValue(AnnotatedElement object, Class annoClass, int options) { Annotation annotation = getAnnotationRecursive(object, annoClass, new HashSet<>()); + if (annotation == null) { + if (object instanceof Class) { + annotation = getAnnotationFromParentClasses((Class) object, annoClass); + } else if (object instanceof Method) { + annotation = getAnnotationFromParentMethods((Method) object, annoClass); + } else if (object instanceof Parameter) { + annotation = getAnnotationFromParameters((Parameter) object, annoClass); + } + } + String value = null; if (annotation != null) { @@ -104,6 +116,60 @@ class Annotations extends AnnotationLookups { return value; } + private static Annotation getAnnotationFromParentClasses(Class clazz, Class annoClass) { + Class parent = clazz.getSuperclass(); + while (parent != null && !parent.equals(BaseCommand.class) && !parent.equals(Object.class)) { + Annotation annotation = getAnnotationRecursive(parent, annoClass, new HashSet<>()); + if (annotation != null) { + return annotation; + } + parent = parent.getSuperclass(); + } + return null; + } + + private static Annotation getAnnotationFromParentMethods(Method method, Class annoClass) { + Class clazz = method.getDeclaringClass().getSuperclass(); + while (clazz != null && !clazz.equals(BaseCommand.class) && !clazz.equals(Object.class)) { + try { + Method parentMethod = clazz.getDeclaredMethod(method.getName(), method.getParameterTypes()); + Annotation parentAnnotation = getAnnotationRecursive(parentMethod, annoClass, new HashSet<>()); + if (parentAnnotation != null) { + return parentAnnotation; + } + } catch (NoSuchMethodException e) { + // No parent method + return null; + } + clazz = clazz.getSuperclass(); + } + + return null; + } + + private static Annotation getAnnotationFromParameters(Parameter parameter, Class annoClass) { + Class clazz = parameter.getDeclaringExecutable().getDeclaringClass().getSuperclass(); + while (clazz != null && !clazz.equals(BaseCommand.class) && !clazz.equals(Object.class)) { + try { + Method parentMethod = clazz.getDeclaredMethod(parameter.getDeclaringExecutable().getName(), parameter.getDeclaringExecutable().getParameterTypes()); + Annotation parentAnnotation = Arrays.stream(parentMethod.getParameters()) + .filter(parentParameter -> parentParameter.getName().equals(parameter.getName()) + && parentParameter.getType().equals(parameter.getType())) + .findFirst() + .map(parentParameter -> getAnnotationRecursive(parentParameter, annoClass, new HashSet<>())) + .orElse(null); + if (parentAnnotation != null) { + return parentAnnotation; + } + } catch (NoSuchMethodException e) { + // No parent method + return null; + } + clazz = clazz.getSuperclass(); + } + return null; + } + private static Annotation getAnnotationRecursive(AnnotatedElement object, Class annoClass, Collection checked) { if (object.isAnnotationPresent(annoClass)) { return object.getAnnotation(annoClass);