Architecture¶
These pages explain how the navigation codegen processor is built. They are written for contributors who want to read or modify the processor itself. If you only want to use the codegen, start at get-started.md and annotations.md instead.
The processor turns one annotated symbol into one or two Kotlin source files on disk. Every page below covers one stage of that journey, in pipeline order.
- pipeline.md covers the KSP entry point: how the processor finds annotated symbols, decides what to do with each, and writes the result.
- data-model.md covers the typed intermediate values that travel between the parser stage and the generator stage.
- parsers.md covers how each annotation is read and validated, including the
@AssistedInjectdetection and the rules that surface as compile errors. - generators.md covers how the typed values are turned into Kotlin source through KotlinPoet, and the two non obvious structural decisions the generators make.
- consumer-contract.md covers the consumer project type names the processor depends on, the runtime flow from a navigation request to a rendered presenter, and how state is preserved across process death.
- testing.md covers the
kctforkand golden file test setup, the test stubs that stand in for consumer types, and the workflow for updating goldens.
Glossary¶
Every architecture page draws from this single vocabulary. New terms introduced on a specific page are defined inline on that page.
- variant. The structural form of a generated artifact. Nine variants exist: a presenter with no runtime parameters, a parameterized presenter, a tab root, a screen
renderer, an overlay renderer, a tab pager renderer, a parent-owned child presenter graph, the application's root presenter binding, and the application's root host
composable. Each variant has its own golden directory under
codegen/processor-test/src/test/resources/golden/. - binding. A Kotlin interface or object that contributes one or more entries to a Metro multibinding. The processor emits one binding per annotated destination and one per annotated UI renderer.
- multibinding. A Metro pattern where many
@Providescontributions are collected into a singleSet<T>that downstream code can request as a whole. The codegen feeds multibindings keyed byNavDestination<*>,NavRouteBinding<*>,NavRootBinding<*>,ScreenContent, andSheetContent. - graph extension. A Metro
@GraphExtensionannotated interface that declares a fragment of a dependency injection graph scoped to a specific type. The codegen emits one for each annotated destination, using the route class as the scope marker. - route. The class the user navigates to. For stack screens and overlays it implements the consumer's
NavRouteinterface. For tab roots it implementsNavRoot. The route doubles as the graph extension's scope marker. - slot. A Decompose primitive that hosts a single child at a time, used for modal overlays. The host filters the active overlay destinations and renders one of them in the slot.
- router. The internal
whenexpression in the processor that picks the right code generator for each parsed annotation. Lives inFileGenerator. - aggregating. A KSP incremental compilation flag.
aggregating = falsetells KSP that the generated file depends only on its own source file, so editing one feature does not force reprocessing of siblings. - Metro. A compile time dependency injection framework by Zac Sweers. The processor emits Metro annotations (
@GraphExtension,@ContributesTo,@Provides,@IntoSet,@BindingContainer). See Metro docs. - Decompose. A Kotlin Multiplatform navigation library by Arkadii Ivanov. The consumer project hosts presenters as Decompose components. See Decompose docs.
- KSP. Kotlin Symbol Processing, the compiler API the processor uses to read annotated symbols and emit Kotlin source files. See KSP docs.
Sub modules¶
The codegen/ directory contains three Gradle sub modules that the architecture pages reference repeatedly.
annotations/is a Kotlin Multiplatform library that defines@NavDestination,@ScreenUi,@SheetUi,@TabUi,@ChildPresenter,@AppRoot, and@AppRootUi. It carries no logic; it is just the surface that consumers depend on.processor/is a JVM library that hosts the KSPSymbolProcessorplus the KotlinPoet generators. This is where every architecture page after pipeline.md lives.processor-test/is a JVM test module that usesdev.zacsweers.kctforkto compile annotated input and assert the output against goldens undersrc/test/resources/golden/. Covered in testing.md.