Open-Source Wikis

/

Kotlin

/

Compiler

/

PSI and parser

JetBrains/kotlin

PSI and parser

Active contributors: Dmitriy Novozhilov, Kirill Rakhman

compiler/psi/ holds the lexer, parser, and PSI (Program Structure Interface) types for Kotlin. Every Kotlin source file that enters the compiler is first turned into a KtFile here, and both K1 and K2 build their representations on top of that.

Purpose

Parse Kotlin source text into a structured, IDE-friendly tree of PSI nodes. The PSI tree is intentionally close to the source: comments, whitespace, and trivia are preserved so that the IDE plugin can use the same trees for editing and refactoring.

Directory layout

compiler/psi/
├── psi/             Core PSI types (Kt*)
├── psi-api/         Public-facing PSI surface
├── parser/          Kotlin grammar / parser implementation
├── lexer/           Kotlin lexer
├── stub/            Indexing / stubbed forms used by IDE indexes
└── light-tree/      Lightweight tree representation for fast paths

Key abstractions

Type Where Role
KtFile compiler/psi/.../KtFile.kt Root node for a Kotlin source file.
KtClass, KtNamedFunction, KtProperty, KtCallExpression, ... compiler/psi/.../psi/ Declaration and expression nodes.
KotlinLexer compiler/psi/.../lexer/KotlinLexer.kt Token-producing lexer.
KotlinParser compiler/psi/.../parser/KotlinParser.kt Top-level parser entry point.
KtElement compiler/psi/.../KtElement.kt Common supertype of all Kotlin PSI elements.

PSI is built on top of IntelliJ's psi infrastructure (com.intellij.psi), which is pulled in via intellij-core. As a result the PSI types feel very IDE-flavored.

Two tree shapes

There are actually two PSI-like representations:

  • Full PSI (KtFile and its descendants) — heavyweight, IDE-friendly, retains all whitespace and trivia. Used by the IDE plugin and by any path that needs to read or modify source.
  • Light tree (compiler/psi/light-tree/) — a much cheaper tree representation used by parts of the compiler that don't need full PSI. K2 has a "light tree" path that builds raw FIR directly from this representation, skipping a heavy PSI allocation.

Both share the same lexer and parser front-end; they differ in what tree structure they materialize.

Stubs

compiler/psi/stub/ defines the stub form of declarations — a compact, indexable summary used by IntelliJ's indexes. Stub-aware PSI lets the IDE answer "show me all classes named Foo" without parsing every file.

How K1 and K2 use PSI

Both frontends start from PSI:

  • K1 treats PSI as the source of truth for resolution. BindingContext keys are PSI elements (KtCallExpression, KtReferenceExpression, ...).
  • K2 builds raw FIR from PSI in compiler/fir/raw-fir/ and then walks FIR alone. The PSI is retained as a back-reference (fir.source) so diagnostics can still be reported on a PSI element.

Light classes

Java-aware tooling (the IDEA Java plugin, Lombok, etc.) often wants a Java-style view of a Kotlin declaration. PSI grew "light classes" — synthesized PsiClass views over Kotlin elements:

  • compiler/light-classes/ — the K1 implementation.
  • analysis/symbol-light-classes/ — the K2 / Analysis API implementation.

Both produce the same Java PSI shapes from different inputs.

Stability

The PSI surface is very stable; external code (notably the IntelliJ Kotlin plugin) reads it heavily. Adding a new PSI element requires propagating through both K1 and K2 raw-FIR builders, and through the light-class generators. Read compiler/psi/AGENTS.md before changing the API.

Integration points

  • Produced by the lexer/parser from Kotlin source.
  • Consumed by K1 (compiler/frontend/), the K2 raw-FIR builder (compiler/fir/raw-fir/), light classes (compiler/light-classes/, analysis/symbol-light-classes/), and IDE tooling.
  • Indexed in stub form by IntelliJ.

See frontend-fir.md, frontend-k1.md, and the analysis API for the consumers.

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

PSI and parser – Kotlin wiki | Factory