Getting a CodeBlock from an AnnotationValue for an enum constant
cushon opened this issue · 2 comments
JDK-8164819 changed the toString()
implementation of some AnnotationValue
implementations to match core reflection.
For AnnotationValue
s representing an enum constant, the toString()
is now the simple name instead of a fully qualified name. I encountered some code that using CodeBlock.of("$L", annotationValue)
, which ends up just calling toString()
, which now results in an unqualified simple name of the enum constant.
Is there already a better way to convert an AnnotationValue
to a CodeBlock
? I couldn't find one. There's some logic in AnnotationSpec
that's close to what I want, but the only entry point takes an entire AnnotationMirror
:
javapoet/src/main/java/com/squareup/javapoet/AnnotationSpec.java
Lines 267 to 269 in 8851788
Demo:
import com.squareup.javapoet.CodeBlock;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic.Kind;
@SupportedAnnotationTypes("*")
public class P extends AbstractProcessor {
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}
enum E {
ONE;
}
@interface A {
E value() default E.ONE;
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
TypeElement typeElement = processingEnv.getElementUtils()
.getTypeElement("P.A");
for (Element member : typeElement.getEnclosedElements()) {
if (member.getSimpleName().contentEquals("value")) {
AnnotationValue av = ((ExecutableElement) member).getDefaultValue();
processingEnv.getMessager().printMessage(Kind.NOTE, CodeBlock.of("$L", av).toString());
}
}
return false;
}
}
With JDK 11, CodeBlock.of("$L", av)
is the qualified name P.E.ONE
:
$ javac -version -processorpath .:javapoet-1.13.0.jar -processor P -cp javapoet-1.13.0.jar P.java
javac 11.0.11
Note: P.E.ONE
Note: P.E.ONE
With JDK 17, it's just ONE
:
$ javac -version -processorpath .:javapoet-1.13.0.jar -processor P -cp javapoet-1.13.0.jar P.java
javac 17-ea
Note: ONE
Note: ONE
A few updates
- I ran into this in some more processors, and the incompatible change in javac is now being tracked by JDK-8268729
- I'm looking at adding a helpers to
auto-common
to convertAnnotationValue
to a more useful string - It might still be nice to have support in JavaPoet for converting
AnnotationValue
s into source
I'm working on this issue and will try to fix it.