[LL FIR] update low-level-api-fir.md doc
This commit is contained in:
committed by
Space Team
parent
71f9c101a1
commit
3ce3c50b92
@@ -1,71 +1,66 @@
|
|||||||
# Low Level API
|
# Low-Level API FIR
|
||||||
|
|
||||||
Low-level API (LL API for short) is an interlayer between Analysis API FIR Implementation and FIR compiler. Low-level API is responsible for:
|
Low-level API FIR (LL API or LL FIR for short) is an interlayer between Analysis API FIR Implementation and FIR compiler.
|
||||||
|
Low-level API FIR is responsible but not limited for:
|
||||||
* Finding corresponding `FirElement` by `KtElement`
|
- Finding corresponding [FirElement](../../../compiler/fir/tree/gen/org/jetbrains/kotlin/fir/FirElement.kt) by `KtElement`
|
||||||
* Lazy resolving of `FirDeclaration`
|
- Lazy resolution of declarations ([FirElementWithResolveState](../../../compiler/fir/tree/gen/org/jetbrains/kotlin/fir/FirElementWithResolveState.kt))
|
||||||
* Collecting diagnostics for `FirDeclaration`
|
- Collecting diagnostics for [FirDeclaration](../../../compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirDeclaration.kt)
|
||||||
* Incremental code analysis
|
- Incremental code analysis
|
||||||
* Implementing FIR providers using IntelliJ indexes
|
- Implementing FIR providers using the Analysis API implementor's declaration/package/etc. providers (e.g., IntelliJ indexes in the IDE)
|
||||||
|
|
||||||
You can read about how FIR compiler works [here](../../fir/fir-basics.md).
|
You can read about how FIR compiler works [here](../../fir/fir-basics.md).
|
||||||
|
|
||||||
The entry point for LL API is `FirModuleResolveState`.` FirModuleResolveState` is a view of project modules visible from the current module.
|
The entry point for LL API is [LLFirResolveSession](../../../analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/LLFirResolveSession.kt).
|
||||||
The lifetime of
|
`LLFirResolveSession` represents a project view from a use-site [KtModule](../../../analysis/project-structure/src/org/jetbrains/kotlin/analysis/project/structure/KtModule.kt).
|
||||||
`FirModuleResolveState` is limited by Kotlin Out of Block Modification.
|
The lifetime of `LLFirResolveSession` is limited by modification events.
|
||||||
|
|
||||||
## Mapping KtElement to FirElement (KT -> FIR) & Incremental Analysis
|
[LowLevelFirApiFacade](../../../analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/LowLevelFirApiFacade.kt)
|
||||||
|
file contains a useful API surface to interact with Low Level API FIR from Analysis API FIR.
|
||||||
|
|
||||||
To implement some stuff in Analysis API, we need to get resolved `FirElement` by the given `KtElement`. Also, this functionality is
|
## Documentation
|
||||||
considered to be used not very often (mostly, for the files opened in the editor) as it resolves declarations to the `BODY_RESOLVE` and
|
|
||||||
collects `KT -> FIR` mappings for it.
|
|
||||||
|
|
||||||
Finding `KT -> FIR` mappings works like the following:
|
There are a bunch of different areas.
|
||||||
|
Docs for each area are sorted by context depth – from the basic overview to the deepest implementation details.
|
||||||
* For every `KtFile` we need mapping for, we have `FileStructure` which contains a tree like-structure of `FileStructureElement`
|
- Mapping from `KtElement` to `FirElement` (*KT -> FIR*) & Incremental Analysis & Collecting diagnostics
|
||||||
* `FileStructureElement` can be one of the following:
|
1. [FirElementBuilder](../../../analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/element/builder/FirElementBuilder.kt)
|
||||||
* `ReanalyzableStructureElement` represents a non-local declaration that can be incrementally reanalyzed after non-out of block change
|
is responsible for mapping from `KtElement` to `FirElement`.
|
||||||
inside it.
|
2. [FileStructure](../../../analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructure.kt)
|
||||||
* `NonReanalyzableDeclarationStructureElement` represents non-local declaration which can not be incrementally reanalyzed
|
is a tree like-structure of `FileStructureElement` which is associated with some `KtFile`.
|
||||||
* `RootFileStructureElement` represents file except all declarations inside
|
Aggregates information about *KT -> FIR* mapping and diagnostics for associated file.
|
||||||
* `FileStructureElement` form a nested tree-like structure
|
3. [FileStructureElement](../../../analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructureElement.kt)
|
||||||
* Then we want to get `KT -> FIR` mapping we find containing `FileStructureElement`. If is not up-to-date we rebuild it and then take from
|
is a representation of specific `KtElement`.
|
||||||
it.
|
Is responsible for *KT -> FIR* mapping and diagnostics for the specific `KtElement`.
|
||||||
|
4. [FileStructureElementDiagnosticRetriever](../../../analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostics/FileStructureElementDiagnosticRetriever.kt)
|
||||||
The following declarations can be reanalyzed (in other words, can be represented as ReanalyzableStructureElement):
|
is responsible to collect diagnostics for `FileStructureElement`.
|
||||||
|
5. [LLFirDeclarationModificationService](../../../analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/LLFirDeclarationModificationService.kt)
|
||||||
* Functions with explicit return type
|
is a service which is responsible for `FileStructure` invalidation in the case of associated PSI modification.
|
||||||
* Properties with explicit type
|
- Lazy resolution
|
||||||
* Secondary constructors
|
1. [FirResolvePhase](../../../compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirResolvePhase.kt)
|
||||||
* Getters/setters of the property with explicit type
|
to understand what the compiler phases are and what is the basic difference between the CLI and the Analysis API modes.
|
||||||
|
2. [LLFirModuleLazyDeclarationResolver](../../../analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirModuleLazyDeclarationResolver.kt)
|
||||||
# Lazy Declaration resolving
|
is the entry point for lazy resolution.
|
||||||
|
Receives some `FirElementWithResolveState` element and a desired phase and resolve this element to this phase.
|
||||||
FIR in compiler mode works by sequentially running every resolve phase on all files at once like shown in pseudo-code:
|
3. [LLFirResolveDesignationCollector](../../../analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirResolveDesignationCollector.kt)
|
||||||
|
is a designation collector.
|
||||||
```kotlin
|
Collects `LLFirResolveTarget` for the specific `FirElementWithResolveState`.
|
||||||
for (phase in allResolvePhases) {
|
Decides which element can be resolved lazily and which cannot.
|
||||||
for (file in allFirFiles) {
|
4. [LLFirResolveTarget](../../../analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/targets/LLFirResolveTarget.kt)
|
||||||
runPhaseOnFile(file, phase)
|
is an instruction on how to resolve specific `FirElementWithResolveState`.
|
||||||
}
|
5. [LLFirLazyResolverRunner](../../../analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirLazyResolverRunner.kt)
|
||||||
}
|
is responsible
|
||||||
```
|
for running [LLFirLazyResolver](../../../analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirLazyResolver.kt)
|
||||||
|
for the specific phase and making sure that it worked correctly.
|
||||||
Such behavior does not work for the Analysis API. Analysis API needs to resolve one specific declaration to the minimum possible phase. To
|
6. [LLFirTargetResolver](../../../analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirTargetResolver.kt)
|
||||||
solve that problem, there are *lazy phases*. Lazy phases can be run only on a single declaration, not on the whole `FirFile`.
|
is the core part of lazy resolution.
|
||||||
|
We have a separate implementation of `LLFirTargetResolver` for each compiler phase,
|
||||||
Suppose we need to resolve some `FirDeclaration` to phase number `N`:
|
each of which is responsible for all the resolution logic for the associated phase.
|
||||||
|
7. [LLFirLockProvider](../../../analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/builder/LLFirLockProvider.kt)
|
||||||
* First, we resolve containing `FirFile` to the `IMPORTS` phase,
|
is responsible for locking logic which is widely used by `LLFirTargetResolver` during resolution.
|
||||||
* Then we resolve file annotations,
|
- [ContextCollector](../../../analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/ContextCollector.kt)
|
||||||
* When we find a non-local container for our declaration as only non-local declarations can be lazily resolved for now,
|
represents resolution context of a specific place in code (a context)
|
||||||
* Finally, resolve *only* that container from phase number `1` to phase `N`
|
|
||||||
|
|
||||||
All resolve happens under containing file-based *write lock*.
|
|
||||||
|
|
||||||
## Project Module Structure
|
## Project Module Structure
|
||||||
|
|
||||||
The `FirModuleResolveState` represents a view from a specific module (**root module**) to the dependent modules. A module is represented by:
|
The `LLFirResolveSession` represents a view from a specific module (**root module**) to the dependent modules. A module is represented by:
|
||||||
|
* `LLFirSession` – the implementation of `FirSession` (FIR compiler representation of a module)
|
||||||
* `FirIdeSourcesSession` the implementation of `FirSession` (FIR compiler representation of a module)
|
* `ModuleFileCache` – the `KtFile -> FirFile` cache & also caches for FIR providers
|
||||||
* `ModuleFileCache` the `KtFile -> FirFile` cache & also caches for FIR providers
|
|
||||||
|
|||||||
Reference in New Issue
Block a user