PSI represents Kotlin source code as a syntax tree. It is the foundation for code analysis, navigation, and refactoring in both the compiler and IDE.
PSI provides syntax information (structure of code). Analysis API builds on top of PSI to provide semantic information (meaning of code).
Source Code → PSI Tree (syntax) → Analysis API (semantics) → Symbols
KtResolvable interface marks PSI elements that can be resolved to Analysis API symbolspsi-api/ - Core PSI interfaces (KtElement, KtExpression, KtDeclaration)psi-impl/ - Implementations and stubs for incremental compilationpsi-frontend-utils/ - Compiler integration utilitiespsi-utils/ - Helper utilitiesKtElement (root interface)
├── KtExpression (calls, literals, operators, etc.)
│ ├── KtCallExpression
│ ├── KtBinaryExpression
│ ├── KtLambdaExpression
│ └── ...
└── KtDeclaration (classes, functions, properties)
├── KtClass, KtObjectDeclaration
├── KtNamedFunction
├── KtProperty
└── ...
KtFile - root of a Kotlin file's PSI treeKtPsiFactory - factory for creating PSI elements programmaticallyVisitor pattern for AST traversal:
KtVisitor<R, D> - base visitor with return type R and data DKtTreeVisitor<D> - recursive tree traversalStubs for performance:
PSI and Analysis API share common development principles. Before contributing:
→ READ analysis/docs/contribution-guide/api-development.md for API design principles → READ analysis/docs/contribution-guide/api-evolution.md for stability and deprecation
J2K Conversion Limitations:
Converting Java PSI classes to Kotlin is NOT always possible. Before attempting:
@JvmName unavailable in interfaces — in some cases it is impossible to convert Java methods to Kotlin properties in a binary-compatible way since @JvmName cannot be used to fix potential clashes.
Platform type handling — IntelliJ Platform APIs use Java types extensively; Kotlin's null-safety interop requires careful handling.
PsiElement.getParent() returning PsiElement!. After conversion to Kotlin it becomes either PsiElement? or PsiElement – both of them are breaking changes. A workaround is to delegate the implementation to a Java method and keep the return type implicit.Binary compatibility — PSI classes are widely used; the binary and source compatibility must be preserved as much as possible.
Guidance: Always consult with PSI maintainers before converting Java classes to Kotlin.
Naming: All PSI types use the Kt prefix (vs Ka for Analysis API).
Stability annotations:
@KtExperimentalApi — Experimental public API@KtImplementationDetail — Internal implementation@KtNonPublicApi — JetBrains-internal APIs@KtPsiInconsistencyHandling — Code handling inconsistent PSI statesJava-Kotlin interop: See the “Java-Kotlin Interoperability” section in api-development.md.
PSI-specific naming patterns:
visit prefix for visitor methods (e.g., visitCallExpression)create prefix for factory methods in KtPsiFactory (e.g., createExpression)General documentation rules from api-development.md apply to all PSI classes. This section describes additional requirements specific to concrete classes implementing KtElement.
Required documentation for concrete KtElement classes:
Class description — A simple explanation of which Kotlin language concept or syntax construct the class represents.
Code example — A code snippet showing the syntax in context. Use ASCII-art markers (^___^) to indicate the specific portion that the class represents.
Example documentation format:
/** * Represents a function call expression. * * ### Example: * * ```kotlin * fun main() { * println(0) * // ^_________^ * } * ``` */ class KtCallExpression : ...
Reference examples:
KtCallExpression and KtAnnotationEntry demonstrate the code example format with ASCII-art markers.Test coverage requirement:
All concrete KtElement classes must be covered by tests in compiler/testData/psi/:
.kt file containing example Kotlin code and a corresponding .txt file showing the expected PSI tree structureKtElement class, add corresponding test cases demonstrating the syntax it representsWHEN modifying PSI interfaces or adding new element types: → Explore psi-api/src/org/jetbrains/kotlin/psi/ for existing patterns
WHEN working with PSI visitors: → READ psi-api/src/org/jetbrains/kotlin/psi/KtVisitor.java → READ psi-api/src/org/jetbrains/kotlin/psi/KtTreeVisitor.java
WHEN creating PSI elements programmatically: → READ psi-api/src/org/jetbrains/kotlin/psi/KtPsiFactory.kt