]> git.lizzy.rs Git - rust.git/blob - ARCHITECTURE.md
update architecture.md
[rust.git] / ARCHITECTURE.md
1 # Architecture
2
3 This document describes high-level architecture of rust-analyzer.
4 If you want to familiarize yourself with the code base, you are just
5 in the right place!
6
7
8 ## Code generation
9
10 Some of the components of this repository are generated through automatic
11 processes. These are outlined below:
12
13 - `gen-syntax`: The kinds of tokens are reused in several places, so a generator
14   is used. We use tera templates to generate the files listed below, based on
15   the grammar described in [grammar.ron]:
16   - [ast/generated.rs][ast generated] in `ra_syntax` based on
17     [ast/generated.tera.rs][ast source]
18   - [syntax_kinds/generated.rs][syntax_kinds generated] in `ra_syntax` based on
19     [syntax_kinds/generated.tera.rs][syntax_kinds source]
20
21 [tera]: https://tera.netlify.com/
22 [grammar.ron]: ./crates/ra_syntax/src/grammar.ron
23 [ast generated]: ./crates/ra_syntax/src/ast/generated.rs
24 [ast source]: ./crates/ra_syntax/src/ast/generated.rs.tera
25 [syntax_kinds generated]: ./crates/ra_syntax/src/syntax_kinds/generated.rs
26 [syntax_kinds source]: ./crates/ra_syntax/src/syntax_kinds/generated.rs.tera
27
28
29 ## Code Walk-Through
30
31 ### `crates/ra_syntax`
32
33 Rust syntax tree structure and parser. See
34 [RFC](https://github.com/rust-lang/rfcs/pull/2256) for some design
35 notes.
36
37 - [rowan](https://github.com/rust-analyzer/rowan) library is used for constructing syntax trees.
38 - `grammar` module is the actual parser. It is a hand-written recursive descent parsers, which
39   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),
40   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)
41   is what we use for the definition of the Rust language.
42 - `parser_api/parser_impl` bridges the tree-agnostic parser from `grammar` with `rowan` trees.
43   This is the thing that turns a flat list of events into a tree (see `EventProcessor`)
44 - `ast` a type safe API on top of the raw `rowan` tree.
45 - `grammar.ron` RON description of the grammar, which is used to
46   generate `syntax_kinds` and `ast` modules, using `cargo gen-syntax` command.
47 - `algo`: generic tree algorithms, including `walk` for O(1) stack
48   space tree traversal (this is cool) and `visit` for type-driven
49   visiting the nodes (this is double plus cool, if you understand how
50   `Visitor` works, you understand rust-analyzer).
51
52 Test for ra_syntax are mostly data-driven: `tests/data/parser` contains a bunch of `.rs`
53 (test vectors) and `.txt` files with corresponding syntax trees. During testing, we check
54 `.rs` against `.txt`. If the `.txt` file is missing, it is created (this is how you update
55 tests). Additionally, running `cargo gen-tests` will walk the grammar module and collect
56 all `//test test_name` comments into files inside `tests/data` directory.
57
58 See [#93](https://github.com/rust-analyzer/rust-analyzer/pull/93) for an example PR which
59 fixes a bug in the grammar.
60
61 ### `crates/ra_db`
62
63 We use [salsa][https://github.com/salsa-rs/salsa] crate for incremental and
64 on-demand computation. Roughly, you can think of salsa as a key-value store, but
65 it also can compute derived values using specified functions. The `ra_db` crate
66 provides a basic infrastructure for interracting with salsa. Crucially, it
67 defines most of the "input" queries: facts supplied by the client of the analyzer.
68
69 ### `crates/ra_hir`
70
71 HIR provides a high-level "object oriented" acess to Rust code.
72
73 The principal difference between HIR and syntax trees is that HIR is bound to a
74 particular crate instance. That is, it has cfg flags and features applied (in
75 theory, in practice this is to be implemented). So, there relation between
76 syntax and HIR is many-to-one. The `source_binder` modules is responsible for
77 guessing a hir for a particular source position.
78
79 Underneath, hir works on top of salsa, using a `HirDatabase` trait.
80
81 ### `crates/ra_analysis`
82
83 A stateful library for analyzing many Rust files as they change.
84 `AnalysisHost` is a mutable entity (clojure's atom) which holds
85 current state, incorporates changes and handles out `Analysis` --- an
86 immutable consistent snapshot of world state at a point in time, which
87 actually powers analysis.
88
89 ### `crates/ra_lsp_server`
90
91 An LSP implementation which uses `ra_analysis` for managing state and
92 `ra_editor` for actually doing useful stuff.
93
94 See [#79](https://github.com/rust-analyzer/rust-analyzer/pull/79/) as an
95 example of PR which adds a new feature to `ra_editor` and exposes it
96 to `ra_lsp_server`.
97
98 ### `crates/ra_editor`
99
100 All IDE features which can be implemented if you only have access to a
101 single file. `ra_editor` could be used to enhance editing of Rust code
102 without the need to fiddle with build-systems, file
103 synchronization and such.
104
105 In a sense, `ra_editor` is just a bunch of pure functions which take a
106 syntax tree as an input.
107
108 The tests for `ra_editor` are `#[cfg(test)] mod tests` unit-tests spread
109 throughout its modules.
110
111 ### `crates/gen_lsp_server`
112
113 A language server scaffold, exposing a synchronous crossbeam-channel based API.
114 This crate handles protocol handshaking and parsing messages, while you
115 control the message dispatch loop yourself.
116
117 Run with `RUST_LOG=sync_lsp_server=debug` to see all the messages.
118
119 ### `crates/ra_cli`
120
121 A CLI interface to rust-analyzer.
122
123 ### `crate/tools`
124
125 Custom Cargo tasks used to develop rust-analyzer:
126
127 - `cargo gen-syntax` -- generate `ast` and `syntax_kinds`
128 - `cargo gen-tests` -- collect inline tests from grammar
129 - `cargo install-code` -- build and install VS Code extension and server
130
131 ### `editors/code`
132
133 VS Code plugin
134
135
136 ## Common workflows
137
138 To try out VS Code extensions, run `cargo install-code`.  This installs both the
139 `ra_lsp_server` binary and VS Code extension. To install only the binary, use
140 `cargo install --path crates/ra_lsp_server --force`
141
142 To see logs from the language server, set `RUST_LOG=info` env variable. To see
143 all communication between the server and the client, use
144 `RUST_LOG=gen_lsp_server=debug` (will print quite a bit of stuff).
145
146 To run tests, just `cargo test`.
147
148 To work on VS Code extension, launch code inside `editors/code` and use `F5` to
149 launch/debug. To automatically apply formatter and linter suggestions, use `npm
150 run fix`.
151