729afb6149
Fix reference to fir_basics
72 lines
3.4 KiB
Markdown
72 lines
3.4 KiB
Markdown
# Low Level API
|
|
|
|
Low-level API (LL API for short) is an interlayer between Analysis API FIR Implementation and FIR compiler. Low-level API is responsible for:
|
|
|
|
* Finding corresponding `FirElement` by `KtElement`
|
|
* Lazy resolving of `FirDeclaration`
|
|
* Collecting diagnostics for `FirDeclaration`
|
|
* Incremental code analysis
|
|
* Implementing FIR providers using IntelliJ indexes
|
|
|
|
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 lifetime of
|
|
`FirModuleResolveState` is limited by Kotlin Out of Block Modification.
|
|
|
|
## Mapping KtElement to FirElement (KT -> FIR) & Incremental Analysis
|
|
|
|
To implement some stuff in Analysis API, we need to get resolved `FirElement` by the given `KtElement`. Also, this functionality is
|
|
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:
|
|
|
|
* For every `KtFile` we need mapping for, we have `FileStructure` which contains a tree like-structure of `FileStructureElement`
|
|
* `FileStructureElement` can be one of the following:
|
|
* `ReanalyzableStructureElement` represents a non-local declaration that can be incrementally reanalyzed after non-out of block change
|
|
inside it.
|
|
* `NonReanalyzableDeclarationStructureElement` represents non-local declaration which can not be incrementally reanalyzed
|
|
* `RootFileStructureElement` represents file except all declarations inside
|
|
* `FileStructureElement` form a nested tree-like structure
|
|
* 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
|
|
it.
|
|
|
|
The following declarations can be reanalyzed (in other words, can be represented as ReanalyzableStructureElement):
|
|
|
|
* Functions with explicit return type
|
|
* Properties with explicit type
|
|
* Secondary constructors
|
|
* Getters/setters of the property with explicit type
|
|
|
|
# Lazy Declaration resolving
|
|
|
|
FIR in compiler mode works by sequentially running every resolve phase on all files at once like shown in pseudo-code:
|
|
|
|
```kotlin
|
|
for (phase in allResolvePhases) {
|
|
for (file in allFirFiles) {
|
|
runPhaseOnFile(file, phase)
|
|
}
|
|
}
|
|
```
|
|
|
|
Such behavior does not work for the Analysis API. Analysis API needs to resolve one specific declaration to the minimum possible phase. To
|
|
solve that problem, there are *lazy phases*. Lazy phases can be run only on a single declaration, not on the whole `FirFile`.
|
|
|
|
Suppose we need to resolve some `FirDeclaration` to phase number `N`:
|
|
|
|
* First, we resolve containing `FirFile` to the `IMPORTS` phase,
|
|
* Then we resolve file annotations,
|
|
* When we find a non-local container for our declaration as only non-local declarations can be lazily resolved for now,
|
|
* Finally, resolve *only* that container from phase number `1` to phase `N`
|
|
|
|
All resolve happens under containing file-based *write lock*.
|
|
|
|
## Project Module Structure
|
|
|
|
The `FirModuleResolveState` represents a view from a specific module (**root module**) to the dependent modules. A module is represented by:
|
|
|
|
* `FirIdeSourcesSession` the implementation of `FirSession` (FIR compiler representation of a module)
|
|
* `ModuleFileCache` the `KtFile -> FirFile` cache & also caches for FIR providers
|