7

I have a custom annotation that I've implemented and I'd like to use an annotation processor to generate a list of all the classes in my app that use that particular annotation.

I've found this tutorial which describes how to generate a class file using an annotation processor, so it should be quite easy to generate a class for each class with my annotation.

What I can't figure out is how I can collect all of that information into a single class. There doesn't seem to be a way to modify a class, so I can't append new items to the list once the class has been generated the first time.

Is there a way to use an annotation processor to generate a method that will return the list of all classes in an app that are annotated with a particular annotation?

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
emmby
  • 99,783
  • 65
  • 191
  • 249

1 Answers1

6

Generated classes do not necessarily have to correspond one-to-one to the input classes being processed. Plus, you can search for classes (Elements) that are annotated with a given annotation via the RoundEnvironment:

roundEnvironment.getElementsAnnotatedWith(MyAnnotation.class)

From this you can generate a single class with a method that returns a collection of the classes found.

A couple issues around this to highlight:

  • Annotation processors can run along with other annotation processors and thus have to deal with classes generated at compile time. To aid this, Java annotation processing is performed in rounds to allow processors to catch the outputs of others. To be compatible with other processors you need to gracefully handle the ErrorType.
  • Only classes in the current compilation pass are returned from the RoundEnvironmnet methods so classes in external libraries will not be included.
  • IDEs (cough cough Eclipse) implement the annotation processing facilities of Java differently which can be a problem for processors that require a full non-partial compilation like I've described.

Coincidentally, I created a similar project recently that does what you are looking for:

https://github.com/johncarl81/silver

Silver is very much a WIP and uses a lot of library code to accomplish the task, but it may give you an idea for what's possible.

John Ericksen
  • 10,995
  • 4
  • 45
  • 75
  • 1
    Hey John! Nice to hear from you :) Silver looks pretty great, what's the runtime impact of SilverUtils.getAnnotated()? Also, what, if anything, does it have to pull into the classloader at runtime beyond the classes that are annotated? – emmby Feb 04 '14 at 19:12
  • 1
    Good to hear from you too Mike! The coolest thing about this approach is that runtime is as fast as it can be. Once you have an instance of Example, the only runtime cost is that of returning a static variable. SiverUtil.get() does perform a little reflection to look-up classes (one call to Class.forName()), but this call is cached and therefore only made once. SilverUtil is really there for convenience anyways, technically you don't have to use it to use the generated code. – John Ericksen Feb 04 '14 at 21:44
  • Hello, John! Nice to see this project - Silver) It may to help me with my annotation processor. Thanks for your hard work! – hohserg Jan 10 '21 at 15:00