Open-Source Wikis

/

Kotlin

/

Compiler plugins

/

Compose

JetBrains/kotlin

Compose

Active contributors: Andrei Shikov, Dmitriy Novozhilov, Wojciech Litewka

plugins/compose/ is the compiler plugin behind Jetpack Compose (Android) and Compose Multiplatform. It transforms @Composable functions, inserts the Compose runtime's bookkeeping calls, generates skipping logic for unchanged inputs, and tracks state-read snapshots. Without this plugin, code marked @Composable would fail to compile against Compose runtime expectations.

Purpose

Implement the Compose programming model at the compiler level. Compose's correctness depends on the compiler injecting per-call group identifiers, lifting state reads, and generating "skippable" wrappers for @Composable functions whose parameters didn't change. The plugin makes this happen.

Directory layout

plugins/compose/
├── compiler-hosted/            The plugin entry points (FIR + IR extensions)
├── compose-cli/                CLI integration helpers
├── compose-compiler-cli/       Standalone compose compiler command
├── compose-compiler-tests/     Tests
├── plugins-interactions-testing/  (cross-plugin tests in the parent plugins/ dir)
├── ChangeLog.md                Compose plugin release notes
└── README.md

Key abstractions

Concept Role
@Composable The annotation that opts a function into Compose. The plugin recognizes it during FIR resolution.
Group keys Stable identifiers the plugin injects into composable bodies so Compose can recompose just the affected part of the tree.
Skipping wrappers Generated wrappers that early-return if all inputs are equal to the previous invocation.
State reads The plugin lifts reads of androidx.compose.runtime.State-derived values so Compose can subscribe a composition to changes.
@Stable, @Immutable Annotations the plugin uses to decide whether a parameter participates in skip logic.
Composer parameter The plugin transforms every @Composable function to take an extra Composer parameter, mirroring how the runtime threads its state.

How it works

graph LR
    FIR["FIR<br/>(post-resolution)"] -->|recognizes @Composable| FirExt["Compose FIR extension"]
    FirExt -->|generates contracts| FIR2["FIR with extra<br/>frontend information"]
    Fir2Ir["fir2ir"] --> IR["IR"]
    IR --> IrTransform["Compose IR generator"]
    IrTransform -->|inject Composer<br/>+ group keys + skipping| IR2["Transformed IR"]
    IR2 --> Backend["JVM / JS / Wasm / Native"]

The plugin runs in two layers: a FIR extension that recognizes Compose constructs and supplies frontend information needed for resolve, and an IR generator (IrGenerationExtension) that does the heavy mechanical transformation.

Multiplatform

Compose is one of Kotlin's flagship Multiplatform stories. The plugin is target-agnostic — it transforms IR before per-target lowering, so the same plugin produces correct output for Android, iOS (Native), desktop (JVM), Wasm, and JS targets.

The runtime that the transformed code calls into (androidx.compose.runtime) lives in separate repositories: AndroidX (Google) for the Android-flavored runtime and JetBrains/compose-multiplatform for the multiplatform runtime. This repository ships only the compiler plugin.

KGP integration

libraries/tools/kotlin-compose-compiler/ is the Gradle DSL counterpart. It applies the plugin and exposes Compose-specific options:

plugins {
    kotlin("multiplatform")
    id("org.jetbrains.kotlin.plugin.compose")
}

Versioning

Compose's compiler plugin is tightly coupled to specific runtime versions because of API contracts. The ChangeLog.md in the plugin's directory tracks compatibility.

Tests

plugins/compose/compose-compiler-tests/ runs golden-file tests against checked-in reference output. The reference output captures the IR after Compose transformation; mismatches indicate the plugin's transformation has changed.

Integration points

  • Backend-agnostic: runs as IR generator, so all backends (JVM, JS, Wasm, Native) get correct output.
  • Consumed by: any Kotlin Multiplatform / Android project using Compose.
  • Co-traveler: androidx.compose.runtime and the JetBrains Compose Multiplatform runtime — defined elsewhere, used at runtime.

Where to start

For a transformation-behavior change: plugins/compose/compiler-hosted/ and look for the IR-transformer classes. For Compose-specific frontend behavior (e.g., a new @Composable rule): the FIR extension in the same module.

See plugins/index.md for the broader plugin landscape.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Compose – Kotlin wiki | Factory