mirror of https://github.com/rust-lang/rls
Update the architecture.md file with the latest repo and code links
Signed-off-by: JmPotato <ghzpotato@gmail.com>
This commit is contained in:
parent
3df74381f3
commit
122ee0e1f2
|
@ -5,7 +5,7 @@ In addition to the document below, an architecture overview can be found at @nrc
|
|||
|
||||
Here we aim to explain in-depth how RLS obtains the underlying data to drive its indexing features as the context for the upcoming IDE planning and discussion at the 2019 Rust All-Hands.
|
||||
|
||||
Also the [rust-analyzer](https://github.com/rust-analyzer/rust-analyzer/blob/e0d8c86563b72e5414cf10fe16da5e88201447e2/guide.md) guide is a great resource as it covers a lot of common ground.
|
||||
Also the [rust-analyzer](https://github.com/rust-analyzer/rust-analyzer/blob/1d53f695f0408f47c5cce5cefa471eb0e86b0db7/docs/dev/guide.md) guide is a great resource as it covers a lot of common ground.
|
||||
|
||||
## High-level overview
|
||||
|
||||
|
@ -27,16 +27,17 @@ once, where we dump and cache the resulting data into a JSON file, which only ne
|
|||
## Information flow (in-depth)
|
||||
The current flow is as follows:
|
||||
```
|
||||
rustc -> librustc_save_analysis -> rls_data -> rls_analysis -> rls
|
||||
rustc -> rustc_save_analysis -> rls_data -> rls_analysis -> rls
|
||||
```
|
||||
|
||||
### [librustc_save_analysis](https://github.com/rust-lang/rust/tree/master/src/librustc_save_analysis)
|
||||
### [rustc_save_analysis](https://github.com/rust-lang/rust/tree/master/compiler/rustc_save_analysis)
|
||||
|
||||
The Rust compiler includes the [`librustc_save_analysis`](https://github.com/rust-lang/rust/tree/master/src/librustc_save_analysis) crate, which allows to dump the knowledge about the currently compiled crate. The main entry point is [`process_crate`](https://github.com/rust-lang/rust/blob/7164a9f151a56316a382d8bc2b15ccf373e129ca/src/librustc_save_analysis/lib.rs#L1119), which walks the post-macro-expansion AST and [saves](https://github.com/rust-lang/rust/blob/7164a9f151a56316a382d8bc2b15ccf373e129ca/src/librustc_save_analysis/lib.rs#L1146) the collected knowledge either by [dumping to a JSON file](https://github.com/rust-lang/rust/blob/7164a9f151a56316a382d8bc2b15ccf373e129ca/src/librustc_save_analysis/lib.rs#L1074-L1090) or by [calling back with resulting data structure](https://github.com/rust-lang/rust/blob/7164a9f151a56316a382d8bc2b15ccf373e129ca/src/librustc_save_analysis/lib.rs#L1092-L1117).
|
||||
The Rust compiler includes the [`rustc_save_analysis`](https://github.com/rust-lang/rust/tree/master/compiler/rustc_save_analysis) crate, which allows to dump the knowledge about the currently compiled crate. The main entry point is [`process_crate`](https://github.com/rust-lang/rust/blob/e08d5693609a659e45025b8ea4dbd9efa342fa68/compiler/rustc_save_analysis/src/lib.rs#L978), which walks the post-macro-expansion AST and [saves](https://github.com/rust-lang/rust/blob/e08d5693609a659e45025b8ea4dbd9efa342fa68/compiler/rustc_save_analysis/src/lib.rs#L1011) the collected knowledge either by [dumping to a JSON file](https://github.com/rust-lang/rust/blob/e08d5693609a659e45025b8ea4dbd9efa342fa68/compiler/rustc_save_analysis/src/lib.rs#L953-L965) or by [calling back with resulting data structure](https://github.com/rust-lang/rust/blob/e08d5693609a659e45025b8ea4dbd9efa342fa68/compiler/rustc_save_analysis/src/lib.rs#L967-L976).
|
||||
|
||||
### [rls_data](https://github.com/rust-dev-tools/rls-data)
|
||||
### [rls_data](https://github.com/rust-lang/rls/tree/master/rls-data)
|
||||
|
||||
As mentioned previously, the returned data structure is [`rls_data::Analysis`](https://github.com/rust-lang/rls/blob/3df74381f37617ec800537c11fb0c3130f5f3616/rls-data/src/lib.rs#L11-L26) inside the [`rls_data`](https://github.com/rust-lang/rls/tree/master/rls-data) crate:
|
||||
|
||||
As mentioned previously, the returned data structure is [`rls_data::Analysis`](https://github.com/rust-dev-tools/rls-data/blob/9edbe8b4947c10ef670c4723be375c6944cab640/src/lib.rs#L30-L48) inside the [`rls_data`](https://github.com/rust-dev-tools/rls-data) crate:
|
||||
```rust
|
||||
/// Basically a type alias, we refer to nodes with HIR ids.
|
||||
/// All of the below nodes are either identified by or refer to those IDs.
|
||||
|
@ -70,23 +71,23 @@ pub struct Analysis {
|
|||
}
|
||||
```
|
||||
|
||||
### [rls_analysis](https://github.com/rust-dev-tools/rls-analysis)
|
||||
### [rls_analysis](https://github.com/rust-lang/rls/tree/master/rls-analysis)
|
||||
|
||||
This [crate](https://github.com/rust-dev-tools/rls-analysis) is responsible for loading and stitching multiple of
|
||||
This [crate](https://github.com/rust-lang/rls/tree/master/rls-analysis) is responsible for loading and stitching multiple of
|
||||
the `rls_data::Analysis` data structures into a single, coherent interface.
|
||||
|
||||
Whereas `rls_data` format can be considered an implementation detail that might
|
||||
change, this crate aims to provide a 'stable' API.
|
||||
|
||||
Another reason behind that is that each of those structures contains data centric
|
||||
to the crate that was being compiled - this [lowering](https://github.com/rust-dev-tools/rls-analysis/blob/bd82c9b38b56e53bbfb199569a32b392056964fd/src/lowering.rs#L167)
|
||||
to the crate that was being compiled - this [lowering](https://github.com/rust-lang/rls/blob/3df74381f37617ec800537c11fb0c3130f5f3616/rls-analysis/src/lowering.rs#L161)
|
||||
cross-references the data
|
||||
and indexes it, resulting in a database spanning multiple crates that can be
|
||||
queried like 'across known crates, find all references to a definition at a
|
||||
given span' or similarly.
|
||||
|
||||
We are capable of updating the index with new crate data. Whenever we encounter
|
||||
a new crate, we [record and translate](https://github.com/rust-dev-tools/rls-analysis/blob/bd82c9b38b56e53bbfb199569a32b392056964fd/src/lowering.rs#L131-L154)
|
||||
a new crate, we [record and translate](https://github.com/rust-lang/rls/blob/3df74381f37617ec800537c11fb0c3130f5f3616/rls-analysis/src/lowering.rs#L122-L144)
|
||||
the crate id into our database-wide crate id mapping.
|
||||
|
||||
However, if data for an already lowered crate is loaded again, we simply
|
||||
|
@ -94,7 +95,7 @@ replace the definitions for a given crate and re-index.
|
|||
|
||||
One interesting edge case is when we lower data for crates having the same name, such
|
||||
as binary and `#[cfg(test)]`-compiled version of it. We need to ensure we lower a given definition
|
||||
[only once](https://github.com/rust-dev-tools/rls-analysis/blob/bd82c9b38b56e53bbfb199569a32b392056964fd/src/lowering.rs#L258-L263)
|
||||
[only once](https://github.com/rust-lang/rls/blob/3df74381f37617ec800537c11fb0c3130f5f3616/rls-analysis/src/lowering.rs#L271-L276)
|
||||
, even if it technically is repeated across multiple crates.
|
||||
|
||||
### rls
|
||||
|
@ -104,6 +105,7 @@ the data - that happens inside the RLS.
|
|||
|
||||
In general, apart from being an LSP server, the RLS is also concerned with
|
||||
build orchestration, and coordination of other components, such as
|
||||
|
||||
* Racer for autocompletion
|
||||
* Cargo for project layout detection and initial build coordination
|
||||
* internal virtual file system (VFS) for handling in-memory text buffers,
|
||||
|
@ -113,7 +115,7 @@ build orchestration, and coordination of other components, such as
|
|||
|
||||
After doing initial compilation with Cargo, we cache a subgraph of the inter-crate
|
||||
dependency graph along with compilation invocations and input files for the
|
||||
crates we're interested in (inside the [primary or path-based packages](https://github.com/rust-lang/rls/blob/d7c2eb8b641ae7e6d7145c268249f28efcf5467c/src/build/cargo.rs#L376-L381))
|
||||
crates we're interested in (inside the [primary or path-based packages](https://github.com/rust-lang/rls/blob/3df74381f37617ec800537c11fb0c3130f5f3616/rls/src/build/cargo.rs#L358-L363))
|
||||
which we later rerun manually.
|
||||
|
||||
In our case Cargo is configured to use a separate target directory
|
||||
|
@ -131,31 +133,33 @@ proc macros initially and when needed (e.g. by modifying a file causing
|
|||
|
||||
## Build scheduling
|
||||
|
||||
On every relevant file change we [mark files as dirty](https://github.com/rust-lang/rls/blob/d7c2eb8b641ae7e6d7145c268249f28efcf5467c/src/actions/notifications.rs#L131) and schedule a normal build.
|
||||
On every relevant file change we [mark files as dirty](https://github.com/rust-lang/rls/blob/3df74381f37617ec800537c11fb0c3130f5f3616/rls/src/actions/notifications.rs#L113) and schedule a normal build.
|
||||
|
||||
We currently discern two [build priorities](https://github.com/rust-lang/rls/blob/3df74381f37617ec800537c11fb0c3130f5f3616/rls/src/build/mod.rs#L114-L124):
|
||||
|
||||
We currently discern two [build priorities](https://github.com/rust-lang/rls/blob/67bce0bdcf2db1d3c05bb1a3d87df9e66eaec7db/src/build/mod.rs#L124-L133):
|
||||
* Normal
|
||||
* Cargo
|
||||
|
||||
The latter is scheduled whenever a change happened that can impact entire
|
||||
project. This includes:
|
||||
* [initial build](https://github.com/rust-lang/rls/blob/67f2a86c13a34dcb231436c2f1db8900fece3c09/src/actions/mod.rs#L331)
|
||||
* [configuration change](https://github.com/rust-lang/rls/blob/67f2a86c13a34dcb231436c2f1db8900fece3c09/src/actions/notifications.rs#L207)
|
||||
|
||||
* [initial build](https://github.com/rust-lang/rls/blob/3df74381f37617ec800537c11fb0c3130f5f3616/rls/src/actions/mod.rs#L328)
|
||||
* [configuration change](https://github.com/rust-lang/rls/blob/3df74381f37617ec800537c11fb0c3130f5f3616/rls/src/actions/notifications.rs#L116)
|
||||
(can potentially build different set of packages)
|
||||
* [Cargo.toml change](https://github.com/rust-lang/rls/blob/67f2a86c13a34dcb231436c2f1db8900fece3c09/src/actions/notifications.rs#L273)
|
||||
* [Cargo.toml change](https://github.com/rust-lang/rls/blob/3df74381f37617ec800537c11fb0c3130f5f3616/rls/src/actions/notifications.rs#L264)
|
||||
(ditto)
|
||||
* [build directory](https://github.com/rust-lang/rls/blob/67bce0bdcf2db1d3c05bb1a3d87df9e66eaec7db/src/build/mod.rs#L479-L486) changed
|
||||
* [modified file](https://github.com/rust-lang/rls/blob/d6570bc62575e03412340e55620cbf24fe59f772/src/build/cargo_plan.rs#L379-L383) in a package we didn't build
|
||||
* [build.rs](https://github.com/rust-lang/rls/blob/d6570bc62575e03412340e55620cbf24fe59f772/src/build/cargo_plan.rs#L392-L396) modification
|
||||
* [build directory](https://github.com/rust-lang/rls/blob/3df74381f37617ec800537c11fb0c3130f5f3616/rls/src/build/mod.rs#L468-L472) changed
|
||||
* [modified file](https://github.com/rust-lang/rls/blob/3df74381f37617ec800537c11fb0c3130f5f3616/rls/src/build/cargo_plan.rs#L350-L354) in a package we didn't build
|
||||
* [build.rs](https://github.com/rust-lang/rls/blob/3df74381f37617ec800537c11fb0c3130f5f3616/rls/src/build/cargo_plan.rs#L359-L360) modification
|
||||
|
||||
On a normal build, we map from dirty files to dirty crates, sort those
|
||||
topologically and run rustc in-process for each crate ourselves.
|
||||
With each compilation in-process we directly
|
||||
[receive `rls_data::Analysis`](https://github.com/rust-lang/rls/blob/41bc0bf70bbbc8661f0c7f9cef700be5e105a926/src/build/rustc.rs#L334-L347)
|
||||
[receive `rls_data::Analysis`](https://github.com/rust-lang/rls/blob/3df74381f37617ec800537c11fb0c3130f5f3616/rls/src/build/rustc.rs#L293-L305)
|
||||
in a callback,
|
||||
[mark corresponding files as built](https://github.com/rust-lang/rls/blob/67bce0bdcf2db1d3c05bb1a3d87df9e66eaec7db/src/build/mod.rs#L493-L505)
|
||||
[mark corresponding files as built](https://github.com/rust-lang/rls/blob/3df74381f37617ec800537c11fb0c3130f5f3616/rls/src/build/mod.rs#L478-L490)
|
||||
and finally
|
||||
[update our analysis database](https://github.com/rust-lang/rls/blob/d7c2eb8b641ae7e6d7145c268249f28efcf5467c/src/actions/post_build.rs#L208-L223)
|
||||
[update our analysis database](https://github.com/rust-lang/rls/blob/3df74381f37617ec800537c11fb0c3130f5f3616/rls/src/actions/post_build.rs#L180-L184)
|
||||
with currently built data for each rebuilt crate.
|
||||
|
||||
If there are still files that are modified after we scheduled a build (user kept
|
||||
|
@ -173,10 +177,10 @@ JSON save-analysis files for our non-path dependencies.
|
|||
### VFS
|
||||
|
||||
To allow running analysis on unsaved in-memory text buffers, we use the
|
||||
[`rls-vfs`](https://github.com/rust-dev-tools/rls-vfs)
|
||||
[`rls-vfs`](https://github.com/rust-lang/rls/tree/master/rls-vfs)
|
||||
crate to act as our virtual file system.
|
||||
|
||||
The Rust compiler supports using custom file providers via [`FileLoader`](https://github.com/rust-lang/rust/blob/79d8a0fcefa5134db2a94739b1d18daa01fc6e9f/src/libsyntax/source_map.rs#L58-L68) trait, which [we use](https://github.com/rust-lang/rls/blob/67bce0bdcf2db1d3c05bb1a3d87df9e66eaec7db/src/build/rustc.rs#L385-L402).
|
||||
The Rust compiler supports using custom file providers via [`FileLoader`](https://github.com/rust-lang/rust/blame/f19851069efd6ee1fe899a469f08ad2d66e76050/compiler/rustc_span/src/source_map.rs#L98-L105) trait, which [we use](https://github.com/rust-lang/rls/blob/3df74381f37617ec800537c11fb0c3130f5f3616/rls/src/build/rustc.rs#L355-L367).
|
||||
|
||||
It delegates to the real file system
|
||||
whenever there are no buffered changes to a file but serves the unsaved buffers [from the VFS](https://github.com/rust-lang/rls/blob/67bce0bdcf2db1d3c05bb1a3d87df9e66eaec7db/src/build/rustc.rs#L79) otherwise.
|
||||
whenever there are no buffered changes to a file but serves the unsaved buffers [from the VFS](https://github.com/rust-lang/rls/blob/3df74381f37617ec800537c11fb0c3130f5f3616/rls/src/build/rustc.rs#L54) otherwise.
|
||||
|
|
Loading…
Reference in New Issue