I have my annotation processor:
public class MyAnnotationProcessor extends AbstractProcessor {
...
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
// Here I deal with the annotated element
...
// use JavaPoet to generate Java source file
TypeSpec generatedClazz = generate_code();
JavaFile javaFile = JavaFile.builder("com.my.foo", generatedClazz).build();
javaFile.writeTo(filer);
}
}
After processing annotated element in above process callback, I use JavaPoet to generate java source code & create the Java file for the code. When build my project, everything works except that the generated java source code file by default goes to build/generated/sources/myApp/com/my/foo. How can I make the generated Java file to be located in my project's source code location src/main/java/com/my/foo ?
My gradle build:
plugins {
id 'java'
}
group 'com.my.app'
version '1.0-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
testImplementation 'junit:junit:4.12'
implementation 'com.squareup:javapoet:1.11.1'
implementation 'com.google.guava:guava:28.1-jre'
}
The bad news: Annotation processors can't do this - the nature of how their rounds work mean that it isn't going to make sense to generate sources in the same directory where "actual" sources live, since those generated sources will be treated as inputs the next time the annotation processor runs.
Good news: JavaPoet is agnostic of how you actually invoke it, so you can just write a simple main() that does the code generation, and either ask your IDE to invoke it when it builds, or attach it to your gradle build. If you plan on manually editing the sources after they are generated, you probably don't want this to happen, since you likely intend your manual changes to be kept instead of being overwritten each time you build.
The JavaFile.writeTo(...) method has several overrides, and only one of them takes the annotation processor Filer. Using the Filer has some advantages - it is very clear where you intend the class to be written - but JavaFile.writeTo(File directory) is also meant to be used in this way. You don't pass it the actual file where you want the MyClass.java to be, just the source directory you want to write to. In your case, this would be roughly javaFile.writeTo(new File("myProject/src/main/java")).
You probably still should parameterize how to invoke this main, so that it knows what inputs to use, how to understand your existing sources, etc. On the other hand, if your generate_code() doesn't need any existing sources from the same project to run, this should be quite straightforward.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With