aboutsummaryrefslogtreecommitdiff
path: root/ARCHITECTURE.md
diff options
context:
space:
mode:
Diffstat (limited to 'ARCHITECTURE.md')
-rw-r--r--ARCHITECTURE.md45
1 files changed, 22 insertions, 23 deletions
diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md
index 9c404f4c3..79adc9321 100644
--- a/ARCHITECTURE.md
+++ b/ARCHITECTURE.md
@@ -1,6 +1,6 @@
1# Architecture 1# Architecture
2 2
3This document describes high-level architecture of rust-analyzer. 3This document describes the high-level architecture of rust-analyzer.
4If you want to familiarize yourself with the code base, you are just 4If you want to familiarize yourself with the code base, you are just
5in the right place! 5in the right place!
6 6
@@ -12,10 +12,10 @@ On the highest level, rust-analyzer is a thing which accepts input source code
12from the client and produces a structured semantic model of the code. 12from the client and produces a structured semantic model of the code.
13 13
14More specifically, input data consists of a set of test files (`(PathBuf, 14More specifically, input data consists of a set of test files (`(PathBuf,
15String)` pairs) and an information about project structure, the so called 15String)` pairs) and information about project structure, captured in the so called
16`CrateGraph`. Crate graph specifies which files are crate roots, which cfg flags 16`CrateGraph`. The crate graph specifies which files are crate roots, which cfg
17are specified for each crate (TODO: actually implement this) and what are 17flags are specified for each crate (TODO: actually implement this) and what
18dependencies between the crates. The analyzer keeps all these input data in 18dependencies exist between the crates. The analyzer keeps all this input data in
19memory and never does any IO. Because the input data is source code, which 19memory and never does any IO. Because the input data is source code, which
20typically measures in tens of megabytes at most, keeping all input data in 20typically measures in tens of megabytes at most, keeping all input data in
21memory is OK. 21memory is OK.
@@ -28,8 +28,8 @@ declarations, etc.
28The client can submit a small delta of input data (typically, a change to a 28The client can submit a small delta of input data (typically, a change to a
29single file) and get a fresh code model which accounts for changes. 29single file) and get a fresh code model which accounts for changes.
30 30
31Underlying engine makes sure that model is computed lazily (on-demand) and can 31The underlying engine makes sure that model is computed lazily (on-demand) and
32be quickly updated for small modifications. 32can be quickly updated for small modifications.
33 33
34 34
35## Code generation 35## Code generation
@@ -37,7 +37,7 @@ be quickly updated for small modifications.
37Some of the components of this repository are generated through automatic 37Some of the components of this repository are generated through automatic
38processes. These are outlined below: 38processes. These are outlined below:
39 39
40- `gen-syntax`: The kinds of tokens are reused in several places, so a generator 40- `gen-syntax`: The kinds of tokens that are reused in several places, so a generator
41 is used. We use tera templates to generate the files listed below, based on 41 is used. We use tera templates to generate the files listed below, based on
42 the grammar described in [grammar.ron]: 42 the grammar described in [grammar.ron]:
43 - [ast/generated.rs][ast generated] in `ra_syntax` based on 43 - [ast/generated.rs][ast generated] in `ra_syntax` based on
@@ -58,17 +58,16 @@ processes. These are outlined below:
58### `crates/ra_syntax` 58### `crates/ra_syntax`
59 59
60Rust syntax tree structure and parser. See 60Rust syntax tree structure and parser. See
61[RFC](https://github.com/rust-lang/rfcs/pull/2256) for some design 61[RFC](https://github.com/rust-lang/rfcs/pull/2256) for some design notes.
62notes.
63 62
64- [rowan](https://github.com/rust-analyzer/rowan) library is used for constructing syntax trees. 63- [rowan](https://github.com/rust-analyzer/rowan) library is used for constructing syntax trees.
65- `grammar` module is the actual parser. It is a hand-written recursive descent parsers, which 64- `grammar` module is the actual parser. It is a hand-written recursive descent parser, which
66 produces a sequence of events like "start node X", "finish not Y". It works similarly to [kotlin parser](https://github.com/JetBrains/kotlin/blob/4d951de616b20feca92f3e9cc9679b2de9e65195/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinParsing.java), 65 produces a sequence of events like "start node X", "finish not Y". It works similarly to [kotlin's parser](https://github.com/JetBrains/kotlin/blob/4d951de616b20feca92f3e9cc9679b2de9e65195/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinParsing.java),
67 which is a good source for inspiration for dealing with syntax errors and incomplete input. Original [libsyntax parser](https://github.com/rust-lang/rust/blob/6b99adeb11313197f409b4f7c4083c2ceca8a4fe/src/libsyntax/parse/parser.rs) 66 which is a good source of inspiration for dealing with syntax errors and incomplete input. Original [libsyntax parser](https://github.com/rust-lang/rust/blob/6b99adeb11313197f409b4f7c4083c2ceca8a4fe/src/libsyntax/parse/parser.rs)
68 is what we use for the definition of the Rust language. 67 is what we use for the definition of the Rust language.
69- `parser_api/parser_impl` bridges the tree-agnostic parser from `grammar` with `rowan` trees. 68- `parser_api/parser_impl` bridges the tree-agnostic parser from `grammar` with `rowan` trees.
70 This is the thing that turns a flat list of events into a tree (see `EventProcessor`) 69 This is the thing that turns a flat list of events into a tree (see `EventProcessor`)
71- `ast` a type safe API on top of the raw `rowan` tree. 70- `ast` provides a type safe API on top of the raw `rowan` tree.
72- `grammar.ron` RON description of the grammar, which is used to 71- `grammar.ron` RON description of the grammar, which is used to
73 generate `syntax_kinds` and `ast` modules, using `cargo gen-syntax` command. 72 generate `syntax_kinds` and `ast` modules, using `cargo gen-syntax` command.
74- `algo`: generic tree algorithms, including `walk` for O(1) stack 73- `algo`: generic tree algorithms, including `walk` for O(1) stack
@@ -90,7 +89,7 @@ fixes a bug in the grammar.
90We use the [salsa](https://github.com/salsa-rs/salsa) crate for incremental and 89We use the [salsa](https://github.com/salsa-rs/salsa) crate for incremental and
91on-demand computation. Roughly, you can think of salsa as a key-value store, but 90on-demand computation. Roughly, you can think of salsa as a key-value store, but
92it also can compute derived values using specified functions. The `ra_db` crate 91it also can compute derived values using specified functions. The `ra_db` crate
93provides a basic infrastructure for interacting with salsa. Crucially, it 92provides basic infrastructure for interacting with salsa. Crucially, it
94defines most of the "input" queries: facts supplied by the client of the 93defines most of the "input" queries: facts supplied by the client of the
95analyzer. Reading the docs of the `ra_db::input` module should be useful: 94analyzer. Reading the docs of the `ra_db::input` module should be useful:
96everything else is strictly derived from those inputs. 95everything else is strictly derived from those inputs.
@@ -102,7 +101,7 @@ HIR provides high-level "object oriented" access to Rust code.
102The principal difference between HIR and syntax trees is that HIR is bound to a 101The principal difference between HIR and syntax trees is that HIR is bound to a
103particular crate instance. That is, it has cfg flags and features applied (in 102particular crate instance. That is, it has cfg flags and features applied (in
104theory, in practice this is to be implemented). So, the relation between 103theory, in practice this is to be implemented). So, the relation between
105syntax and HIR is many-to-one. The `source_binder` modules is responsible for 104syntax and HIR is many-to-one. The `source_binder` module is responsible for
106guessing a HIR for a particular source position. 105guessing a HIR for a particular source position.
107 106
108Underneath, HIR works on top of salsa, using a `HirDatabase` trait. 107Underneath, HIR works on top of salsa, using a `HirDatabase` trait.
@@ -111,12 +110,12 @@ Underneath, HIR works on top of salsa, using a `HirDatabase` trait.
111 110
112A stateful library for analyzing many Rust files as they change. `AnalysisHost` 111A stateful library for analyzing many Rust files as they change. `AnalysisHost`
113is a mutable entity (clojure's atom) which holds the current state, incorporates 112is a mutable entity (clojure's atom) which holds the current state, incorporates
114changes and handles out `Analysis` --- an immutable and consistent snapshot of 113changes and hands out `Analysis` --- an immutable and consistent snapshot of
115world state at a point in time, which actually powers analysis. 114the world state at a point in time, which actually powers analysis.
116 115
117One interesting aspect of analysis is its support for cancellation. When a 116One interesting aspect of analysis is its support for cancellation. When a
118change is applied to `AnalysisHost`, first all currently active snapshots are 117change is applied to `AnalysisHost`, first all currently active snapshots are
119cancelled. Only after all snapshots are dropped the change actually affects the 118canceled. Only after all snapshots are dropped the change actually affects the
120database. 119database.
121 120
122APIs in this crate are IDE centric: they take text offsets as input and produce 121APIs in this crate are IDE centric: they take text offsets as input and produce
@@ -142,7 +141,7 @@ An LSP implementation which wraps `ra_ide_api` into a langauge server protocol.
142 141
143### `crates/ra_vfs` 142### `crates/ra_vfs`
144 143
145Although `hir` and `ra_ide_api` don't do any io, we need to be able to read 144Although `hir` and `ra_ide_api` don't do any IO, we need to be able to read
146files from disk at the end of the day. This is what `ra_vfs` does. It also 145files from disk at the end of the day. This is what `ra_vfs` does. It also
147manages overlays: "dirty" files in the editor, whose "true" contents is 146manages overlays: "dirty" files in the editor, whose "true" contents is
148different from data on disk. 147different from data on disk.
@@ -175,16 +174,16 @@ VS Code plugin
175## Common workflows 174## Common workflows
176 175
177To try out VS Code extensions, run `cargo install-code`. This installs both the 176To try out VS Code extensions, run `cargo install-code`. This installs both the
178`ra_lsp_server` binary and VS Code extension. To install only the binary, use 177`ra_lsp_server` binary and the VS Code extension. To install only the binary, use
179`cargo install --path crates/ra_lsp_server --force` 178`cargo install --path crates/ra_lsp_server --force`
180 179
181To see logs from the language server, set `RUST_LOG=info` env variable. To see 180To see logs from the language server, set `RUST_LOG=info` env variable. To see
182all communication between the server and the client, use 181all communication between the server and the client, use
183`RUST_LOG=gen_lsp_server=debug` (will print quite a bit of stuff). 182`RUST_LOG=gen_lsp_server=debug` (this will print quite a bit of stuff).
184 183
185To run tests, just `cargo test`. 184To run tests, just `cargo test`.
186 185
187To work on VS Code extension, launch code inside `editors/code` and use `F5` to 186To work on the VS Code extension, launch code inside `editors/code` and use `F5` to
188launch/debug. To automatically apply formatter and linter suggestions, use `npm 187launch/debug. To automatically apply formatter and linter suggestions, use `npm
189run fix`. 188run fix`.
190 189