Search code examples
gradlegroovy

Is it possible for an external gradle annotationProcessor to imply its dependencies?


As far as I can tell, you need to manually specify what's going to be in the classpath when using Gradle's annotationProcessor dependency handler. I'm looking for a way to possibly automate that.

It feels like I'm missing something. Let's say I have an annotation processor called my.processor, with javapoet as a dependency:

dependencies {
    implementation 'com.squareup:javapoet:1.13.0'
}

However, when it's time to apply my processor to a given class, I need to manually specify that JavaPoet has to be present in the classpath:

dependencies {
    // (other dependencies)
    annotationProcessor 'my:processor:1.0.0'
    annotationProcessor 'com.squareup:javapoet:1.13.0'
}

If I don't, it's going to throw an exception (TypeDefNotFoundException if I recall correctly) lamenting that it can't find one of the javapoet classes - obviously, since it's not in the classpath.

Is it possible to just write:

dependencies {
    // (other dependencies)
    annotationProcessor 'my:processor:1.0.0'
}

and have the presence of javapoet (or any other dependency of my.processor) be implied?


Solution

  • This is tricky. The short answer is NO, but here is my logic.

    Marking your my-processor library as an annotationProcessor should pull over your transient dependencies which means javapoet will be on the classpath through the implementation dependency, but it would not be marked as an annotationProcessor in your project. Just because javapoet COULD be used an an annotationProcessor doesn't mean it SHOULD be. Hence you must specify both annotation processors because your 3rd party project uses both. Gradle can't read your mind.

    The only way I'd know if it would have any chance of working is if you specified javapoet as an annotationProcessor in your my-processor project and by specifying my-processor as an annotationProcess that had some transient dependency relationship and gradle would 'know' to pull over javapoet too as an annotationProcessor. But I don't know if that exists or not, and as I describe it; it sounds like a big reach. Here's why:

    Consider this alternative that my-processor had some annotations in its code base from javapoet that it used to function internally. But it used javapoet as an annotationProcessor to create some code for its library to work, but wasn't piggy backing off a 3rd party project also using javapoet. In that case the fact that javapoet was marked as an annotationProcessor wouldn't also be applied to other projects that were dependent on my-processor. In which case you'd only register my-processor and not javapoet and that would be the expected case because the 3rd party project only used my-processor and NOT javapoet. That case would look exactly like what I described above with my-project declaring annotationProcessor for javapoet. In one case you want isolation from dependencies' usage of annotationProcessor. And in the desired case you want it to transiently be applied to 3rd party cases. But the configuration of both of those situations is exactly the same so you couldn't differentiate what the developer wanted to happen. So my guess is NO you have to specify both annotation processors in your projects that directly use those libraries.