JetBrains/kotlin
Frontend (K1 / FE 1.0)
Active contributors: Dmitriy Novozhilov, Alexander Udalov, Mikhail Glukhikh
K1 is the legacy Kotlin frontend. It pre-dates FIR by a decade and shipped as the default frontend until Kotlin 2.0 (May 2024). It is no longer the focus of new language work, but it stays in the tree because the IntelliJ Kotlin plugin still ships a K1 mode for a long compatibility window, and several tooling paths depend on it.
Purpose
Take a parsed KtFile (PSI) and produce a fully resolved program model in the form of BindingContext plus descriptors (core/descriptors). That model is then either translated to backend IR (via compiler/ir/ir.psi2ir/) or consumed by the legacy Analysis API surface (analysis/analysis-api-fe10/).
Directory layout
compiler/
├── frontend/ Core K1 resolution
├── frontend.common/ Shared utilities
├── frontend.common.jvm/ JVM-specific shared utilities
├── frontend.common-psi/ PSI helpers used from frontend.common
├── frontend.java/ Java interop frontend (KS-side Java reading)
├── resolution/ Resolution algorithms (call resolution, ...)
├── resolution.common/ Shared resolution code
├── resolution.common.jvm/ JVM resolution add-ons
├── light-classes/ Synthesized Java views of Kotlin declarations
├── psi/ PSI parser (used by both K1 and K2)
└── core/descriptors/ Declaration model (descriptors)The line between compiler/frontend/ and core/descriptors/ is conceptual — descriptors are the modeling layer K1 outputs, and the frontend is the resolution machinery that creates them.
Key abstractions
| Type | Where | Role |
|---|---|---|
BindingContext |
compiler/frontend/.../BindingContext.kt |
Map of resolution facts (call → resolved call, expression → type, etc.). |
BindingTrace |
compiler/frontend/.../BindingTrace.kt |
Mutable view of BindingContext used during resolve. |
DeclarationDescriptor |
core/descriptors/.../DeclarationDescriptor.java |
Root of the descriptor hierarchy. Modeled in Java for legacy reasons. |
KotlinType |
core/descriptors/.../KotlinType.kt |
K1's type. (Note: K2 uses ConeKotlinType instead.) |
LazyTopDownAnalyzer |
compiler/frontend/.../LazyTopDownAnalyzer.kt |
The K1 resolution driver. |
CallResolver, ArgumentTypeResolver, ... |
compiler/resolution/... |
The call-resolution algorithms. |
JavaResolver |
compiler/frontend.java/... |
Reads Java sources/classes into descriptors. |
How resolution works
K1 uses a lazy, top-down resolution model. When the compiler asks for the type of an expression, the relevant declarations are resolved on demand and the results are cached in BindingContext. Unlike K2, there are no explicit phases — the work is driven by the call graph of resolution requests.
The PSI is shared with K2. The K1 frontend just consumes it differently and produces descriptors instead of FIR symbols.
Diagnostics
K1 diagnostics are reported through the BindingTrace and registered in checker classes under compiler/frontend/.../checkers. The diagnostic IDs are different from K2's, but for many features there is a 1:1 map between a K1 and a K2 diagnostic.
psi2ir
compiler/ir/ir.psi2ir/ is the K1 → backend-IR translator (analogous to compiler/fir/fir2ir/ for K2). It walks the K1-resolved PSI tree and emits backend IR using the shared IR types from compiler/ir/ir.tree/. Once IR is produced, the rest of the compiler is the same.
Why K1 still exists
Three reasons:
- IDE plugin compatibility window. The IntelliJ Kotlin plugin (in
JetBrains/intellij-community) ships K1 and K2 modes for a long time. Until that ends, the K1 frontend has to keep working. The Analysis API has aanalysis-api-fe10/implementation backed by K1 to support this. - Light classes for Java interop.
compiler/light-classes/(the K1 light-class generator) is still used by some external tools that have not migrated to the symbol-based light classes inanalysis/symbol-light-classes/. - Older Kotlin language versions. Building with
-language-version 1.9or below uses K1.
Integration points
- Consumed by
compiler/ir/ir.psi2ir/(legacy path to IR/backends). - Consumed by
analysis/analysis-api-fe10/. - CLI:
kotlinc -language-version 1.9(or earlier) selects K1 explicitly.
Where to start
If you have to touch K1, find the parallel implementation in K2 first — it is usually clearer and serves as a model. New diagnostics generally land in K2 only. Bug fixes in K1 should keep the K2 behavior in mind so the two stay aligned.
See Frontend (K2 / FIR) for the modern frontend, and patterns and conventions for the K1/K2 dual-implementation pattern.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.