diff --git a/src/main/java/io/github/classgraph/AnnotationInfoList.java b/src/main/java/io/github/classgraph/AnnotationInfoList.java index 03b60fb5b..0bc31c421 100644 --- a/src/main/java/io/github/classgraph/AnnotationInfoList.java +++ b/src/main/java/io/github/classgraph/AnnotationInfoList.java @@ -28,6 +28,7 @@ */ package io.github.classgraph; +import java.lang.annotation.Annotation; import java.lang.annotation.Repeatable; import java.util.ArrayList; import java.util.HashSet; @@ -36,6 +37,7 @@ import java.util.Set; import io.github.classgraph.ClassInfo.RelType; +import nonapi.io.github.classgraph.utils.Assert; import nonapi.io.github.classgraph.utils.CollectionUtils; import nonapi.io.github.classgraph.utils.LogNode; @@ -344,6 +346,17 @@ public AnnotationInfoList directOnly() { // ------------------------------------------------------------------------------------------------------------- + /** + * Get the {@link Repeatable} annotation with the given class, or the empty list if none found. + * + * @param annotationClass The class to search for. + * @return The list of annotations with the given class, or the empty list if none found. + */ + public AnnotationInfoList getRepeatable(final Class extends Annotation> annotationClass) { + Assert.isAnnotation(annotationClass); + return getRepeatable(annotationClass.getName()); + } + /** * Get the {@link Repeatable} annotation with the given name, or the empty list if none found. * diff --git a/src/main/java/io/github/classgraph/ClassInfo.java b/src/main/java/io/github/classgraph/ClassInfo.java index bd71f11bc..fc6c7ae53 100644 --- a/src/main/java/io/github/classgraph/ClassInfo.java +++ b/src/main/java/io/github/classgraph/ClassInfo.java @@ -29,6 +29,7 @@ package io.github.classgraph; import java.io.File; +import java.lang.annotation.Annotation; import java.lang.annotation.Inherited; import java.lang.annotation.Repeatable; import java.lang.reflect.Modifier; @@ -56,6 +57,7 @@ import nonapi.io.github.classgraph.types.Parser; import nonapi.io.github.classgraph.types.TypeUtils; import nonapi.io.github.classgraph.types.TypeUtils.ModifierType; +import nonapi.io.github.classgraph.utils.Assert; import nonapi.io.github.classgraph.utils.LogNode; /** Holds metadata about a class encountered during a scan. */ @@ -1291,6 +1293,16 @@ public boolean isArrayClass() { return this instanceof ArrayClassInfo; } + /** + * Checks if this class extends the superclass. + * + * @param superclass A superclass. + * @return true if this class extends the superclass. + */ + public boolean extendsSuperclass(final Class> superclass) { + return extendsSuperclass(superclass.getName()); + } + /** * Checks if this class extends the named superclass. * @@ -1348,6 +1360,17 @@ public boolean isImplementedInterface() { return relatedClasses.get(RelType.CLASSES_IMPLEMENTING) != null || isInterface(); } + /** + * Checks whether this class implements the interface. + * + * @param interfaceClazz An interface. + * @return true if this class implements the interface. + */ + public boolean implementsInterface(final Class> interfaceClazz) { + Assert.isInterface(interfaceClazz); + return implementsInterface(interfaceClazz.getName()); + } + /** * Checks whether this class implements the named interface. * @@ -1359,6 +1382,17 @@ public boolean implementsInterface(final String interfaceName) { return getInterfaces().containsName(interfaceName); } + /** + * Checks whether this class has the annotation. + * + * @param annotation An annotation. + * @return true if this class has the annotation. + */ + public boolean hasAnnotation(final Class extends Annotation> annotation) { + Assert.isAnnotation(annotation); + return hasAnnotation(annotation.getName()); + } + /** * Checks whether this class has the named annotation. * @@ -1397,6 +1431,17 @@ public boolean hasField(final String fieldName) { return false; } + /** + * Checks whether this class declares a field with the annotation. + * + * @param annotation A field annotation. + * @return true if this class declares a field with the annotation. + */ + public boolean hasDeclaredFieldAnnotation(final Class extends Annotation> annotation) { + Assert.isAnnotation(annotation); + return hasDeclaredFieldAnnotation(annotation.getName()); + } + /** * Checks whether this class declares a field with the named annotation. * @@ -1413,6 +1458,17 @@ public boolean hasDeclaredFieldAnnotation(final String fieldAnnotationName) { return false; } + /** + * Checks whether this class or one of its superclasses declares a field with the annotation. + * + * @param fieldAnnotation A field annotation. + * @return true if this class or one of its superclasses declares a field with the annotation. + */ + public boolean hasFieldAnnotation(final Class extends Annotation> fieldAnnotation) { + Assert.isAnnotation(fieldAnnotation); + return hasFieldAnnotation(fieldAnnotation.getName()); + } + /** * Checks whether this class or one of its superclasses declares a field with the named annotation. * @@ -1456,6 +1512,17 @@ public boolean hasMethod(final String methodName) { return false; } + /** + * Checks whether this class declares a method with the annotation. + * + * @param methodAnnotation A method annotation. + * @return true if this class declares a method with the annotation. + */ + public boolean hasDeclaredMethodAnnotation(final Class extends Annotation> methodAnnotation) { + Assert.isAnnotation(methodAnnotation); + return hasDeclaredMethodAnnotation(methodAnnotation.getName()); + } + /** * Checks whether this class declares a method with the named annotation. * @@ -1472,6 +1539,19 @@ public boolean hasDeclaredMethodAnnotation(final String methodAnnotationName) { return false; } + /** + * Checks whether this class or one of its superclasses or interfaces declares a method with the + * annotation. + * + * @param methodAnnotation A method annotation. + * @return true if this class or one of its superclasses or interfaces declares a method with the + * annotation. + */ + public boolean hasMethodAnnotation(final Class extends Annotation> methodAnnotation) { + Assert.isAnnotation(methodAnnotation); + return hasMethodAnnotation(methodAnnotation.getName()); + } + /** * Checks whether this class or one of its superclasses or interfaces declares a method with the named * annotation. @@ -1490,6 +1570,17 @@ public boolean hasMethodAnnotation(final String methodAnnotationName) { return false; } + /** + * Checks whether this class declares a method with the annotation. + * + * @param methodParameterAnnotation A method annotation. + * @return true if this class declares a method with the annotation. + */ + public boolean hasDeclaredMethodParameterAnnotation(final Class extends Annotation> methodParameterAnnotation) { + Assert.isAnnotation(methodParameterAnnotation); + return hasDeclaredMethodParameterAnnotation(methodParameterAnnotation.getName()); + } + /** * Checks whether this class declares a method with the named annotation. * @@ -1506,6 +1597,17 @@ public boolean hasDeclaredMethodParameterAnnotation(final String methodParameter return false; } + /** + * Checks whether this class or one of its superclasses or interfaces has a method with the annotation. + * + * @param methodParameterAnnotation A method annotation. + * @return true if this class or one of its superclasses or interfaces has a method with the annotation. + */ + public boolean hasMethodParameterAnnotation(final Class extends Annotation> methodParameterAnnotation) { + Assert.isAnnotation(methodParameterAnnotation); + return hasMethodParameterAnnotation(methodParameterAnnotation.getName()); + } + /** * Checks whether this class or one of its superclasses or interfaces has a method with the named annotation. * @@ -1837,7 +1939,7 @@ public AnnotationInfoList getAnnotationInfo() { } /** - * Get a the named non-{@link Repeatable} annotation on this class, or null if the class does not have the named + * Get a the non-{@link Repeatable} annotation on this class, or null if the class does not have the * annotation. (Use {@link #getAnnotationInfoRepeatable(String)} for {@link Repeatable} annotations.) * *
@@ -1845,10 +1947,33 @@ public AnnotationInfoList getAnnotationInfo() { * its subclasses. * *
+ * Note that if you need to get multiple annotations, it is faster to call {@link #getAnnotationInfo()}, + * and then get the annotations from the returned {@link AnnotationInfoList}, so that the returned list + * doesn't have to be built multiple times. + * + * @param annotation + * The annotation. + * @return An {@link AnnotationInfo} object representing the annotation on this class, or null if the + * class does not have the annotation. + */ + public AnnotationInfo getAnnotationInfo(final Class extends Annotation> annotation) { + Assert.isAnnotation(annotation); + return getAnnotationInfo(annotation.getName()); + } + + /** + * Get a the named non-{@link Repeatable} annotation on this class, or null if the class does not have the named + * annotation. (Use {@link #getAnnotationInfoRepeatable(String)} for {@link Repeatable} annotations.) + * + *
+ * Also handles the {@link Inherited} meta-annotation, which causes an annotation to annotate a class and all of + * its subclasses. + * + *
* Note that if you need to get multiple named annotations, it is faster to call {@link #getAnnotationInfo()}, * and then get the named annotations from the returned {@link AnnotationInfoList}, so that the returned list * doesn't have to be built multiple times. - * + * * @param annotationName * The annotation name. * @return An {@link AnnotationInfo} object representing the named annotation on this class, or null if the @@ -1859,18 +1984,41 @@ public AnnotationInfo getAnnotationInfo(final String annotationName) { } /** - * Get a the named {@link Repeatable} annotation on this class, or the empty list if the class does not have the - * named annotation. + * Get a the {@link Repeatable} annotation on this class, or the empty list if the class does not have the + * annotation. * *
* Also handles the {@link Inherited} meta-annotation, which causes an annotation to annotate a class and all of * its subclasses. * *
+ * Note that if you need to get multiple annotations, it is faster to call {@link #getAnnotationInfo()}, + * and then get the annotations from the returned {@link AnnotationInfoList}, so that the returned list + * doesn't have to be built multiple times. + * + * @param annotation + * The annotation. + * @return An {@link AnnotationInfoList} of all instances of the annotation on this class, or the empty + * list if the class does not have the annotation. + */ + public AnnotationInfoList getAnnotationInfoRepeatable(final Class extends Annotation> annotation) { + Assert.isAnnotation(annotation); + return getAnnotationInfoRepeatable(annotation.getName()); + } + + /** + * Get a the named {@link Repeatable} annotation on this class, or the empty list if the class does not have the + * named annotation. + * + *
+ * Also handles the {@link Inherited} meta-annotation, which causes an annotation to annotate a class and all of + * its subclasses. + * + *
* Note that if you need to get multiple named annotations, it is faster to call {@link #getAnnotationInfo()},
* and then get the named annotations from the returned {@link AnnotationInfoList}, so that the returned list
* doesn't have to be built multiple times.
- *
+ *
* @param annotationName
* The annotation name.
* @return An {@link AnnotationInfoList} of all instances of the named annotation on this class, or the empty
diff --git a/src/main/java/io/github/classgraph/FieldInfo.java b/src/main/java/io/github/classgraph/FieldInfo.java
index 519100b00..a6f960181 100644
--- a/src/main/java/io/github/classgraph/FieldInfo.java
+++ b/src/main/java/io/github/classgraph/FieldInfo.java
@@ -28,6 +28,7 @@
*/
package io.github.classgraph;
+import java.lang.annotation.Annotation;
import java.lang.annotation.Repeatable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
@@ -40,6 +41,7 @@
import nonapi.io.github.classgraph.types.ParseException;
import nonapi.io.github.classgraph.types.TypeUtils;
import nonapi.io.github.classgraph.types.TypeUtils.ModifierType;
+import nonapi.io.github.classgraph.utils.Assert;
import nonapi.io.github.classgraph.utils.LogNode;
/**
@@ -370,10 +372,24 @@ public AnnotationInfoList getAnnotationInfo() {
: AnnotationInfoList.getIndirectAnnotations(annotationInfo, /* annotatedClass = */ null);
}
+ /**
+ * Get a the non-{@link Repeatable} annotation on this field, or null if the field does not have the
+ * annotation. (Use {@link #getAnnotationInfoRepeatable(Class)} for {@link Repeatable} annotations.)
+ *
+ * @param annotation
+ * The annotation.
+ * @return An {@link AnnotationInfo} object representing the annotation on this field, or null if the
+ * field does not have the annotation.
+ */
+ public AnnotationInfo getAnnotationInfo(final Class extends Annotation> annotation) {
+ Assert.isAnnotation(annotation);
+ return getAnnotationInfo(annotation.getName());
+ }
+
/**
* Get a the named non-{@link Repeatable} annotation on this field, or null if the field does not have the named
* annotation. (Use {@link #getAnnotationInfoRepeatable(String)} for {@link Repeatable} annotations.)
- *
+ *
* @param annotationName
* The annotation name.
* @return An {@link AnnotationInfo} object representing the named annotation on this field, or null if the
@@ -383,10 +399,24 @@ public AnnotationInfo getAnnotationInfo(final String annotationName) {
return getAnnotationInfo().get(annotationName);
}
+ /**
+ * Get a the {@link Repeatable} annotation on this field, or the empty list if the field does not have the
+ * annotation.
+ *
+ * @param annotation
+ * The annotation.
+ * @return An {@link AnnotationInfoList} of all instances of the annotation on this field, or the empty
+ * list if the field does not have the annotation.
+ */
+ public AnnotationInfoList getAnnotationInfoRepeatable(final Class extends Annotation> annotation) {
+ Assert.isAnnotation(annotation);
+ return getAnnotationInfoRepeatable(annotation.getName());
+ }
+
/**
* Get a the named {@link Repeatable} annotation on this field, or the empty list if the field does not have the
* named annotation.
- *
+ *
* @param annotationName
* The annotation name.
* @return An {@link AnnotationInfoList} of all instances of the named annotation on this field, or the empty
@@ -396,6 +426,17 @@ public AnnotationInfoList getAnnotationInfoRepeatable(final String annotationNam
return getAnnotationInfo().getRepeatable(annotationName);
}
+ /**
+ * Check if the field has a given annotation.
+ *
+ * @param annotation The annotation.
+ * @return true if this field has the annotation.
+ */
+ public boolean hasAnnotation(final Class extends Annotation> annotation) {
+ Assert.isAnnotation(annotation);
+ return hasAnnotation(annotation.getName());
+ }
+
/**
* Check if the field has a given named annotation.
*
diff --git a/src/main/java/io/github/classgraph/MethodInfo.java b/src/main/java/io/github/classgraph/MethodInfo.java
index 577360ebb..754d3d3f6 100644
--- a/src/main/java/io/github/classgraph/MethodInfo.java
+++ b/src/main/java/io/github/classgraph/MethodInfo.java
@@ -28,6 +28,7 @@
*/
package io.github.classgraph;
+import java.lang.annotation.Annotation;
import java.lang.annotation.Repeatable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
@@ -42,6 +43,7 @@
import nonapi.io.github.classgraph.types.ParseException;
import nonapi.io.github.classgraph.types.TypeUtils;
import nonapi.io.github.classgraph.types.TypeUtils.ModifierType;
+import nonapi.io.github.classgraph.utils.Assert;
import nonapi.io.github.classgraph.utils.LogNode;
/**
@@ -572,10 +574,23 @@ public AnnotationInfoList getAnnotationInfo() {
: AnnotationInfoList.getIndirectAnnotations(annotationInfo, /* annotatedClass = */ null);
}
+ /**
+ * Get a the non-{@link Repeatable} annotation on this method, or null if the method does not have the
+ * annotation. (Use {@link #getAnnotationInfoRepeatable(Class)} for {@link Repeatable} annotations.)
+ *
+ * @param annotation The annotation.
+ * @return An {@link AnnotationInfo} object representing the annotation on this method, or null if the
+ * method does not have the annotation.
+ */
+ public AnnotationInfo getAnnotationInfo(final Class extends Annotation> annotation) {
+ Assert.isAnnotation(annotation);
+ return getAnnotationInfo(annotation.getName());
+ }
+
/**
* Get a the named non-{@link Repeatable} annotation on this method, or null if the method does not have the
* named annotation. (Use {@link #getAnnotationInfoRepeatable(String)} for {@link Repeatable} annotations.)
- *
+ *
* @param annotationName
* The annotation name.
* @return An {@link AnnotationInfo} object representing the named annotation on this method, or null if the
@@ -585,10 +600,23 @@ public AnnotationInfo getAnnotationInfo(final String annotationName) {
return getAnnotationInfo().get(annotationName);
}
+ /**
+ * Get a the {@link Repeatable} annotation on this method, or the empty list if the method does not have
+ * the annotation.
+ *
+ * @param annotation The annotation.
+ * @return An {@link AnnotationInfoList} containing all instances of the annotation on this method, or the
+ * empty list if the method does not have the annotation.
+ */
+ public AnnotationInfoList getAnnotationInfoRepeatable(final Class extends Annotation> annotation) {
+ Assert.isAnnotation(annotation);
+ return getAnnotationInfoRepeatable(annotation.getName());
+ }
+
/**
* Get a the named {@link Repeatable} annotation on this method, or the empty list if the method does not have
* the named annotation.
- *
+ *
* @param annotationName
* The annotation name.
* @return An {@link AnnotationInfoList} containing all instances of the named annotation on this method, or the
@@ -598,6 +626,17 @@ public AnnotationInfoList getAnnotationInfoRepeatable(final String annotationNam
return getAnnotationInfo().getRepeatable(annotationName);
}
+ /**
+ * Check if this method has the annotation.
+ *
+ * @param annotation The annotation.
+ * @return true if this method has the annotation.
+ */
+ public boolean hasAnnotation(final Class extends Annotation> annotation) {
+ Assert.isAnnotation(annotation);
+ return hasAnnotation(annotation.getName());
+ }
+
/**
* Check if this method has the named annotation.
*
@@ -609,6 +648,17 @@ public boolean hasAnnotation(final String annotationName) {
return getAnnotationInfo().containsName(annotationName);
}
+ /**
+ * Check if this method has a parameter with the annotation.
+ *
+ * @param annotation The method parameter annotation.
+ * @return true if this method has a parameter with the annotation.
+ */
+ public boolean hasParameterAnnotation(final Class extends Annotation> annotation) {
+ Assert.isAnnotation(annotation);
+ return hasParameterAnnotation(annotation.getName());
+ }
+
/**
* Check if this method has a parameter with the named annotation.
*
diff --git a/src/main/java/io/github/classgraph/MethodParameterInfo.java b/src/main/java/io/github/classgraph/MethodParameterInfo.java
index abb48f037..652397f77 100644
--- a/src/main/java/io/github/classgraph/MethodParameterInfo.java
+++ b/src/main/java/io/github/classgraph/MethodParameterInfo.java
@@ -28,6 +28,9 @@
*/
package io.github.classgraph;
+import nonapi.io.github.classgraph.utils.Assert;
+
+import java.lang.annotation.Annotation;
import java.lang.annotation.Repeatable;
import java.lang.reflect.Modifier;
import java.util.Arrays;
@@ -178,11 +181,26 @@ public AnnotationInfoList getAnnotationInfo() {
}
}
+ /**
+ * Get a the non-{@link Repeatable} annotation on this method, or null if the method parameter does not
+ * have the annotation. (Use {@link #getAnnotationInfoRepeatable(Class)} for {@link Repeatable}
+ * annotations.)
+ *
+ * @param annotation
+ * The annotation.
+ * @return An {@link AnnotationInfo} object representing the annotation on this method parameter, or null
+ * if the method parameter does not have the annotation.
+ */
+ public AnnotationInfo getAnnotationInfo(final Class extends Annotation> annotation) {
+ Assert.isAnnotation(annotation);
+ return getAnnotationInfo(annotation.getName());
+ }
+
/**
* Get a the named non-{@link Repeatable} annotation on this method, or null if the method parameter does not
* have the named annotation. (Use {@link #getAnnotationInfoRepeatable(String)} for {@link Repeatable}
* annotations.)
- *
+ *
* @param annotationName
* The annotation name.
* @return An {@link AnnotationInfo} object representing the named annotation on this method parameter, or null
@@ -192,10 +210,24 @@ public AnnotationInfo getAnnotationInfo(final String annotationName) {
return getAnnotationInfo().get(annotationName);
}
+ /**
+ * Get a the {@link Repeatable} annotation on this method, or the empty list if the method parameter does
+ * not have the annotation.
+ *
+ * @param annotation
+ * The annotation.
+ * @return An {@link AnnotationInfoList} containing all instances of the annotation on this method
+ * parameter, or the empty list if the method parameter does not have the annotation.
+ */
+ public AnnotationInfoList getAnnotationInfoRepeatable(final Class extends Annotation> annotation) {
+ Assert.isAnnotation(annotation);
+ return getAnnotationInfoRepeatable(annotation.getName());
+ }
+
/**
* Get a the named {@link Repeatable} annotation on this method, or the empty list if the method parameter does
* not have the named annotation.
- *
+ *
* @param annotationName
* The annotation name.
* @return An {@link AnnotationInfoList} containing all instances of the named annotation on this method
@@ -205,6 +237,17 @@ public AnnotationInfoList getAnnotationInfoRepeatable(final String annotationNam
return getAnnotationInfo().getRepeatable(annotationName);
}
+ /**
+ * Check whether this method parameter has the annotation.
+ *
+ * @param annotation The annotation.
+ * @return true if this method parameter has the annotation.
+ */
+ public boolean hasAnnotation(final Class extends Annotation> annotation) {
+ Assert.isAnnotation(annotation);
+ return hasAnnotation(annotation.getName());
+ }
+
/**
* Check whether this method parameter has the named annotation.
*
diff --git a/src/main/java/io/github/classgraph/ModuleInfo.java b/src/main/java/io/github/classgraph/ModuleInfo.java
index 272e7c65b..8b94c725b 100644
--- a/src/main/java/io/github/classgraph/ModuleInfo.java
+++ b/src/main/java/io/github/classgraph/ModuleInfo.java
@@ -28,11 +28,13 @@
*/
package io.github.classgraph;
+import java.lang.annotation.Annotation;
import java.net.URI;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
+import nonapi.io.github.classgraph.utils.Assert;
import nonapi.io.github.classgraph.utils.CollectionUtils;
/** Holds metadata about a package encountered during a scan. */
@@ -231,9 +233,21 @@ void addAnnotations(final AnnotationInfoList moduleAnnotations) {
}
}
+ /**
+ * Get a the annotation on this module, or null if the module does not have the annotation.
+ *
+ * @param annotation The annotation.
+ * @return An {@link AnnotationInfo} object representing the annotation on this module, or null if the
+ * module does not have the annotation.
+ */
+ public AnnotationInfo getAnnotationInfo(final Class extends Annotation> annotation) {
+ Assert.isAnnotation(annotation);
+ return getAnnotationInfo(annotation.getName());
+ }
+
/**
* Get a the named annotation on this module, or null if the module does not have the named annotation.
- *
+ *
* @param annotationName
* The annotation name.
* @return An {@link AnnotationInfo} object representing the named annotation on this module, or null if the
@@ -260,9 +274,20 @@ public AnnotationInfoList getAnnotationInfo() {
return annotationInfo;
}
+ /**
+ * Check if this module has the annotation.
+ *
+ * @param annotation The annotation.
+ * @return true if this module has the annotation.
+ */
+ public boolean hasAnnotation(final Class extends Annotation> annotation) {
+ Assert.isAnnotation(annotation);
+ return hasAnnotation(annotation.getName());
+ }
+
/**
* Check if this module has the named annotation.
- *
+ *
* @param annotationName
* The name of an annotation.
* @return true if this module has the named annotation.
diff --git a/src/main/java/io/github/classgraph/PackageInfo.java b/src/main/java/io/github/classgraph/PackageInfo.java
index ed7f0b604..7d180720c 100644
--- a/src/main/java/io/github/classgraph/PackageInfo.java
+++ b/src/main/java/io/github/classgraph/PackageInfo.java
@@ -28,6 +28,7 @@
*/
package io.github.classgraph;
+import java.lang.annotation.Annotation;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
@@ -36,6 +37,7 @@
import java.util.Set;
import nonapi.io.github.classgraph.scanspec.ScanSpec;
+import nonapi.io.github.classgraph.utils.Assert;
import nonapi.io.github.classgraph.utils.CollectionUtils;
/** Holds metadata about a package encountered during a scan. */
@@ -123,8 +125,21 @@ void addClassInfo(final ClassInfo classInfo) {
// -------------------------------------------------------------------------------------------------------------
/**
- * Get a the named annotation on this package, or null if the package does not have the named annotation.
+ * Get a the annotation on this package, or null if the package does not have the annotation.
*
+ * @param annotation
+ * The annotation.
+ * @return An {@link AnnotationInfo} object representing the annotation on this package, or null if the
+ * package does not have the annotation.
+ */
+ public AnnotationInfo getAnnotationInfo(final Class extends Annotation> annotation) {
+ Assert.isAnnotation(annotation);
+ return getAnnotationInfo(annotation.getName());
+ }
+
+ /**
+ * Get a the named annotation on this package, or null if the package does not have the named annotation.
+ *
* @param annotationName
* The annotation name.
* @return An {@link AnnotationInfo} object representing the named annotation on this package, or null if the
@@ -151,6 +166,17 @@ public AnnotationInfoList getAnnotationInfo() {
return annotationInfo;
}
+ /**
+ * Check if the package has the annotation.
+ *
+ * @param annotation The annotation.
+ * @return true if this package has the annotation.
+ */
+ public boolean hasAnnotation(final Class extends Annotation> annotation) {
+ Assert.isAnnotation(annotation);
+ return hasAnnotation(annotation.getName());
+ }
+
/**
* Check if the package has the named annotation.
*
diff --git a/src/main/java/io/github/classgraph/ScanResult.java b/src/main/java/io/github/classgraph/ScanResult.java
index f54cdfd26..1a34e24cb 100644
--- a/src/main/java/io/github/classgraph/ScanResult.java
+++ b/src/main/java/io/github/classgraph/ScanResult.java
@@ -30,6 +30,7 @@
import java.io.Closeable;
import java.io.File;
+import java.lang.annotation.Annotation;
import java.lang.ref.WeakReference;
import java.net.MalformedURLException;
import java.net.URI;
@@ -56,10 +57,7 @@
import nonapi.io.github.classgraph.json.JSONDeserializer;
import nonapi.io.github.classgraph.json.JSONSerializer;
import nonapi.io.github.classgraph.scanspec.ScanSpec;
-import nonapi.io.github.classgraph.utils.CollectionUtils;
-import nonapi.io.github.classgraph.utils.FileUtils;
-import nonapi.io.github.classgraph.utils.JarUtils;
-import nonapi.io.github.classgraph.utils.LogNode;
+import nonapi.io.github.classgraph.utils.*;
/**
* The result of a scan. You should assign a ScanResult in a try-with-resources block, or manually close it when you
@@ -882,6 +880,16 @@ public ClassInfoList getAllStandardClasses() {
return ClassInfo.getAllStandardClasses(classNameToClassInfo.values(), scanSpec);
}
+ /**
+ * Get all subclasses of the superclass.
+ *
+ * @param superclass The superclass.
+ * @return A list of subclasses of the superclass, or the empty list if none.
+ */
+ public ClassInfoList getSubclasses(final Class> superclass) {
+ return getSubclasses(superclass.getName());
+ }
+
/**
* Get all subclasses of the named superclass.
*
@@ -923,6 +931,17 @@ public ClassInfoList getSuperclasses(final String subclassName) {
return subclass == null ? ClassInfoList.EMPTY_LIST : subclass.getSuperclasses();
}
+ /**
+ * Get classes that have a method with an annotation of the named type.
+ *
+ * @param methodAnnotation the method annotation.
+ * @return A list of classes with a method that has an annotation of the named type, or the empty list if none.
+ */
+ public ClassInfoList getClassesWithMethodAnnotation(final Class extends Annotation> methodAnnotation) {
+ Assert.isAnnotation(methodAnnotation);
+ return getClassesWithMethodAnnotation(methodAnnotation.getName());
+ }
+
/**
* Get classes that have a method with an annotation of the named type.
*
@@ -942,6 +961,18 @@ public ClassInfoList getClassesWithMethodAnnotation(final String methodAnnotatio
return classInfo == null ? ClassInfoList.EMPTY_LIST : classInfo.getClassesWithMethodAnnotation();
}
+ /**
+ * Get classes that have a method with a parameter that is annotated with an annotation of the named type.
+ *
+ * @param methodParameterAnnotation the method parameter annotation.
+ * @return A list of classes that have a method with a parameter annotated with the named annotation type, or
+ * the empty list if none.
+ */
+ public ClassInfoList getClassesWithMethodParameterAnnotation(final Class extends Annotation> methodParameterAnnotation) {
+ Assert.isAnnotation(methodParameterAnnotation);
+ return getClassesWithMethodParameterAnnotation(methodParameterAnnotation.getName());
+ }
+
/**
* Get classes that have a method with a parameter that is annotated with an annotation of the named type.
*
@@ -962,6 +993,17 @@ public ClassInfoList getClassesWithMethodParameterAnnotation(final String method
return classInfo == null ? ClassInfoList.EMPTY_LIST : classInfo.getClassesWithMethodParameterAnnotation();
}
+ /**
+ * Get classes that have a field with an annotation of the named type.
+ *
+ * @param fieldAnnotation the field annotation.
+ * @return A list of classes that have a field with an annotation of the named type, or the empty list if none.
+ */
+ public ClassInfoList getClassesWithFieldAnnotation(final Class extends Annotation> fieldAnnotation) {
+ Assert.isAnnotation(fieldAnnotation);
+ return getClassesWithFieldAnnotation(fieldAnnotation.getName());
+ }
+
/**
* Get classes that have a field with an annotation of the named type.
*
@@ -1020,6 +1062,18 @@ public ClassInfoList getInterfaces(final String className) {
return classInfo == null ? ClassInfoList.EMPTY_LIST : classInfo.getInterfaces();
}
+ /**
+ * Get all classes that implement (or have superclasses that implement) the interface (or one of its
+ * subinterfaces).
+ *
+ * @param interfaceClass The interface class.
+ * @return A list of all classes that implement the interface, or the empty list if none.
+ */
+ public ClassInfoList getClassesImplementing(final Class> interfaceClass) {
+ Assert.isInterface(interfaceClass);
+ return getClassesImplementing(interfaceClass.getName());
+ }
+
/**
* Get all classes that implement (or have superclasses that implement) the named interface (or one of its
* subinterfaces).
@@ -1075,6 +1129,18 @@ public ClassInfoList getAllInterfacesAndAnnotations() {
return ClassInfo.getAllInterfacesOrAnnotationClasses(classNameToClassInfo.values(), scanSpec);
}
+ /**
+ * Get classes with the class annotation or meta-annotation.
+ *
+ * @param annotation The class annotation or meta-annotation.
+ * @return A list of all non-annotation classes that were found with the class annotation during the scan,
+ * or the empty list if none.
+ */
+ public ClassInfoList getClassesWithAnnotation(final Class extends Annotation> annotation) {
+ Assert.isAnnotation(annotation);
+ return getClassesWithAnnotation(annotation.getName());
+ }
+
/**
* Get classes with the named class annotation or meta-annotation.
*
diff --git a/src/main/java/nonapi/io/github/classgraph/utils/Assert.java b/src/main/java/nonapi/io/github/classgraph/utils/Assert.java
new file mode 100644
index 000000000..204eaa38f
--- /dev/null
+++ b/src/main/java/nonapi/io/github/classgraph/utils/Assert.java
@@ -0,0 +1,16 @@
+package nonapi.io.github.classgraph.utils;
+
+public final class Assert {
+
+ public static void isAnnotation(Class> clazz) {
+ if (!clazz.isAnnotation()) {
+ throw new IllegalArgumentException(clazz + " is not an annotation");
+ }
+ }
+
+ public static void isInterface(Class> clazz) {
+ if (!clazz.isInterface()) {
+ throw new IllegalArgumentException(clazz + " is not an interface");
+ }
+ }
+}
diff --git a/src/test/java/io/github/classgraph/features/MethodParameterAnnotationsTest.java b/src/test/java/io/github/classgraph/features/MethodParameterAnnotationsTest.java
index f4d0d3cb4..9373a1d7c 100644
--- a/src/test/java/io/github/classgraph/features/MethodParameterAnnotationsTest.java
+++ b/src/test/java/io/github/classgraph/features/MethodParameterAnnotationsTest.java
@@ -68,9 +68,9 @@ public void annotationEquality() {
.containsOnly(W.class.getName());
assertThat(scanResult.getClassInfo(Z.class.getName()).getMethodParameterAnnotations().getNames())
.containsOnly(X.class.getName());
- assertThat(scanResult.getClassesWithMethodParameterAnnotation(W.class.getName()).getNames())
+ assertThat(scanResult.getClassesWithMethodParameterAnnotation(W.class).getNames())
.containsOnly(Y.class.getName());
- assertThat(scanResult.getClassesWithMethodParameterAnnotation(X.class.getName()).getNames())
+ assertThat(scanResult.getClassesWithMethodParameterAnnotation(X.class).getNames())
.containsOnly(Z.class.getName());
}
}
diff --git a/src/test/java/io/github/classgraph/issues/IssuesTest.java b/src/test/java/io/github/classgraph/issues/IssuesTest.java
index 1ca9adecc..6a8291f5a 100644
--- a/src/test/java/io/github/classgraph/issues/IssuesTest.java
+++ b/src/test/java/io/github/classgraph/issues/IssuesTest.java
@@ -21,7 +21,7 @@ public class IssuesTest {
@Test
public void issue70() {
try (ScanResult scanResult = new ClassGraph().acceptPackages(Impl1.class.getPackage().getName()).scan()) {
- assertThat(scanResult.getSubclasses(Object.class.getName()).getNames()).contains(Impl1.class.getName());
+ assertThat(scanResult.getSubclasses(Object.class).getNames()).contains(Impl1.class.getName());
}
}
@@ -32,7 +32,7 @@ public void issue70() {
public void issue70EnableExternalClasses() {
try (ScanResult scanResult = new ClassGraph().acceptPackages(Impl1.class.getPackage().getName())
.enableExternalClasses().scan()) {
- assertThat(scanResult.getSubclasses(Object.class.getName()).getNames()).contains(Impl1.class.getName());
+ assertThat(scanResult.getSubclasses(Object.class).getNames()).contains(Impl1.class.getName());
assertThat(scanResult.getSuperclasses(Impl1Sub.class.getName()).getNames())
.containsOnly(Impl1.class.getName());
}
@@ -70,7 +70,7 @@ public void extendsExternalWithEnableExternal() {
public void extendsExternalSubclass() {
try (ScanResult scanResult = new ClassGraph()
.acceptPackages(InternalExtendsExternal.class.getPackage().getName()).scan()) {
- assertThat(scanResult.getSubclasses(ExternalSuperclass.class.getName()).getNames())
+ assertThat(scanResult.getSubclasses(ExternalSuperclass.class).getNames())
.containsOnly(InternalExtendsExternal.class.getName());
}
}
@@ -83,7 +83,7 @@ public void nonStrictExtendsExternalSubclass() {
try (ScanResult scanResult = new ClassGraph()
.acceptPackages(InternalExtendsExternal.class.getPackage().getName()).enableExternalClasses()
.scan()) {
- assertThat(scanResult.getSubclasses(ExternalSuperclass.class.getName()).getNames())
+ assertThat(scanResult.getSubclasses(ExternalSuperclass.class).getNames())
.containsOnly(InternalExtendsExternal.class.getName());
}
}
diff --git a/src/test/java/io/github/classgraph/issues/issue101/Issue101Test.java b/src/test/java/io/github/classgraph/issues/issue101/Issue101Test.java
index 421326983..645406af9 100644
--- a/src/test/java/io/github/classgraph/issues/issue101/Issue101Test.java
+++ b/src/test/java/io/github/classgraph/issues/issue101/Issue101Test.java
@@ -46,7 +46,7 @@ public class Issue101Test {
public void nonInheritedAnnotation() {
try (ScanResult scanResult = new ClassGraph().acceptPackages(Issue101Test.class.getPackage().getName())
.enableAllInfo().scan()) {
- assertThat(scanResult.getClassesWithAnnotation(NonInheritedAnnotation.class.getName()).getNames())
+ assertThat(scanResult.getClassesWithAnnotation(NonInheritedAnnotation.class).getNames())
.containsOnly(AnnotatedClass.class.getName());
}
}
@@ -58,7 +58,7 @@ public void nonInheritedAnnotation() {
public void inheritedMetaAnnotation() {
try (ScanResult scanResult = new ClassGraph().acceptPackages(Issue101Test.class.getPackage().getName())
.enableAllInfo().scan()) {
- assertThat(scanResult.getClassesWithAnnotation(InheritedMetaAnnotation.class.getName())
+ assertThat(scanResult.getClassesWithAnnotation(InheritedMetaAnnotation.class)
.getStandardClasses().getNames()).containsOnly(AnnotatedClass.class.getName(),
NonAnnotatedSubclass.class.getName());
}
@@ -71,7 +71,7 @@ public void inheritedMetaAnnotation() {
public void inheritedAnnotation() {
try (ScanResult scanResult = new ClassGraph().acceptPackages(Issue101Test.class.getPackage().getName())
.enableAllInfo().scan()) {
- assertThat(scanResult.getClassesWithAnnotation(InheritedAnnotation.class.getName()).getNames())
+ assertThat(scanResult.getClassesWithAnnotation(InheritedAnnotation.class).getNames())
.containsOnly(AnnotatedClass.class.getName(), NonAnnotatedSubclass.class.getName(),
AnnotatedInterface.class.getName());
}
diff --git a/src/test/java/io/github/classgraph/issues/issue107/Issue107Test.java b/src/test/java/io/github/classgraph/issues/issue107/Issue107Test.java
index a53864c14..729c8d85f 100644
--- a/src/test/java/io/github/classgraph/issues/issue107/Issue107Test.java
+++ b/src/test/java/io/github/classgraph/issues/issue107/Issue107Test.java
@@ -51,7 +51,7 @@ public void issue107Test() {
// package-info is a non-public class
.ignoreClassVisibility() //
.scan()) {
- assertThat(scanResult.getClassesWithAnnotation(PackageAnnotation.class.getName()).getNames()).isEmpty();
+ assertThat(scanResult.getClassesWithAnnotation(PackageAnnotation.class).getNames()).isEmpty();
assertThat(scanResult.getPackageInfo().getNames())
.containsAll(Arrays.asList("io.github.classgraph", Issue107Test.class.getPackage().getName()));
assertThat(scanResult.getPackageInfo(Issue107Test.class.getPackage().getName()).getAnnotationInfo()
diff --git a/src/test/java/io/github/classgraph/issues/issue216/Issue216Test.java b/src/test/java/io/github/classgraph/issues/issue216/Issue216Test.java
index 0ead78230..f8818b24a 100644
--- a/src/test/java/io/github/classgraph/issues/issue216/Issue216Test.java
+++ b/src/test/java/io/github/classgraph/issues/issue216/Issue216Test.java
@@ -54,7 +54,7 @@ public void testSpringBootJarWithLibJars() {
assertThat(result.getAllClasses().filter(new ClassInfoFilter() {
@Override
public boolean accept(final ClassInfo ci) {
- return ci.hasAnnotation(Entity.class.getName());
+ return ci.hasAnnotation(Entity.class);
}
}).getNames()).containsOnly(Issue216Test.class.getName());
}
diff --git a/src/test/java/io/github/classgraph/issues/issue261/Issue261Test.java b/src/test/java/io/github/classgraph/issues/issue261/Issue261Test.java
index 6f52e4580..d2415fad0 100644
--- a/src/test/java/io/github/classgraph/issues/issue261/Issue261Test.java
+++ b/src/test/java/io/github/classgraph/issues/issue261/Issue261Test.java
@@ -64,7 +64,7 @@ private static class Cls extends SuperCls {
public void issue261Test() {
// Accept only the class Cls, so that SuperCls and SuperSuperCls are external classes
try (ScanResult scanResult = new ClassGraph().acceptClasses(Cls.class.getName()).enableAllInfo().scan()) {
- assertThat(scanResult.getSubclasses(SuperSuperCls.class.getName()).getNames())
+ assertThat(scanResult.getSubclasses(SuperSuperCls.class).getNames())
.containsOnly(SuperCls.class.getName(), Cls.class.getName());
}
}
diff --git a/src/test/java/io/github/classgraph/issues/issue314/Issue314.java b/src/test/java/io/github/classgraph/issues/issue314/Issue314.java
index d0016228c..97727bc6a 100644
--- a/src/test/java/io/github/classgraph/issues/issue314/Issue314.java
+++ b/src/test/java/io/github/classgraph/issues/issue314/Issue314.java
@@ -44,8 +44,8 @@ public void issue314() {
try (final ScanResult scanResult2 = ScanResult.fromJSON(scanResult1.toJSON())) {
final String json2 = scanResult2.toJSON(2);
assertThat(json1).isEqualTo(json2);
- assertThat(scanResult1.getSubclasses(A.class.getName()).getNames()).containsOnly(B.class.getName());
- assertThat(scanResult2.getSubclasses(A.class.getName()).getNames()).containsOnly(B.class.getName());
+ assertThat(scanResult1.getSubclasses(A.class).getNames()).containsOnly(B.class.getName());
+ assertThat(scanResult2.getSubclasses(A.class).getNames()).containsOnly(B.class.getName());
}
}
}
diff --git a/src/test/java/io/github/classgraph/issues/issue318/Issue318.java b/src/test/java/io/github/classgraph/issues/issue318/Issue318.java
index b207e598d..b182f27cf 100644
--- a/src/test/java/io/github/classgraph/issues/issue318/Issue318.java
+++ b/src/test/java/io/github/classgraph/issues/issue318/Issue318.java
@@ -79,10 +79,10 @@ public void issue318() {
.enableAnnotationInfo().enableClassInfo().ignoreClassVisibility() //
//.verbose() //
.scan()) {
- assertThat(scanResult.getClassesWithAnnotation(MyAnn.class.getName()).getNames()).containsOnly(
+ assertThat(scanResult.getClassesWithAnnotation(MyAnn.class).getNames()).containsOnly(
With1MyAnn.class.getName(), With2MyAnn.class.getName(), With3MyAnn.class.getName());
assertThat(scanResult.getClassInfo(With3MyAnn.class.getName())
- .getAnnotationInfoRepeatable(MyAnn.class.getName()).size()).isEqualTo(3);
+ .getAnnotationInfoRepeatable(MyAnn.class).size()).isEqualTo(3);
}
}
}
diff --git a/src/test/java/io/github/classgraph/issues/issue350/Issue350.java b/src/test/java/io/github/classgraph/issues/issue350/Issue350.java
index 5cbb2729e..73fef1549 100644
--- a/src/test/java/io/github/classgraph/issues/issue350/Issue350.java
+++ b/src/test/java/io/github/classgraph/issues/issue350/Issue350.java
@@ -70,17 +70,17 @@ public static class PrivSub extends Priv {
public void test() {
try (ScanResult scanResult = new ClassGraph().acceptPackages(Issue350.class.getPackage().getName())
.enableClassInfo().enableFieldInfo().enableMethodInfo().enableAnnotationInfo().scan()) {
- assertThat(scanResult.getClassesWithFieldAnnotation(SuperclassAnnotation.class.getName()).getNames())
+ assertThat(scanResult.getClassesWithFieldAnnotation(SuperclassAnnotation.class).getNames())
.containsOnly(Pub.class.getName(), PubSub.class.getName());
- assertThat(scanResult.getClassesWithMethodAnnotation(SuperclassAnnotation.class.getName()).getNames())
+ assertThat(scanResult.getClassesWithMethodAnnotation(SuperclassAnnotation.class).getNames())
.containsOnly(Pub.class.getName(), PubSub.class.getName());
}
try (ScanResult scanResult = new ClassGraph().acceptPackages(Issue350.class.getPackage().getName())
.enableClassInfo().enableFieldInfo().enableMethodInfo().enableAnnotationInfo()
.ignoreFieldVisibility().ignoreMethodVisibility().scan()) {
- assertThat(scanResult.getClassesWithFieldAnnotation(SuperclassAnnotation.class.getName()).getNames())
+ assertThat(scanResult.getClassesWithFieldAnnotation(SuperclassAnnotation.class).getNames())
.containsOnly(Pub.class.getName(), PubSub.class.getName(), Priv.class.getName());
- assertThat(scanResult.getClassesWithMethodAnnotation(SuperclassAnnotation.class.getName()).getNames())
+ assertThat(scanResult.getClassesWithMethodAnnotation(SuperclassAnnotation.class).getNames())
.containsOnly(Pub.class.getName(), PubSub.class.getName(), Priv.class.getName());
}
}
diff --git a/src/test/java/io/github/classgraph/issues/issue370/Issue370Test.java b/src/test/java/io/github/classgraph/issues/issue370/Issue370Test.java
index c099dc214..24d88eebb 100644
--- a/src/test/java/io/github/classgraph/issues/issue370/Issue370Test.java
+++ b/src/test/java/io/github/classgraph/issues/issue370/Issue370Test.java
@@ -54,7 +54,7 @@ public void issue370Test() {
final ClassInfo clazzInfo = scanResult.getClassInfo(ClassWithAnnotation.class.getName());
assertThat(clazzInfo).isNotNull();
for (final MethodInfo methodInfo : clazzInfo.getMethodInfo().filter(MethodInfo::isPublic)) {
- final AnnotationInfo annotationInfo = methodInfo.getAnnotationInfo(ApiOperation.class.getName());
+ final AnnotationInfo annotationInfo = methodInfo.getAnnotationInfo(ApiOperation.class);
final String value = annotationInfo.getParameterValues().get("notes").getValue().toString();
assertThat(value).isEqualTo("${snippetclassifications.findById}");
}
diff --git a/src/test/java/io/github/classgraph/issues/issue38/Issue38Test.java b/src/test/java/io/github/classgraph/issues/issue38/Issue38Test.java
index 402e3bf22..f42ebf12d 100644
--- a/src/test/java/io/github/classgraph/issues/issue38/Issue38Test.java
+++ b/src/test/java/io/github/classgraph/issues/issue38/Issue38Test.java
@@ -29,7 +29,7 @@ public static abstract class AnnotationLiteral