如何从注释处理器中的嵌套注释中读取 Class[] 值
How to read a Class[] values from a nested annotation in an annotation processor
我正在尝试使用 Java 注释处理工具生成一些代码,我有嵌套注释,其中父注释值是子注释的数组,子注释值是 类.
注释:
public @interface ParentAnnotation {
ChildAnnotation[] value();
}
public @interface ChildAnnotation {
Class<?>[] value();
}
用法:
@ParentAnnotation(
{
@ChildAnnotation({Foo.class, Bar.class}),
@ChildAnnotation({Goo.class, Doo.class})
})
public class Sample{
}
使用我的 Processor
子类型对注释调用 value()
失败,出现以下异常:
Error:java: error while creating source file javax.lang.model.type.MirroredTypeException: Attempt to access Class object for TypeMirror org.dominokit.samples.layout.shared.extension.LayoutEvent
at com.sun.tools.javac.model.AnnotationProxyMaker$MirroredTypeExceptionProxy.generateException(AnnotationProxyMaker.java:308)
at sun.reflect.annotation.AnnotationInvocationHandler.invoke(AnnotationInvocationHandler.java:84)
at com.sun.proxy.$Proxy28.value(Unknown Source)
at org.dominokit.domino.apt.client.processors.module.client.presenters.PresenterProxySourceWriter.generateFireActivationEvent(PresenterProxySourceWriter.java:238)
at org.dominokit.domino.apt.client.processors.module.client.presenters.PresenterProxySourceWriter.asTypeBuilder(PresenterProxySourceWriter.java:64)
at org.dominokit.domino.apt.client.processors.module.client.presenters.PresenterProxyProcessingStep.generateProxy(PresenterProxyProcessingStep.java:66)
at org.dominokit.domino.apt.client.processors.module.client.presenters.PresenterProxyProcessingStep.process(PresenterProxyProcessingStep.java:53)
at org.dominokit.domino.apt.client.processors.module.client.presenters.PresenterProxyProcessor.process(PresenterProxyProcessor.java:61)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:794)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:705)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.access00(JavacProcessingEnvironment.java:91)
at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176)
at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170)
at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856)
at com.sun.tools.javac.main.Main.compile(Main.java:523)
at com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:129)
at com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:138)
at org.jetbrains.jps.javac.JavacMain.compile(JavacMain.java:196)
at org.jetbrains.jps.incremental.java.JavaBuilder.compileJava(JavaBuilder.java:448)
at org.jetbrains.jps.incremental.java.JavaBuilder.compile(JavaBuilder.java:318)
at org.jetbrains.jps.incremental.java.JavaBuilder.doBuild(JavaBuilder.java:243)
at org.jetbrains.jps.incremental.java.JavaBuilder.build(JavaBuilder.java:201)
at org.jetbrains.jps.incremental.IncProjectBuilder.runModuleLevelBuilders(IncProjectBuilder.java:1327)
at org.jetbrains.jps.incremental.IncProjectBuilder.runBuildersForChunk(IncProjectBuilder.java:1007)
at org.jetbrains.jps.incremental.IncProjectBuilder.buildTargetsChunk(IncProjectBuilder.java:1074)
at org.jetbrains.jps.incremental.IncProjectBuilder.buildChunkIfAffected(IncProjectBuilder.java:968)
at org.jetbrains.jps.incremental.IncProjectBuilder.buildChunks(IncProjectBuilder.java:797)
at org.jetbrains.jps.incremental.IncProjectBuilder.runBuild(IncProjectBuilder.java:375)
at org.jetbrains.jps.incremental.IncProjectBuilder.build(IncProjectBuilder.java:178)
at org.jetbrains.jps.cmdline.BuildRunner.runBuild(BuildRunner.java:138)
at org.jetbrains.jps.cmdline.BuildSession.runBuild(BuildSession.java:302)
at org.jetbrains.jps.cmdline.BuildSession.run(BuildSession.java:135)
at org.jetbrains.jps.cmdline.BuildMain$MyMessageHandler.lambda$channelRead0[=13=](BuildMain.java:229)
at org.jetbrains.jps.service.impl.SharedThreadPoolImpl.lambda$executeOnPooledThread[=13=](SharedThreadPoolImpl.java:42)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
那么我如何从注释中读取这些 类 作为 List<TypeMirror>
?
经过大量调试并一次尝试一件事后,我找到了解决方案,想法是如何使用 AnnotationMirror
获得 AnnotationValue
,有一些混乱在某些时候,预期的 return 类型 AnnotationValue[]
实际上是 List<AnnotationValue>
,下面是我编写的实用方法,用于将 类 读取为 List<List<TypeMirror>>
:
private List<List<TypeMirror>> getNestedAnnotationClassesValue(Element element){
List<List<TypeMirror>> classesInAnntation = new ArrayList<>();
if (nonNull(element.getAnnotation(ParentAnnotation.class))) {
List<? extends AnnotationMirror> annotations = element.getAnnotationMirrors();
for (AnnotationMirror annotationMirror : annotations) {
if (types.isSameType(annotationMirror.getAnnotationType(), elements.getTypeElement(ParentAnnotation.class.getName()).asType())) {
Map<? extends ExecutableElement, ? extends AnnotationValue> elementValues = annotationMirror.getElementValues();
elementValues.values()
.stream()
.findFirst()
.ifPresent(annotationValue -> {
List<AnnotationMirror> childAnnotations = (List<AnnotationMirror>) annotationValue.getValue();
childAnnotations.stream()
.forEach(childAnnotationMirror -> {
Collection<? extends AnnotationValue> values = childAnnotationMirror.getElementValues()
.values();
AnnotationValue childAnnotationValue = values.stream().findFirst().get();
List<AnnotationValue> classesInNestedAnnotation = (List<AnnotationValue>) childAnnotationValue.getValue();
Iterator<? extends AnnotationValue> iterator = classesInNestedAnnotation.iterator();
List<TypeMirror> typeMirrorsInNestedAnnotation = new ArrayList<>();
while (iterator.hasNext()) {
AnnotationValue next = iterator.next();
typeMirrorsInNestedAnnotation.add((TypeMirror) next.getValue());
}
if (!typeMirrorsInNestedAnnotation.isEmpty()) {
classesInAnntation.add(typeMirrorsInNestedAnnotation);
}
});
});
}
}
}
return classesInAnntation;
}
我正在尝试使用 Java 注释处理工具生成一些代码,我有嵌套注释,其中父注释值是子注释的数组,子注释值是 类.
注释:
public @interface ParentAnnotation {
ChildAnnotation[] value();
}
public @interface ChildAnnotation {
Class<?>[] value();
}
用法:
@ParentAnnotation(
{
@ChildAnnotation({Foo.class, Bar.class}),
@ChildAnnotation({Goo.class, Doo.class})
})
public class Sample{
}
使用我的 Processor
子类型对注释调用 value()
失败,出现以下异常:
Error:java: error while creating source file javax.lang.model.type.MirroredTypeException: Attempt to access Class object for TypeMirror org.dominokit.samples.layout.shared.extension.LayoutEvent
at com.sun.tools.javac.model.AnnotationProxyMaker$MirroredTypeExceptionProxy.generateException(AnnotationProxyMaker.java:308)
at sun.reflect.annotation.AnnotationInvocationHandler.invoke(AnnotationInvocationHandler.java:84)
at com.sun.proxy.$Proxy28.value(Unknown Source)
at org.dominokit.domino.apt.client.processors.module.client.presenters.PresenterProxySourceWriter.generateFireActivationEvent(PresenterProxySourceWriter.java:238)
at org.dominokit.domino.apt.client.processors.module.client.presenters.PresenterProxySourceWriter.asTypeBuilder(PresenterProxySourceWriter.java:64)
at org.dominokit.domino.apt.client.processors.module.client.presenters.PresenterProxyProcessingStep.generateProxy(PresenterProxyProcessingStep.java:66)
at org.dominokit.domino.apt.client.processors.module.client.presenters.PresenterProxyProcessingStep.process(PresenterProxyProcessingStep.java:53)
at org.dominokit.domino.apt.client.processors.module.client.presenters.PresenterProxyProcessor.process(PresenterProxyProcessor.java:61)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:794)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:705)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.access00(JavacProcessingEnvironment.java:91)
at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176)
at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170)
at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856)
at com.sun.tools.javac.main.Main.compile(Main.java:523)
at com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:129)
at com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:138)
at org.jetbrains.jps.javac.JavacMain.compile(JavacMain.java:196)
at org.jetbrains.jps.incremental.java.JavaBuilder.compileJava(JavaBuilder.java:448)
at org.jetbrains.jps.incremental.java.JavaBuilder.compile(JavaBuilder.java:318)
at org.jetbrains.jps.incremental.java.JavaBuilder.doBuild(JavaBuilder.java:243)
at org.jetbrains.jps.incremental.java.JavaBuilder.build(JavaBuilder.java:201)
at org.jetbrains.jps.incremental.IncProjectBuilder.runModuleLevelBuilders(IncProjectBuilder.java:1327)
at org.jetbrains.jps.incremental.IncProjectBuilder.runBuildersForChunk(IncProjectBuilder.java:1007)
at org.jetbrains.jps.incremental.IncProjectBuilder.buildTargetsChunk(IncProjectBuilder.java:1074)
at org.jetbrains.jps.incremental.IncProjectBuilder.buildChunkIfAffected(IncProjectBuilder.java:968)
at org.jetbrains.jps.incremental.IncProjectBuilder.buildChunks(IncProjectBuilder.java:797)
at org.jetbrains.jps.incremental.IncProjectBuilder.runBuild(IncProjectBuilder.java:375)
at org.jetbrains.jps.incremental.IncProjectBuilder.build(IncProjectBuilder.java:178)
at org.jetbrains.jps.cmdline.BuildRunner.runBuild(BuildRunner.java:138)
at org.jetbrains.jps.cmdline.BuildSession.runBuild(BuildSession.java:302)
at org.jetbrains.jps.cmdline.BuildSession.run(BuildSession.java:135)
at org.jetbrains.jps.cmdline.BuildMain$MyMessageHandler.lambda$channelRead0[=13=](BuildMain.java:229)
at org.jetbrains.jps.service.impl.SharedThreadPoolImpl.lambda$executeOnPooledThread[=13=](SharedThreadPoolImpl.java:42)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
那么我如何从注释中读取这些 类 作为 List<TypeMirror>
?
经过大量调试并一次尝试一件事后,我找到了解决方案,想法是如何使用 AnnotationMirror
获得 AnnotationValue
,有一些混乱在某些时候,预期的 return 类型 AnnotationValue[]
实际上是 List<AnnotationValue>
,下面是我编写的实用方法,用于将 类 读取为 List<List<TypeMirror>>
:
private List<List<TypeMirror>> getNestedAnnotationClassesValue(Element element){
List<List<TypeMirror>> classesInAnntation = new ArrayList<>();
if (nonNull(element.getAnnotation(ParentAnnotation.class))) {
List<? extends AnnotationMirror> annotations = element.getAnnotationMirrors();
for (AnnotationMirror annotationMirror : annotations) {
if (types.isSameType(annotationMirror.getAnnotationType(), elements.getTypeElement(ParentAnnotation.class.getName()).asType())) {
Map<? extends ExecutableElement, ? extends AnnotationValue> elementValues = annotationMirror.getElementValues();
elementValues.values()
.stream()
.findFirst()
.ifPresent(annotationValue -> {
List<AnnotationMirror> childAnnotations = (List<AnnotationMirror>) annotationValue.getValue();
childAnnotations.stream()
.forEach(childAnnotationMirror -> {
Collection<? extends AnnotationValue> values = childAnnotationMirror.getElementValues()
.values();
AnnotationValue childAnnotationValue = values.stream().findFirst().get();
List<AnnotationValue> classesInNestedAnnotation = (List<AnnotationValue>) childAnnotationValue.getValue();
Iterator<? extends AnnotationValue> iterator = classesInNestedAnnotation.iterator();
List<TypeMirror> typeMirrorsInNestedAnnotation = new ArrayList<>();
while (iterator.hasNext()) {
AnnotationValue next = iterator.next();
typeMirrorsInNestedAnnotation.add((TypeMirror) next.getValue());
}
if (!typeMirrorsInNestedAnnotation.isEmpty()) {
classesInAnntation.add(typeMirrorsInNestedAnnotation);
}
});
});
}
}
}
return classesInAnntation;
}