Class KotlinPsi
The only class in Copilot permitted to import
org.jetbrains.kotlin.*. Everything else works through
invalid reference
KtNodeRef
Uses the lightweight PSI path — CoreApplicationEnvironment plus a
KotlinParserDefinition — and deliberately not
KotlinCoreEnvironment.createForProduction, which loads the whole
compiler frontend and its extension registry for no benefit here: Copilot
needs exact source offsets, not resolved types. Types come from reflection on
the live component instead.
Measured on this path: ~240 ms one-off environment setup, ~1.2 ms to parse a
typical view, ~2 MB retained heap. See
kotlin-support/PHASE-0-FINDINGS.md.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic interfaceWork that reads a parse tree. -
Method Summary
Modifier and TypeMethodDescriptionstatic <T> TinPsi(KotlinPsi.PsiWork<T> work) Runs work that reads a parse tree, with no other such work running.static org.jetbrains.kotlin.psi.KtFileParses Kotlin source text.
-
Method Details
-
parse
Parses Kotlin source text.The returned tree must not be retained past the operation that asked for it: it holds the whole PSI graph alive, and this class keeps its environment for the lifetime of the JVM.
- Parameters:
fileName- the file's name, used only for messages and to pick the parsertext- the source- Returns:
- the parsed file
-
inPsi
Runs work that reads a parse tree, with no other such work running.IntelliJ PSI is not thread safe, and a tree is not independent of the others: every file parsed here shares one project environment and one
PsiManager, so two threads walking two different files still touch shared state.parse(java.lang.String, java.lang.String)being synchronized only makes parsing safe — it says nothing about the traversal that follows, which is where nearly all of the time is spent.That matters because Copilot genuinely does this concurrently.
get-propertiesis dispatched asynchronously (CopilotSession#handleMessageAsync) while the property commands run on the caller's thread, so selecting a component can have the panel reading a Kotlin view on one thread while an edit rewrites one on another.One lock for all of it, rather than one per file, because the shared state is the environment rather than the tree. The cost is small — a parse is about 1 ms and a property lookup less — and the alternative is a data race whose symptom would be a corrupted tree in a developer's IDE.
- Type Parameters:
T- what the work produces- Parameters:
work- the work to run- Returns:
- its result
- Throws:
IOException- if the work cannot read a source
-