Anvil is composed of several independent code generators that provide hints for the later stages
in the build graph when all modules and components are merged together. These code generators
are similar to annotation processors in the way that they look for a specific annotation like
@ContributesTo
and then generate necessary code. For more information about the internals of
Anvil itself, please take a look at this guide.
If you see yourself repeating the same code structures and patterns for your dependency injection
setup over and over again, then you can extend Anvil and implement your own code generator via
the CodeGenerator
interface.
It's recommended to create your own annotation for your use case to not conflict with Anvil and
its own annotations. The annotation needs to live in its own module separate from the code
generator, e.g. :sample:annotation
.
annotation class MyAnnotation
Later you'll use this annotation to give your code generator a hint for work to perform.
In the code generator module :sample:code-generator
you need to import the compiler-api
artifact:
dependencies {
api "com.squareup.anvil:compiler-api:${latest_version}"
// Optional:
compileOnly "com.google.auto.service:auto-service-annotations:1.0"
kapt "com.google.auto.service:auto-service:1.0"
}
After that implement the CodeGenerator
interface:
@AutoService(CodeGenerator::class)
class SampleCodeGenerator : CodeGenerator {
override fun isApplicable(context: AnvilContext): Boolean = true
override fun generateCode(
codeGenDir: File,
module: ModuleDescriptor,
projectFiles: Collection<KtFile>
): Collection<GeneratedFile> {
return projectFiles
.classAndInnerClassReferences(module)
.filter { it.isAnnotatedWith(FqName("sample.MyAnnotation")) }
.map { clazz ->
// ...
createGeneratedFile(
codeGenDir = codeGenDir,
packageName = // ...
fileName = // ...
content = // ...
)
}
.toList()
}
}
Note that the sample code generator is annotated with @AutoService
. It's recommended to use the
AutoService library to generate necessary
code for the ServiceLoader
API. Anvil uses this mechanism to load your custom code generator.
You can generate as many classes and files as you wish. You can even generate code that uses Anvil
or Dagger annotations and Anvil will process these files. The generateCode()
function is called
multiple times until no code generators generate code anymore.
To use your new code generator in any module you need to add the module to the Anvil classpath:
plugins {
id 'com.squareup.anvil' version "${latest_version}"
}
dependencies {
anvil project(':sample:code-generator')
implementation project(':sample:annotation')
}
Anvil code generators are no replacement for Java annotation processing or Kotlin symbol processing. If you want to generate code independent of Anvil, then it's better to rely on an annotation processor, KSP or your own Kotlin compiler plugin instead.
Anvil code generators can only generate new code and not modify or remove existing code. For that you need to create your own compiler plugin.