Compile-time Annotation Processing [Solved]
-
I am attempting to generate a compile-time error if a subclass does not define a specific static field with a type subclassed from a defined Class field in the annotation. For example:
// RequiredStaticField.java
import java.lang.annotation.*;@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
@Inherited
public @interface RequiredStaticField {
public String name();
public Class type();
}// MyClass.java
@RequiredStaticField(name="StaticField", type=Number.class)
public class MyClass {
private static Integer StaticField;
}The classes above should validate and compile. However, I am having trouble determining if "Integer" is a subtype of "Number" in my AbstractProcessor implementation...
// RequiredStaticFieldProcessor.java
import java.util.Set;import javax.annotation.processing.*;
import javax.lang.model.element.*;
import javax.lang.model.util.Types;@SupportedAnnotationTypes("NAMESPACE.RequiredStaticField");
public class RequiredStaticFieldProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment environment) {
// Get all classes that have the annotation
Set<? extends Element> elementsWithAnnotation =
environment.getElementsAnnotatedWith(RequiredStaticField.class);
for (Element elementWithAnnotation : elementsWithAnnotation) {
// If the element kind is not ElementKind.CLASS, display warning and continue
// If the class is abstract, continue
boolean isFound = false;
RequiredStaticMethod annotation = elementWithAnnotation
.getAnnotation(RequiredStaticMethod.class);
for (Element member : elementWithAnnotation.getEnclosedElements()) {
// If not a field, continue
// If the field has the wrong name, continue// THIS IS WHERE I NEED HELP! The following does not compile. // In the following, I either need to get the Class // of member.asType(), or I need to iterate through the superclasses // of member.asType(), or I need to convert annotation.type() // to a TypeMirror object. Any Ideas? isFound = Types.isSubType(member.asType(), annotation.type()); if (isFound) { break; } else { // Display error about declari
-
I am attempting to generate a compile-time error if a subclass does not define a specific static field with a type subclassed from a defined Class field in the annotation. For example:
// RequiredStaticField.java
import java.lang.annotation.*;@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
@Inherited
public @interface RequiredStaticField {
public String name();
public Class type();
}// MyClass.java
@RequiredStaticField(name="StaticField", type=Number.class)
public class MyClass {
private static Integer StaticField;
}The classes above should validate and compile. However, I am having trouble determining if "Integer" is a subtype of "Number" in my AbstractProcessor implementation...
// RequiredStaticFieldProcessor.java
import java.util.Set;import javax.annotation.processing.*;
import javax.lang.model.element.*;
import javax.lang.model.util.Types;@SupportedAnnotationTypes("NAMESPACE.RequiredStaticField");
public class RequiredStaticFieldProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment environment) {
// Get all classes that have the annotation
Set<? extends Element> elementsWithAnnotation =
environment.getElementsAnnotatedWith(RequiredStaticField.class);
for (Element elementWithAnnotation : elementsWithAnnotation) {
// If the element kind is not ElementKind.CLASS, display warning and continue
// If the class is abstract, continue
boolean isFound = false;
RequiredStaticMethod annotation = elementWithAnnotation
.getAnnotation(RequiredStaticMethod.class);
for (Element member : elementWithAnnotation.getEnclosedElements()) {
// If not a field, continue
// If the field has the wrong name, continue// THIS IS WHERE I NEED HELP! The following does not compile. // In the following, I either need to get the Class // of member.asType(), or I need to iterate through the superclasses // of member.asType(), or I need to convert annotation.type() // to a TypeMirror object. Any Ideas? isFound = Types.isSubType(member.asType(), annotation.type()); if (isFound) { break; } else { // Display error about declari
Figured it out: you can't access an annotation field of type Class<?> at compile-time. Attempting to do so results in a MirroredTypeException. Instead, pass the class in as a string containing the fully-qualified name of the type, and use the following code to get the TypeMirror for that type:
MyAnnotation annotation = elementWithAnnotation.getAnnotation(MyAnnotation.class);
// type is a string...
Element typeDeclaration = processingEnv.getElementUtils().getTypeElement(annotation.type());
if (typeDeclaration == null) {
// The type could not be found
} else {
// Do something with typeDeclaration.asType()
}Hope this helps,
Sounds like somebody's got a case of the Mondays -Jeff