aboutsummaryrefslogtreecommitdiff
path: root/docs/dev
diff options
context:
space:
mode:
Diffstat (limited to 'docs/dev')
-rw-r--r--docs/dev/README.md25
-rw-r--r--docs/dev/architecture.md24
-rw-r--r--docs/dev/guide.md66
-rw-r--r--docs/dev/lsp-extensions.md8
-rw-r--r--docs/dev/style.md51
-rw-r--r--docs/dev/syntax.md4
6 files changed, 109 insertions, 69 deletions
diff --git a/docs/dev/README.md b/docs/dev/README.md
index 67813a9c0..36edddc70 100644
--- a/docs/dev/README.md
+++ b/docs/dev/README.md
@@ -14,7 +14,7 @@ To learn more about how rust-analyzer works, see
14 14
15We also publish rustdoc docs to pages: 15We also publish rustdoc docs to pages:
16 16
17https://rust-analyzer.github.io/rust-analyzer/ra_ide/ 17https://rust-analyzer.github.io/rust-analyzer/ide/
18 18
19Various organizational and process issues are discussed in this document. 19Various organizational and process issues are discussed in this document.
20 20
@@ -92,11 +92,11 @@ This is primarily useful for performance optimizations, or for bug minimization.
92 92
93## Parser Tests 93## Parser Tests
94 94
95Tests for the parser (`ra_parser`) live in the `ra_syntax` crate (see `test_data` directory). 95Tests for the parser (`parser`) live in the `syntax` crate (see `test_data` directory).
96There are two kinds of tests: 96There are two kinds of tests:
97 97
98* Manually written test cases in `parser/ok` and `parser/err` 98* Manually written test cases in `parser/ok` and `parser/err`
99* "Inline" tests in `parser/inline` (these are generated) from comments in `ra_parser` crate. 99* "Inline" tests in `parser/inline` (these are generated) from comments in `parser` crate.
100 100
101The purpose of inline tests is not to achieve full coverage by test cases, but to explain to the reader of the code what each particular `if` and `match` is responsible for. 101The purpose of inline tests is not to achieve full coverage by test cases, but to explain to the reader of the code what each particular `if` and `match` is responsible for.
102If you are tempted to add a large inline test, it might be a good idea to leave only the simplest example in place, and move the test to a manual `parser/ok` test. 102If you are tempted to add a large inline test, it might be a good idea to leave only the simplest example in place, and move the test to a manual `parser/ok` test.
@@ -148,23 +148,28 @@ Internal representations are lowered to LSP in the `rust-analyzer` crate (the on
148 148
149## IDE/Compiler split 149## IDE/Compiler split
150 150
151There's a semi-hard split between "compiler" and "IDE", at the `ra_hir` crate. 151There's a semi-hard split between "compiler" and "IDE", at the `hir` crate.
152Compiler derives new facts about source code. 152Compiler derives new facts about source code.
153It explicitly acknowledges that not all info is available (i.e. you can't look at types during name resolution). 153It explicitly acknowledges that not all info is available (i.e. you can't look at types during name resolution).
154 154
155IDE assumes that all information is available at all times. 155IDE assumes that all information is available at all times.
156 156
157IDE should use only types from `ra_hir`, and should not depend on the underling compiler types. 157IDE should use only types from `hir`, and should not depend on the underling compiler types.
158`ra_hir` is a facade. 158`hir` is a facade.
159 159
160## IDE API 160## IDE API
161 161
162The main IDE crate (`ra_ide`) uses "Plain Old Data" for the API. 162The main IDE crate (`ide`) uses "Plain Old Data" for the API.
163Rather than talking in definitions and references, it talks in Strings and textual offsets. 163Rather than talking in definitions and references, it talks in Strings and textual offsets.
164In general, API is centered around UI concerns -- the result of the call is what the user sees in the editor, and not what the compiler sees underneath. 164In general, API is centered around UI concerns -- the result of the call is what the user sees in the editor, and not what the compiler sees underneath.
165The results are 100% Rust specific though. 165The results are 100% Rust specific though.
166Shout outs to LSP developers for popularizing the idea that "UI" is a good place to draw a boundary at. 166Shout outs to LSP developers for popularizing the idea that "UI" is a good place to draw a boundary at.
167 167
168## CI
169
170CI does not test rust-analyzer, CI is a core part of rust-analyzer, and is maintained with above average standard of quality.
171CI is reproducible -- it can only be broken by changes to files in this repository, any dependence on externalities is a bug.
172
168# Code Style & Review Process 173# Code Style & Review Process
169 174
170Do see [./style.md](./style.md). 175Do see [./style.md](./style.md).
@@ -256,9 +261,9 @@ Release steps:
256 * checkout the `release` branch 261 * checkout the `release` branch
257 * reset it to `upstream/nightly` 262 * reset it to `upstream/nightly`
258 * push it to `upstream`. This triggers GitHub Actions which: 263 * push it to `upstream`. This triggers GitHub Actions which:
259 ** runs `cargo xtask dist` to package binaries and VS Code extension 264 * runs `cargo xtask dist` to package binaries and VS Code extension
260 ** makes a GitHub release 265 * makes a GitHub release
261 ** pushes VS Code extension to the marketplace 266 * pushes VS Code extension to the marketplace
262 * create new changelog in `rust-analyzer.github.io` 267 * create new changelog in `rust-analyzer.github.io`
263 * create `rust-analyzer.github.io/git.log` file with the log of merge commits since last release 268 * create `rust-analyzer.github.io/git.log` file with the log of merge commits since last release
2642. While the release is in progress, fill-in the changelog using `git.log` 2692. While the release is in progress, fill-in the changelog using `git.log`
diff --git a/docs/dev/architecture.md b/docs/dev/architecture.md
index d0c6eea61..6f1377f2f 100644
--- a/docs/dev/architecture.md
+++ b/docs/dev/architecture.md
@@ -56,7 +56,7 @@ In particular, `cargo xtask codegen` generates:
562. [`ast/generated`](https://github.com/rust-analyzer/rust-analyzer/blob/a0be39296d2925972cacd9fbf8b5fb258fad6947/crates/ra_syntax/src/ast/generated.rs) 562. [`ast/generated`](https://github.com/rust-analyzer/rust-analyzer/blob/a0be39296d2925972cacd9fbf8b5fb258fad6947/crates/ra_syntax/src/ast/generated.rs)
57 -- AST data structure. 57 -- AST data structure.
58 58
593. [`doc_tests/generated`](https://github.com/rust-analyzer/rust-analyzer/blob/a0be39296d2925972cacd9fbf8b5fb258fad6947/crates/ra_assists/src/doc_tests/generated.rs), 593. [`doc_tests/generated`](https://github.com/rust-analyzer/rust-analyzer/blob/a0be39296d2925972cacd9fbf8b5fb258fad6947/crates/assists/src/doc_tests/generated.rs),
60 [`test_data/parser/inline`](https://github.com/rust-analyzer/rust-analyzer/tree/a0be39296d2925972cacd9fbf8b5fb258fad6947/crates/ra_syntax/test_data/parser/inline) 60 [`test_data/parser/inline`](https://github.com/rust-analyzer/rust-analyzer/tree/a0be39296d2925972cacd9fbf8b5fb258fad6947/crates/ra_syntax/test_data/parser/inline)
61 -- tests for assists and the parser. 61 -- tests for assists and the parser.
62 62
@@ -64,7 +64,7 @@ The source for 1 and 2 is in [`ast_src.rs`](https://github.com/rust-analyzer/rus
64 64
65## Code Walk-Through 65## Code Walk-Through
66 66
67### `crates/ra_syntax`, `crates/ra_parser` 67### `crates/ra_syntax`, `crates/parser`
68 68
69Rust syntax tree structure and parser. See 69Rust syntax tree structure and parser. See
70[RFC](https://github.com/rust-lang/rfcs/pull/2256) and [./syntax.md](./syntax.md) for some design notes. 70[RFC](https://github.com/rust-lang/rfcs/pull/2256) and [./syntax.md](./syntax.md) for some design notes.
@@ -92,17 +92,17 @@ in particular: it shows off various methods of working with syntax tree.
92See [#93](https://github.com/rust-analyzer/rust-analyzer/pull/93) for an example PR which 92See [#93](https://github.com/rust-analyzer/rust-analyzer/pull/93) for an example PR which
93fixes a bug in the grammar. 93fixes a bug in the grammar.
94 94
95### `crates/ra_db` 95### `crates/base_db`
96 96
97We use the [salsa](https://github.com/salsa-rs/salsa) crate for incremental and 97We use the [salsa](https://github.com/salsa-rs/salsa) crate for incremental and
98on-demand computation. Roughly, you can think of salsa as a key-value store, but 98on-demand computation. Roughly, you can think of salsa as a key-value store, but
99it also can compute derived values using specified functions. The `ra_db` crate 99it also can compute derived values using specified functions. The `base_db` crate
100provides basic infrastructure for interacting with salsa. Crucially, it 100provides basic infrastructure for interacting with salsa. Crucially, it
101defines most of the "input" queries: facts supplied by the client of the 101defines most of the "input" queries: facts supplied by the client of the
102analyzer. Reading the docs of the `ra_db::input` module should be useful: 102analyzer. Reading the docs of the `base_db::input` module should be useful:
103everything else is strictly derived from those inputs. 103everything else is strictly derived from those inputs.
104 104
105### `crates/ra_hir*` crates 105### `crates/hir*` crates
106 106
107HIR provides high-level "object oriented" access to Rust code. 107HIR provides high-level "object oriented" access to Rust code.
108 108
@@ -113,12 +113,12 @@ is responsible for guessing a HIR for a particular source position.
113 113
114Underneath, HIR works on top of salsa, using a `HirDatabase` trait. 114Underneath, HIR works on top of salsa, using a `HirDatabase` trait.
115 115
116`ra_hir_xxx` crates have a strong ECS flavor, in that they work with raw ids and 116`hir_xxx` crates have a strong ECS flavor, in that they work with raw ids and
117directly query the database. 117directly query the database.
118 118
119The top-level `ra_hir` façade crate wraps ids into a more OO-flavored API. 119The top-level `hir` façade crate wraps ids into a more OO-flavored API.
120 120
121### `crates/ra_ide` 121### `crates/ide`
122 122
123A stateful library for analyzing many Rust files as they change. `AnalysisHost` 123A stateful library for analyzing many Rust files as they change. `AnalysisHost`
124is a mutable entity (clojure's atom) which holds the current state, incorporates 124is a mutable entity (clojure's atom) which holds the current state, incorporates
@@ -136,11 +136,11 @@ offsets and strings as output. This works on top of rich code model powered by
136 136
137### `crates/rust-analyzer` 137### `crates/rust-analyzer`
138 138
139An LSP implementation which wraps `ra_ide` into a language server protocol. 139An LSP implementation which wraps `ide` into a language server protocol.
140 140
141### `ra_vfs` 141### `ra_vfs`
142 142
143Although `hir` and `ra_ide` don't do any IO, we need to be able to read 143Although `hir` and `ide` don't do any IO, we need to be able to read
144files from disk at the end of the day. This is what `ra_vfs` does. It also 144files from disk at the end of the day. This is what `ra_vfs` does. It also
145manages overlays: "dirty" files in the editor, whose "true" contents is 145manages overlays: "dirty" files in the editor, whose "true" contents is
146different from data on disk. This is more or less the single really 146different from data on disk. This is more or less the single really
@@ -161,7 +161,7 @@ disk. For this reason, we try to avoid writing too many tests on this boundary:
161in a statically typed language, it's hard to make an error in the protocol 161in a statically typed language, it's hard to make an error in the protocol
162itself if messages are themselves typed. 162itself if messages are themselves typed.
163 163
164The middle, and most important, boundary is `ra_ide`. Unlike 164The middle, and most important, boundary is `ide`. Unlike
165`rust-analyzer`, which exposes API, `ide` uses Rust API and is intended to 165`rust-analyzer`, which exposes API, `ide` uses Rust API and is intended to
166use by various tools. Typical test creates an `AnalysisHost`, calls some 166use by various tools. Typical test creates an `AnalysisHost`, calls some
167`Analysis` functions and compares the results against expectation. 167`Analysis` functions and compares the results against expectation.
diff --git a/docs/dev/guide.md b/docs/dev/guide.md
index c3252f1f6..b5a5d7c93 100644
--- a/docs/dev/guide.md
+++ b/docs/dev/guide.md
@@ -40,8 +40,8 @@ terms of files and offsets, and **not** in terms of Rust concepts like structs,
40traits, etc. The "typed" API with Rust specific types is slightly lower in the 40traits, etc. The "typed" API with Rust specific types is slightly lower in the
41stack, we'll talk about it later. 41stack, we'll talk about it later.
42 42
43[`AnalysisHost`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/lib.rs#L265-L284 43[`AnalysisHost`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ide_api/src/lib.rs#L265-L284
44[`Analysis`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/lib.rs#L291-L478 44[`Analysis`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ide_api/src/lib.rs#L291-L478
45 45
46The reason for this separation of `Analysis` and `AnalysisHost` is that we want to apply 46The reason for this separation of `Analysis` and `AnalysisHost` is that we want to apply
47changes "uniquely", but we might also want to fork an `Analysis` and send it to 47changes "uniquely", but we might also want to fork an `Analysis` and send it to
@@ -69,7 +69,7 @@ the `AnalysisHost::apply_change` method, which accepts a single argument, a
69"transaction", so it suffices to study its methods to understand all of the 69"transaction", so it suffices to study its methods to understand all of the
70input data. 70input data.
71 71
72[`AnalysisChange`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/lib.rs#L119-L167 72[`AnalysisChange`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ide_api/src/lib.rs#L119-L167
73 73
74The `(add|change|remove)_file` methods control the set of the input files, where 74The `(add|change|remove)_file` methods control the set of the input files, where
75each file has an integer id (`FileId`, picked by the client), text (`String`) 75each file has an integer id (`FileId`, picked by the client), text (`String`)
@@ -253,13 +253,13 @@ All analyzer information is stored in a salsa database. `Analysis` and
253`AnalysisHost` types are newtype wrappers for [`RootDatabase`] -- a salsa 253`AnalysisHost` types are newtype wrappers for [`RootDatabase`] -- a salsa
254database. 254database.
255 255
256[`RootDatabase`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/db.rs#L88-L134 256[`RootDatabase`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ide_api/src/db.rs#L88-L134
257 257
258Salsa input queries are defined in [`FilesDatabase`] (which is a part of 258Salsa input queries are defined in [`FilesDatabase`] (which is a part of
259`RootDatabase`). They closely mirror the familiar `AnalysisChange` structure: 259`RootDatabase`). They closely mirror the familiar `AnalysisChange` structure:
260indeed, what `apply_change` does is it sets the values of input queries. 260indeed, what `apply_change` does is it sets the values of input queries.
261 261
262[`FilesDatabase`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_db/src/input.rs#L150-L174 262[`FilesDatabase`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/base_db/src/input.rs#L150-L174
263 263
264## From text to semantic model 264## From text to semantic model
265 265
@@ -275,7 +275,7 @@ several times, with different sets of `cfg`s enabled. The IDE-specific task of
275mapping source code position into a semantic model is inherently imprecise for 275mapping source code position into a semantic model is inherently imprecise for
276this reason, and is handled by the [`source_binder`]. 276this reason, and is handled by the [`source_binder`].
277 277
278[`source_binder`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/source_binder.rs 278[`source_binder`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/hir/src/source_binder.rs
279 279
280The semantic interface is declared in the [`code_model_api`] module. Each entity is 280The semantic interface is declared in the [`code_model_api`] module. Each entity is
281identified by an integer ID and has a bunch of methods which take a salsa database 281identified by an integer ID and has a bunch of methods which take a salsa database
@@ -283,8 +283,8 @@ as an argument and returns other entities (which are also IDs). Internally, thes
283methods invoke various queries on the database to build the model on demand. 283methods invoke various queries on the database to build the model on demand.
284Here's [the list of queries]. 284Here's [the list of queries].
285 285
286[`code_model_api`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/code_model_api.rs 286[`code_model_api`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/hir/src/code_model_api.rs
287[the list of queries]: https://github.com/rust-analyzer/rust-analyzer/blob/7e84440e25e19529e4ff8a66e521d1b06349c6ec/crates/ra_hir/src/db.rs#L20-L106 287[the list of queries]: https://github.com/rust-analyzer/rust-analyzer/blob/7e84440e25e19529e4ff8a66e521d1b06349c6ec/crates/hir/src/db.rs#L20-L106
288 288
289The first step of building the model is parsing the source code. 289The first step of building the model is parsing the source code.
290 290
@@ -341,7 +341,7 @@ The algorithm for building a tree of modules is to start with a crate root
341declarations and recursively process child modules. This is handled by the 341declarations and recursively process child modules. This is handled by the
342[`module_tree_query`], with two slight variations. 342[`module_tree_query`], with two slight variations.
343 343
344[`module_tree_query`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/module_tree.rs#L116-L123 344[`module_tree_query`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/hir/src/module_tree.rs#L116-L123
345 345
346First, rust-analyzer builds a module tree for all crates in a source root 346First, rust-analyzer builds a module tree for all crates in a source root
347simultaneously. The main reason for this is historical (`module_tree` predates 347simultaneously. The main reason for this is historical (`module_tree` predates
@@ -364,7 +364,7 @@ the same, we don't have to re-execute [`module_tree_query`]. In fact, we only
364need to re-execute it when we add/remove new files or when we change mod 364need to re-execute it when we add/remove new files or when we change mod
365declarations. 365declarations.
366 366
367[`submodules_query`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/module_tree.rs#L41 367[`submodules_query`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/hir/src/module_tree.rs#L41
368 368
369We store the resulting modules in a `Vec`-based indexed arena. The indices in 369We store the resulting modules in a `Vec`-based indexed arena. The indices in
370the arena becomes module IDs. And this brings us to the next topic: 370the arena becomes module IDs. And this brings us to the next topic:
@@ -392,8 +392,8 @@ integers which can "intern" a location and return an integer ID back. The salsa
392database we use includes a couple of [interners]. How to "garbage collect" 392database we use includes a couple of [interners]. How to "garbage collect"
393unused locations is an open question. 393unused locations is an open question.
394 394
395[`LocationInterner`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_db/src/loc2id.rs#L65-L71 395[`LocationInterner`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/base_db/src/loc2id.rs#L65-L71
396[interners]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/db.rs#L22-L23 396[interners]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/hir/src/db.rs#L22-L23
397 397
398For example, we use `LocationInterner` to assign IDs to definitions of functions, 398For example, we use `LocationInterner` to assign IDs to definitions of functions,
399structs, enums, etc. The location, [`DefLoc`] contains two bits of information: 399structs, enums, etc. The location, [`DefLoc`] contains two bits of information:
@@ -407,7 +407,7 @@ using offsets, text ranges or syntax trees as keys and values for queries. What
407we do instead is we store "index" of the item among all of the items of a file 407we do instead is we store "index" of the item among all of the items of a file
408(so, a positional based ID, but localized to a single file). 408(so, a positional based ID, but localized to a single file).
409 409
410[`DefLoc`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/ids.rs#L127-L139 410[`DefLoc`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/hir/src/ids.rs#L127-L139
411 411
412One thing we've glossed over for the time being is support for macros. We have 412One thing we've glossed over for the time being is support for macros. We have
413only proof of concept handling of macros at the moment, but they are extremely 413only proof of concept handling of macros at the moment, but they are extremely
@@ -440,7 +440,7 @@ terms of `HirFileId`! This does not recur infinitely though: any chain of
440`HirFileId`s bottoms out in `HirFileId::FileId`, that is, some source file 440`HirFileId`s bottoms out in `HirFileId::FileId`, that is, some source file
441actually written by the user. 441actually written by the user.
442 442
443[`HirFileId`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/ids.rs#L18-L125 443[`HirFileId`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/hir/src/ids.rs#L18-L125
444 444
445Now that we understand how to identify a definition, in a source or in a 445Now that we understand how to identify a definition, in a source or in a
446macro-generated file, we can discuss name resolution a bit. 446macro-generated file, we can discuss name resolution a bit.
@@ -454,14 +454,14 @@ each module into a position-independent representation which does not change if
454we modify bodies of the items. After that we [loop] resolving all imports until 454we modify bodies of the items. After that we [loop] resolving all imports until
455we've reached a fixed point. 455we've reached a fixed point.
456 456
457[lower]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/lower.rs#L113-L117 457[lower]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/hir/src/nameres/lower.rs#L113-L117
458[loop]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres.rs#L186-L196 458[loop]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/hir/src/nameres.rs#L186-L196
459 459
460And, given all our preparation with IDs and a position-independent representation, 460And, given all our preparation with IDs and a position-independent representation,
461it is satisfying to [test] that typing inside function body does not invalidate 461it is satisfying to [test] that typing inside function body does not invalidate
462name resolution results. 462name resolution results.
463 463
464[test]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/tests.rs#L376 464[test]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/hir/src/nameres/tests.rs#L376
465 465
466An interesting fact about name resolution is that it "erases" all of the 466An interesting fact about name resolution is that it "erases" all of the
467intermediate paths from the imports: in the end, we know which items are defined 467intermediate paths from the imports: in the end, we know which items are defined
@@ -496,10 +496,10 @@ there's an intermediate [projection query] which returns only the first
496position-independent part of the lowering. The result of this query is stable. 496position-independent part of the lowering. The result of this query is stable.
497Naturally, name resolution [uses] this stable projection query. 497Naturally, name resolution [uses] this stable projection query.
498 498
499[imports]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/lower.rs#L52-L59 499[imports]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/hir/src/nameres/lower.rs#L52-L59
500[`SourceMap`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/lower.rs#L52-L59 500[`SourceMap`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/hir/src/nameres/lower.rs#L52-L59
501[projection query]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/lower.rs#L97-L103 501[projection query]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/hir/src/nameres/lower.rs#L97-L103
502[uses]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/query_definitions.rs#L49 502[uses]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/hir/src/query_definitions.rs#L49
503 503
504## Type inference 504## Type inference
505 505
@@ -521,10 +521,10 @@ construct a mapping from `ExprId`s to types.
521 521
522[@flodiebold]: https://github.com/flodiebold 522[@flodiebold]: https://github.com/flodiebold
523[#327]: https://github.com/rust-analyzer/rust-analyzer/pull/327 523[#327]: https://github.com/rust-analyzer/rust-analyzer/pull/327
524[lower the AST]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/expr.rs 524[lower the AST]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/hir/src/expr.rs
525[positional ID]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/expr.rs#L13-L15 525[positional ID]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/hir/src/expr.rs#L13-L15
526[a source map]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/expr.rs#L41-L44 526[a source map]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/hir/src/expr.rs#L41-L44
527[type inference]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/ty.rs#L1208-L1223 527[type inference]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/hir/src/ty.rs#L1208-L1223
528 528
529## Tying it all together: completion 529## Tying it all together: completion
530 530
@@ -565,11 +565,11 @@ the type to completion.
565[schedule it on the threadpool]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop.rs#L428 565[schedule it on the threadpool]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop.rs#L428
566[catch]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop.rs#L436-L442 566[catch]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop.rs#L436-L442
567[the handler]: https://salsa.zulipchat.com/#narrow/stream/181542-rfcs.2Fsalsa-query-group/topic/design.20next.20steps 567[the handler]: https://salsa.zulipchat.com/#narrow/stream/181542-rfcs.2Fsalsa-query-group/topic/design.20next.20steps
568[ask analysis for completion]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/lib.rs#L439-L444 568[ask analysis for completion]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ide_api/src/lib.rs#L439-L444
569[completion implementation]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/completion.rs#L46-L62 569[completion implementation]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ide_api/src/completion.rs#L46-L62
570[`CompletionContext`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/completion/completion_context.rs#L14-L37 570[`CompletionContext`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ide_api/src/completion/completion_context.rs#L14-L37
571["IntelliJ Trick"]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/completion/completion_context.rs#L72-L75 571["IntelliJ Trick"]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ide_api/src/completion/completion_context.rs#L72-L75
572[find an ancestor `fn` node]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/completion/completion_context.rs#L116-L120 572[find an ancestor `fn` node]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ide_api/src/completion/completion_context.rs#L116-L120
573[semantic model]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/completion/completion_context.rs#L123 573[semantic model]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ide_api/src/completion/completion_context.rs#L123
574[series of independent completion routines]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/completion.rs#L52-L59 574[series of independent completion routines]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ide_api/src/completion.rs#L52-L59
575[`complete_dot`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/completion/complete_dot.rs#L6-L22 575[`complete_dot`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ide_api/src/completion/complete_dot.rs#L6-L22
diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md
index 1be01fd88..2e3133449 100644
--- a/docs/dev/lsp-extensions.md
+++ b/docs/dev/lsp-extensions.md
@@ -412,7 +412,13 @@ Reloads project information (that is, re-executes `cargo metadata`).
412 412
413**Method:** `rust-analyzer/status` 413**Method:** `rust-analyzer/status`
414 414
415**Notification:** `"loading" | "ready" | "invalid" | "needsReload"` 415**Notification:**
416
417```typescript
418interface StatusParams {
419 status: "loading" | "ready" | "invalid" | "needsReload",
420}
421```
416 422
417This notification is sent from server to client. 423This notification is sent from server to client.
418The client can use it to display persistent status to the user (in modline). 424The client can use it to display persistent status to the user (in modline).
diff --git a/docs/dev/style.md b/docs/dev/style.md
index 1c68f5702..8effddcda 100644
--- a/docs/dev/style.md
+++ b/docs/dev/style.md
@@ -65,7 +65,7 @@ There are many benefits to this:
65It also makes sense to format snippets more compactly (for example, by placing enum definitions like `enum E { Foo, Bar }` on a single line), 65It also makes sense to format snippets more compactly (for example, by placing enum definitions like `enum E { Foo, Bar }` on a single line),
66as long as they are still readable. 66as long as they are still readable.
67 67
68## Order of Imports 68# Order of Imports
69 69
70Separate import groups with blank lines. 70Separate import groups with blank lines.
71Use one `use` per crate. 71Use one `use` per crate.
@@ -91,19 +91,19 @@ use super::{}
91Module declarations come before the imports. 91Module declarations come before the imports.
92Order them in "suggested reading order" for a person new to the code base. 92Order them in "suggested reading order" for a person new to the code base.
93 93
94## Import Style 94# Import Style
95 95
96Qualify items from `hir` and `ast`. 96Qualify items from `hir` and `ast`.
97 97
98```rust 98```rust
99// Good 99// Good
100use ra_syntax::ast; 100use syntax::ast;
101 101
102fn frobnicate(func: hir::Function, strukt: ast::StructDef) {} 102fn frobnicate(func: hir::Function, strukt: ast::StructDef) {}
103 103
104// Not as good 104// Not as good
105use hir::Function; 105use hir::Function;
106use ra_syntax::ast::StructDef; 106use syntax::ast::StructDef;
107 107
108fn frobnicate(func: Function, strukt: StructDef) {} 108fn frobnicate(func: Function, strukt: StructDef) {}
109``` 109```
@@ -112,7 +112,7 @@ Avoid local `use MyEnum::*` imports.
112 112
113Prefer `use crate::foo::bar` to `use super::bar`. 113Prefer `use crate::foo::bar` to `use super::bar`.
114 114
115## Order of Items 115# Order of Items
116 116
117Optimize for the reader who sees the file for the first time, and wants to get a general idea about what's going on. 117Optimize for the reader who sees the file for the first time, and wants to get a general idea about what's going on.
118People read things from top to bottom, so place most important things first. 118People read things from top to bottom, so place most important things first.
@@ -143,7 +143,7 @@ struct Foo {
143} 143}
144``` 144```
145 145
146## Variable Naming 146# Variable Naming
147 147
148Use boring and long names for local variables ([yay code completion](https://github.com/rust-analyzer/rust-analyzer/pull/4162#discussion_r417130973)). 148Use boring and long names for local variables ([yay code completion](https://github.com/rust-analyzer/rust-analyzer/pull/4162#discussion_r417130973)).
149The default name is a lowercased name of the type: `global_state: GlobalState`. 149The default name is a lowercased name of the type: `global_state: GlobalState`.
@@ -151,12 +151,12 @@ Avoid ad-hoc acronyms and contractions, but use the ones that exist consistently
151The default name for "result of the function" local variable is `res`. 151The default name for "result of the function" local variable is `res`.
152The default name for "I don't really care about the name" variable is `it`. 152The default name for "I don't really care about the name" variable is `it`.
153 153
154## Collection types 154# Collection types
155 155
156Prefer `rustc_hash::FxHashMap` and `rustc_hash::FxHashSet` instead of the ones in `std::collections`. 156Prefer `rustc_hash::FxHashMap` and `rustc_hash::FxHashSet` instead of the ones in `std::collections`.
157They use a hasher that's slightly faster and using them consistently will reduce code size by some small amount. 157They use a hasher that's slightly faster and using them consistently will reduce code size by some small amount.
158 158
159## Preconditions 159# Preconditions
160 160
161Express function preconditions in types and force the caller to provide them (rather than checking in callee): 161Express function preconditions in types and force the caller to provide them (rather than checking in callee):
162 162
@@ -176,7 +176,36 @@ fn frobnicate(walrus: Option<Walrus>) {
176} 176}
177``` 177```
178 178
179## Premature Pessimization 179# Getters & Setters
180
181If a field can have any value without breaking invariants, make the field public.
182Conversely, if there is an invariant, document it, enforce it in the "constructor" function, make the field private, and provide a getter.
183Never provide setters.
184
185Getters should return borrowed data:
186
187```
188struct Person {
189 // Invariant: never empty
190 first_name: String,
191 middle_name: Option<String>
192}
193
194// Good
195impl Person {
196 fn first_name(&self) -> &str { self.first_name.as_str() }
197 fn middle_name(&self) -> Option<&str> { self.middle_name.as_ref() }
198}
199
200// Not as good
201impl Person {
202 fn first_name(&self) -> String { self.first_name.clone() }
203 fn middle_name(&self) -> &Option<String> { &self.middle_name }
204}
205```
206
207
208# Premature Pessimization
180 209
181Avoid writing code which is slower than it needs to be. 210Avoid writing code which is slower than it needs to be.
182Don't allocate a `Vec` where an iterator would do, don't allocate strings needlessly. 211Don't allocate a `Vec` where an iterator would do, don't allocate strings needlessly.
@@ -197,12 +226,12 @@ if words.len() != 2 {
197} 226}
198``` 227```
199 228
200## Documentation 229# Documentation
201 230
202For `.md` and `.adoc` files, prefer a sentence-per-line format, don't wrap lines. 231For `.md` and `.adoc` files, prefer a sentence-per-line format, don't wrap lines.
203If the line is too long, you want to split the sentence in two :-) 232If the line is too long, you want to split the sentence in two :-)
204 233
205## Commit Style 234# Commit Style
206 235
207We don't have specific rules around git history hygiene. 236We don't have specific rules around git history hygiene.
208Maintaining clean git history is encouraged, but not enforced. 237Maintaining clean git history is encouraged, but not enforced.
diff --git a/docs/dev/syntax.md b/docs/dev/syntax.md
index d4bc4b07c..c08062ef4 100644
--- a/docs/dev/syntax.md
+++ b/docs/dev/syntax.md
@@ -11,7 +11,7 @@ The things described are implemented in two places
11* [rowan](https://github.com/rust-analyzer/rowan/tree/v0.9.0) -- a generic library for rowan syntax trees. 11* [rowan](https://github.com/rust-analyzer/rowan/tree/v0.9.0) -- a generic library for rowan syntax trees.
12* [ra_syntax](https://github.com/rust-analyzer/rust-analyzer/tree/cf5bdf464cad7ceb9a67e07985a3f4d3799ec0b6/crates/ra_syntax) crate inside rust-analyzer which wraps `rowan` into rust-analyzer specific API. 12* [ra_syntax](https://github.com/rust-analyzer/rust-analyzer/tree/cf5bdf464cad7ceb9a67e07985a3f4d3799ec0b6/crates/ra_syntax) crate inside rust-analyzer which wraps `rowan` into rust-analyzer specific API.
13 Nothing in rust-analyzer except this crate knows about `rowan`. 13 Nothing in rust-analyzer except this crate knows about `rowan`.
14* [ra_parser](https://github.com/rust-analyzer/rust-analyzer/tree/cf5bdf464cad7ceb9a67e07985a3f4d3799ec0b6/crates/ra_parser) crate parses input tokens into an `ra_syntax` tree 14* [parser](https://github.com/rust-analyzer/rust-analyzer/tree/cf5bdf464cad7ceb9a67e07985a3f4d3799ec0b6/crates/parser) crate parses input tokens into an `ra_syntax` tree
15 15
16## Design Goals 16## Design Goals
17 17
@@ -74,7 +74,7 @@ Points of note:
74* The original text can be recovered by concatenating the texts of all tokens in order. 74* The original text can be recovered by concatenating the texts of all tokens in order.
75* Accessing a child of particular type (for example, parameter list of a function) generally involves linerary traversing the children, looking for a specific `kind`. 75* Accessing a child of particular type (for example, parameter list of a function) generally involves linerary traversing the children, looking for a specific `kind`.
76* Modifying the tree is roughly `O(depth)`. 76* Modifying the tree is roughly `O(depth)`.
77 We don't make special efforts to guarantree that the depth is not liner, but, in practice, syntax trees are branchy and shallow. 77 We don't make special efforts to guarantee that the depth is not linear, but, in practice, syntax trees are branchy and shallow.
78* If mandatory (grammar wise) node is missing from the input, it's just missing from the tree. 78* If mandatory (grammar wise) node is missing from the input, it's just missing from the tree.
79* If an extra erroneous input is present, it is wrapped into a node with `ERROR` kind, and treated just like any other node. 79* If an extra erroneous input is present, it is wrapped into a node with `ERROR` kind, and treated just like any other node.
80* Parser errors are not a part of syntax tree. 80* Parser errors are not a part of syntax tree.