diff options
Diffstat (limited to 'ARCHITECTURE.md')
-rw-r--r-- | ARCHITECTURE.md | 45 |
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 | ||
3 | This document describes high-level architecture of rust-analyzer. | 3 | This document describes the high-level architecture of rust-analyzer. |
4 | If you want to familiarize yourself with the code base, you are just | 4 | If you want to familiarize yourself with the code base, you are just |
5 | in the right place! | 5 | in the right place! |
6 | 6 | ||
@@ -12,10 +12,10 @@ On the highest level, rust-analyzer is a thing which accepts input source code | |||
12 | from the client and produces a structured semantic model of the code. | 12 | from the client and produces a structured semantic model of the code. |
13 | 13 | ||
14 | More specifically, input data consists of a set of test files (`(PathBuf, | 14 | More specifically, input data consists of a set of test files (`(PathBuf, |
15 | String)` pairs) and an information about project structure, the so called | 15 | String)` 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 |
17 | are specified for each crate (TODO: actually implement this) and what are | 17 | flags are specified for each crate (TODO: actually implement this) and what |
18 | dependencies between the crates. The analyzer keeps all these input data in | 18 | dependencies exist between the crates. The analyzer keeps all this input data in |
19 | memory and never does any IO. Because the input data is source code, which | 19 | memory and never does any IO. Because the input data is source code, which |
20 | typically measures in tens of megabytes at most, keeping all input data in | 20 | typically measures in tens of megabytes at most, keeping all input data in |
21 | memory is OK. | 21 | memory is OK. |
@@ -28,8 +28,8 @@ declarations, etc. | |||
28 | The client can submit a small delta of input data (typically, a change to a | 28 | The client can submit a small delta of input data (typically, a change to a |
29 | single file) and get a fresh code model which accounts for changes. | 29 | single file) and get a fresh code model which accounts for changes. |
30 | 30 | ||
31 | Underlying engine makes sure that model is computed lazily (on-demand) and can | 31 | The underlying engine makes sure that model is computed lazily (on-demand) and |
32 | be quickly updated for small modifications. | 32 | can 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. | |||
37 | Some of the components of this repository are generated through automatic | 37 | Some of the components of this repository are generated through automatic |
38 | processes. These are outlined below: | 38 | processes. 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 | ||
60 | Rust syntax tree structure and parser. See | 60 | Rust 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. |
62 | notes. | ||
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. | |||
90 | We use the [salsa](https://github.com/salsa-rs/salsa) crate for incremental and | 89 | We use the [salsa](https://github.com/salsa-rs/salsa) crate for incremental and |
91 | on-demand computation. Roughly, you can think of salsa as a key-value store, but | 90 | on-demand computation. Roughly, you can think of salsa as a key-value store, but |
92 | it also can compute derived values using specified functions. The `ra_db` crate | 91 | it also can compute derived values using specified functions. The `ra_db` crate |
93 | provides a basic infrastructure for interacting with salsa. Crucially, it | 92 | provides basic infrastructure for interacting with salsa. Crucially, it |
94 | defines most of the "input" queries: facts supplied by the client of the | 93 | defines most of the "input" queries: facts supplied by the client of the |
95 | analyzer. Reading the docs of the `ra_db::input` module should be useful: | 94 | analyzer. Reading the docs of the `ra_db::input` module should be useful: |
96 | everything else is strictly derived from those inputs. | 95 | everything else is strictly derived from those inputs. |
@@ -102,7 +101,7 @@ HIR provides high-level "object oriented" access to Rust code. | |||
102 | The principal difference between HIR and syntax trees is that HIR is bound to a | 101 | The principal difference between HIR and syntax trees is that HIR is bound to a |
103 | particular crate instance. That is, it has cfg flags and features applied (in | 102 | particular crate instance. That is, it has cfg flags and features applied (in |
104 | theory, in practice this is to be implemented). So, the relation between | 103 | theory, in practice this is to be implemented). So, the relation between |
105 | syntax and HIR is many-to-one. The `source_binder` modules is responsible for | 104 | syntax and HIR is many-to-one. The `source_binder` module is responsible for |
106 | guessing a HIR for a particular source position. | 105 | guessing a HIR for a particular source position. |
107 | 106 | ||
108 | Underneath, HIR works on top of salsa, using a `HirDatabase` trait. | 107 | Underneath, 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 | ||
112 | A stateful library for analyzing many Rust files as they change. `AnalysisHost` | 111 | A stateful library for analyzing many Rust files as they change. `AnalysisHost` |
113 | is a mutable entity (clojure's atom) which holds the current state, incorporates | 112 | is a mutable entity (clojure's atom) which holds the current state, incorporates |
114 | changes and handles out `Analysis` --- an immutable and consistent snapshot of | 113 | changes and hands out `Analysis` --- an immutable and consistent snapshot of |
115 | world state at a point in time, which actually powers analysis. | 114 | the world state at a point in time, which actually powers analysis. |
116 | 115 | ||
117 | One interesting aspect of analysis is its support for cancellation. When a | 116 | One interesting aspect of analysis is its support for cancellation. When a |
118 | change is applied to `AnalysisHost`, first all currently active snapshots are | 117 | change is applied to `AnalysisHost`, first all currently active snapshots are |
119 | cancelled. Only after all snapshots are dropped the change actually affects the | 118 | canceled. Only after all snapshots are dropped the change actually affects the |
120 | database. | 119 | database. |
121 | 120 | ||
122 | APIs in this crate are IDE centric: they take text offsets as input and produce | 121 | APIs 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 | ||
145 | Although `hir` and `ra_ide_api` don't do any io, we need to be able to read | 144 | Although `hir` and `ra_ide_api` don't do any IO, we need to be able to read |
146 | files from disk at the end of the day. This is what `ra_vfs` does. It also | 145 | files from disk at the end of the day. This is what `ra_vfs` does. It also |
147 | manages overlays: "dirty" files in the editor, whose "true" contents is | 146 | manages overlays: "dirty" files in the editor, whose "true" contents is |
148 | different from data on disk. | 147 | different from data on disk. |
@@ -175,16 +174,16 @@ VS Code plugin | |||
175 | ## Common workflows | 174 | ## Common workflows |
176 | 175 | ||
177 | To try out VS Code extensions, run `cargo install-code`. This installs both the | 176 | To 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 | ||
181 | To see logs from the language server, set `RUST_LOG=info` env variable. To see | 180 | To see logs from the language server, set `RUST_LOG=info` env variable. To see |
182 | all communication between the server and the client, use | 181 | all 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 | ||
185 | To run tests, just `cargo test`. | 184 | To run tests, just `cargo test`. |
186 | 185 | ||
187 | To work on VS Code extension, launch code inside `editors/code` and use `F5` to | 186 | To work on the VS Code extension, launch code inside `editors/code` and use `F5` to |
188 | launch/debug. To automatically apply formatter and linter suggestions, use `npm | 187 | launch/debug. To automatically apply formatter and linter suggestions, use `npm |
189 | run fix`. | 188 | run fix`. |
190 | 189 | ||