Generating Metro Code¶
Java annotation processing and KSP both support multiple rounds of processing, allowing custom processors to generate new code with injection annotations that can be processed in later rounds. Anvil supported custom CodeGenerator
implementations in K1 and anvil-ksp and kotlin-inject-anvil support specifying custom contributing annotations to allow them to intelligently defer processing to later rounds.
Since Metro is implemented as a compiler plugin, asking users to write compiler plugins to interact with it would be a bit unwieldy. However, KSP processors that generate metro-annotated code work out of the box with it since they run before Metro’s plugin does.
If you have an existing KSP processor for a different framework, you could leverage it + custom annotations interop support described above to make them work out of the box with Metro.
Origin Annotations¶
When code generators create Metro-annotated types, they can use the @Origin
annotation to link the generated type back to its source. This is particularly useful for contribution merging - when a source type is excluded or replaced in a @DependencyGraph
, any generated types with @Origin
pointing to it will also be excluded or replaced automatically.
// Source type
@GenerateSomething
class UserRepository
// Generated by your KSP processor
@ContributesBinding(AppScope::class)
@Origin(UserRepository::class) // Links back to the source
class UserRepository_Impl : UserRepository
Now if UserRepository
is excluded in a graph:
@DependencyGraph(
scope = AppScope::class,
excludes = [UserRepository::class] // This also excludes UserRepository_Impl
)
interface AppGraph
Custom Origin Annotations¶
You can configure Metro to recognize custom origin annotations through the Gradle plugin:
metro {
interop {
origin.add("com.example.GeneratedFrom")
}
}
The annotation must have a KClass
parameter at index 0
.
If using Anvil interop, kotlin-inject-anvil’s @Origin
annotation is automatically recognized.
metro {
interop {
includeAnvil(includeKotlinInjectAnvil = true)
}
}