Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Annotation Processor accessing Annotated classes from different modules

I'm having an Android Studio project with 2 modules: A and B. (I do not include here the Annotation Processor and the Annotations module)

B depends on A.

B is an Android Library Module, and A is simple Java library Module. I'm also having an Annotation Processor on module B.

The problem I'm facing is:

I want to generate some code, based on annotated files placed in both modules - A and B. The problem comes from the way the Annotation Processor works - only with source code files *.java - not with compiled *.class ones. Unfortunately, during the compilation of B, the Annotation Processor doesn't have access to those source files from A...

The only thing, I was able to think about as a kind of solution, even an ugly one, was to include the folder with the annotated classes from module A as a source set to module B. This way I give module B access to those files during compilation.

sourceSets {
    main {
        java {
            srcDirs = ['src/main/java', '../module_A/src/main/java/path/to/annotated/classes/folder']
        }
    }
}

That solves the problem - now the Annotation Processor has access to all the annotated classes from both modules, but...

Unfortunately, it introduces another issue... those annotated classes from module A, are now compiled twice. And they are included in the module A's JAR file and in the module B's AAR file.

Question 1: Is there another way to access those source files of module A, from the Annotation Processor running on B??? (From what I was able to find, the answer is NO, but checking...)

Question 2: How can I exclude those compiled files (the repeated ones) from the AAR final package of module B?

Question 3: Maybe... that's an absolutely wrong approach? Any suggestions?

Thanks in advance!

like image 732
ivtoto Avatar asked Oct 18 '22 15:10

ivtoto


1 Answers

Nop, you can not achieve what you want using just java.lang.model API. At least not without some additional tricks.

The issues is not with binary-vs-source. Annotation processors can use Elements#getTypeElement to interospect compiled classes as well as source-defined classes:

Elements elementUtil = processingEnvironment.getElementUtils();
TypeElement integerClass = elementUtil.getTypeElement("java.lang.Integer");
TypeElement myClass = elementUtil.getTypeElement("currently.compiled.Class");

But you still need to have class on compilation classpath to observe it, and the class must be in process of being compiled to be visible to getElementsAnnotatedWith.

You can work around later limitation by using a tool like FastClasspathScanner: it will use it's own mechanisms to find annotations in compiled bytecode, and report them to you separately from compilation process. But you can not work around the classpath issue: if you don't have some dependency in compilation classpath, it can not be processed. So you have to compile modules together — either by merging them into one (as you did) or via declaring one to depend on another. In later case you might not be able to use getElementsAnnotatedWith, but getTypeElement and FastClasspathScanner will work.

like image 179
user1643723 Avatar answered Oct 29 '22 19:10

user1643723