Skip to content

Ideally avaje-inject-generator should not depend on avaje-inject #276

@agentgt

Description

@agentgt

A lot of folks are not aware of this but you should almost never use the actual annotation classes in an annotation processor even your own. BTW I only know of couple libraries that generally do this correctly: MapStruct, JStachio (mine) and I believe Micronaut (so don't feel bad). It is also probably why no one knows about Hickory (or the new MapStruct gemtools).

So why is it problematic? Well the annotation processor is not guaranteed to have classes loaded and if your annotation references other classes (e.g. has a Class<?> parameter ) that are not yours you will have issues especially and I mean especially if you are dealing with modularized projects.

So why have you guys not run into issues? Well because both Maven and I think gradle as well will simply move whatever dependencies that are in <annotationProcessorPaths> into the classpath during compilation. Otherwise all libraries that are referenced with requires (static or not) in module-info (and not in the annotationProcessorPaths) will be put in the module-path.

The above is one the reasons why <annotationProcessorPaths> is required for modular projects but it is seriously limited and technically not correct either: https://issues.apache.org/jira/browse/MCOMPILER-391 and https://issues.apache.org/jira/browse/MCOMPILER-412

Otherwise if avaje-inject-generator does not have dependencies just having avaje-inject-generator on the classpath will work and you would not need to do <annotationProcessorPaths> for modular projects and this is one of the big advantages to doing it the painful. BTW this is also why lots of annotation processors shade their deps but you can't really do that for annotations.

So how do you access your own annotations without using them directly? You have to load the TypeElement.

readScopes(roundEnv.getElementsAnnotatedWith(Scope.class));

Instead of Scope.class you are going to pass a TypeElement. To get the TypeElement you can either get it from the call process function or just call Elements.getTypeElement: https://docs.oracle.com/en/java/javase/11/docs/api/java.compiler/javax/lang/model/util/Elements.html#getTypeElement(java.lang.CharSequence)

Anyway that is easy and fine however it becomes a pain in the ass to get annotation parameters. That is where Hickory comes in (or mapstruct gemtools but you would have to shade it).
https://javadoc.io/static/com.jolira/hickory/1.0.0/net/java/dev/hickory/prism/package-summary.html

Hickory is an annotation processor that makes what are called prisms which you can access your annotations as though you are accessing them directly.

Anyway I normally would not bother even bringing all this up as yeah there is a work around ... manually register annotation processors...

But the project appears to not heavily dependent on its annotation core lib and is not a big change. In fact I could probably do a PR and do it myself if you are interested.

Furthermore it is technically the right way to do it and will prevent problems in the future as more folks embrace modularity.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions