diff options
Diffstat (limited to 'docs')
-rw-r--r-- | docs/dev/README.md | 76 | ||||
-rw-r--r-- | docs/dev/architecture.md | 13 | ||||
-rw-r--r-- | docs/dev/lsp-extensions.md | 47 | ||||
-rw-r--r-- | docs/dev/style.md | 72 | ||||
-rw-r--r-- | docs/dev/syntax.md | 8 | ||||
-rw-r--r-- | docs/user/manual.adoc | 28 |
6 files changed, 157 insertions, 87 deletions
diff --git a/docs/dev/README.md b/docs/dev/README.md index 57162a47d..9c0eb1358 100644 --- a/docs/dev/README.md +++ b/docs/dev/README.md | |||
@@ -1,7 +1,7 @@ | |||
1 | # Contributing Quick Start | 1 | # Contributing Quick Start |
2 | 2 | ||
3 | Rust Analyzer is an ordinary Rust project, which is organized as a Cargo | 3 | Rust Analyzer is an ordinary Rust project, which is organized as a Cargo workspace, builds on stable and doesn't depend on C libraries. |
4 | workspace, builds on stable and doesn't depend on C libraries. So, just | 4 | So, just |
5 | 5 | ||
6 | ``` | 6 | ``` |
7 | $ cargo test | 7 | $ cargo test |
@@ -13,9 +13,8 @@ To learn more about how rust-analyzer works, see [./architecture.md](./architect | |||
13 | It also explains the high-level layout of the source code. | 13 | It also explains the high-level layout of the source code. |
14 | Do skim through that document. | 14 | Do skim through that document. |
15 | 15 | ||
16 | We also publish rustdoc docs to pages: | 16 | We also publish rustdoc docs to pages: https://rust-analyzer.github.io/rust-analyzer/ide/. |
17 | 17 | Note though, that internal documentation is very incomplete. | |
18 | https://rust-analyzer.github.io/rust-analyzer/ide/ | ||
19 | 18 | ||
20 | Various organizational and process issues are discussed in this document. | 19 | Various organizational and process issues are discussed in this document. |
21 | 20 | ||
@@ -25,7 +24,7 @@ Rust Analyzer is a part of [RLS-2.0 working | |||
25 | group](https://github.com/rust-lang/compiler-team/tree/6a769c13656c0a6959ebc09e7b1f7c09b86fb9c0/working-groups/rls-2.0). | 24 | group](https://github.com/rust-lang/compiler-team/tree/6a769c13656c0a6959ebc09e7b1f7c09b86fb9c0/working-groups/rls-2.0). |
26 | Discussion happens in this Zulip stream: | 25 | Discussion happens in this Zulip stream: |
27 | 26 | ||
28 | https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Fwg-rls-2.2E0 | 27 | https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frust-analyzer |
29 | 28 | ||
30 | # Issue Labels | 29 | # Issue Labels |
31 | 30 | ||
@@ -33,6 +32,8 @@ https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Fwg-rls-2.2E0 | |||
33 | are good issues to get into the project. | 32 | are good issues to get into the project. |
34 | * [E-has-instructions](https://github.com/rust-analyzer/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-has-instructions) | 33 | * [E-has-instructions](https://github.com/rust-analyzer/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-has-instructions) |
35 | issues have links to the code in question and tests. | 34 | issues have links to the code in question and tests. |
35 | * [Broken Window](https://github.com/rust-analyzer/rust-analyzer/issues?q=is:issue+is:open+label:%22Broken+Window%22) | ||
36 | are issues which are not critical by themselves, but which should be fixed ASAP regardless, to avoid accumulation of technical debt. | ||
36 | * [E-easy](https://github.com/rust-analyzer/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-easy), | 37 | * [E-easy](https://github.com/rust-analyzer/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-easy), |
37 | [E-medium](https://github.com/rust-analyzer/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-medium), | 38 | [E-medium](https://github.com/rust-analyzer/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-medium), |
38 | [E-hard](https://github.com/rust-analyzer/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-hard), | 39 | [E-hard](https://github.com/rust-analyzer/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-hard), |
@@ -49,21 +50,28 @@ https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Fwg-rls-2.2E0 | |||
49 | Also a kind of fun. | 50 | Also a kind of fun. |
50 | These issues should generally include a link to a Zulip discussion thread. | 51 | These issues should generally include a link to a Zulip discussion thread. |
51 | 52 | ||
52 | # CI | 53 | # Code Style & Review Process |
54 | |||
55 | Do see [./style.md](./style.md). | ||
53 | 56 | ||
54 | We use GitHub Actions for CI. Most of the things, including formatting, are checked by | 57 | # Cookbook |
55 | `cargo test` so, if `cargo test` passes locally, that's a good sign that CI will | 58 | |
56 | be green as well. The only exception is that some long-running tests are skipped locally by default. | 59 | ## CI |
60 | |||
61 | We use GitHub Actions for CI. | ||
62 | Most of the things, including formatting, are checked by `cargo test`. | ||
63 | If `cargo test` passes locally, that's a good sign that CI will be green as well. | ||
64 | The only exception is that some long-running tests are skipped locally by default. | ||
57 | Use `env RUN_SLOW_TESTS=1 cargo test` to run the full suite. | 65 | Use `env RUN_SLOW_TESTS=1 cargo test` to run the full suite. |
58 | 66 | ||
59 | We use bors-ng to enforce the [not rocket science](https://graydon2.dreamwidth.org/1597.html) rule. | 67 | We use bors-ng to enforce the [not rocket science](https://graydon2.dreamwidth.org/1597.html) rule. |
60 | 68 | ||
61 | # Launching rust-analyzer | 69 | ## Launching rust-analyzer |
62 | 70 | ||
63 | Debugging the language server can be tricky. | 71 | Debugging the language server can be tricky. |
64 | LSP is rather chatty, so driving it from the command line is not really feasible, driving it via VS Code requires interacting with two processes. | 72 | LSP is rather chatty, so driving it from the command line is not really feasible, driving it via VS Code requires interacting with two processes. |
65 | 73 | ||
66 | For this reason, the best way to see how rust-analyzer works is to find a relevant test and execute it. | 74 | For this reason, the best way to see how rust-analyzer works is to **find a relevant test and execute it**. |
67 | VS Code & Emacs include an action for running a single test. | 75 | VS Code & Emacs include an action for running a single test. |
68 | 76 | ||
69 | Launching a VS Code instance with a locally built language server is also possible. | 77 | Launching a VS Code instance with a locally built language server is also possible. |
@@ -107,12 +115,7 @@ cd editors/code | |||
107 | npm ci | 115 | npm ci |
108 | npm run lint | 116 | npm run lint |
109 | ``` | 117 | ``` |
110 | 118 | ## How to ... | |
111 | # Code Style & Review Process | ||
112 | |||
113 | Do see [./style.md](./style.md). | ||
114 | |||
115 | # How to ... | ||
116 | 119 | ||
117 | * ... add an assist? [#7535](https://github.com/rust-analyzer/rust-analyzer/pull/7535) | 120 | * ... add an assist? [#7535](https://github.com/rust-analyzer/rust-analyzer/pull/7535) |
118 | * ... add a new protocol extension? [#4569](https://github.com/rust-analyzer/rust-analyzer/pull/4569) | 121 | * ... add a new protocol extension? [#4569](https://github.com/rust-analyzer/rust-analyzer/pull/4569) |
@@ -120,33 +123,30 @@ Do see [./style.md](./style.md). | |||
120 | * ... add a new completion? [#6964](https://github.com/rust-analyzer/rust-analyzer/pull/6964) | 123 | * ... add a new completion? [#6964](https://github.com/rust-analyzer/rust-analyzer/pull/6964) |
121 | * ... allow new syntax in the parser? [#7338](https://github.com/rust-analyzer/rust-analyzer/pull/7338) | 124 | * ... allow new syntax in the parser? [#7338](https://github.com/rust-analyzer/rust-analyzer/pull/7338) |
122 | 125 | ||
123 | # Logging | 126 | ## Logging |
124 | 127 | ||
125 | Logging is done by both rust-analyzer and VS Code, so it might be tricky to | 128 | Logging is done by both rust-analyzer and VS Code, so it might be tricky to figure out where logs go. |
126 | figure out where logs go. | ||
127 | 129 | ||
128 | Inside rust-analyzer, we use the standard `log` crate for logging, and | 130 | Inside rust-analyzer, we use the standard `log` crate for logging, and `env_logger` for logging frontend. |
129 | `env_logger` for logging frontend. By default, log goes to stderr, but the | 131 | By default, log goes to stderr, but the stderr itself is processed by VS Code. |
130 | stderr itself is processed by VS Code. | 132 | `--log-file <PATH>` CLI argument allows logging to file. |
131 | 133 | ||
132 | To see stderr in the running VS Code instance, go to the "Output" tab of the | 134 | To see stderr in the running VS Code instance, go to the "Output" tab of the panel and select `rust-analyzer`. |
133 | panel and select `rust-analyzer`. This shows `eprintln!` as well. Note that | 135 | This shows `eprintln!` as well. |
134 | `stdout` is used for the actual protocol, so `println!` will break things. | 136 | Note that `stdout` is used for the actual protocol, so `println!` will break things. |
135 | 137 | ||
136 | To log all communication between the server and the client, there are two choices: | 138 | To log all communication between the server and the client, there are two choices: |
137 | 139 | ||
138 | * you can log on the server side, by running something like | 140 | * You can log on the server side, by running something like |
139 | ``` | 141 | ``` |
140 | env RA_LOG=lsp_server=debug code . | 142 | env RA_LOG=lsp_server=debug code . |
141 | ``` | 143 | ``` |
142 | 144 | * You can log on the client side, by enabling `"rust-analyzer.trace.server": "verbose"` workspace setting. | |
143 | * you can log on the client side, by enabling `"rust-analyzer.trace.server": | 145 | These logs are shown in a separate tab in the output and could be used with LSP inspector. |
144 | "verbose"` workspace setting. These logs are shown in a separate tab in the | 146 | Kudos to [@DJMcNab](https://github.com/DJMcNab) for setting this awesome infra up! |
145 | output and could be used with LSP inspector. Kudos to | ||
146 | [@DJMcNab](https://github.com/DJMcNab) for setting this awesome infra up! | ||
147 | 147 | ||
148 | 148 | ||
149 | There are also two VS Code commands which might be of interest: | 149 | There are also several VS Code commands which might be of interest: |
150 | 150 | ||
151 | * `Rust Analyzer: Status` shows some memory-usage statistics. | 151 | * `Rust Analyzer: Status` shows some memory-usage statistics. |
152 | 152 | ||
@@ -164,7 +164,7 @@ There are also two VS Code commands which might be of interest: | |||
164 | 164 | ||
165 | ![demo](https://user-images.githubusercontent.com/36276403/78225773-6636a480-74d3-11ea-9d9f-1c9d42da03b0.png) | 165 | ![demo](https://user-images.githubusercontent.com/36276403/78225773-6636a480-74d3-11ea-9d9f-1c9d42da03b0.png) |
166 | 166 | ||
167 | # Profiling | 167 | ## Profiling |
168 | 168 | ||
169 | We have a built-in hierarchical profiler, you can enable it by using `RA_PROFILE` env-var: | 169 | We have a built-in hierarchical profiler, you can enable it by using `RA_PROFILE` env-var: |
170 | 170 | ||
@@ -192,7 +192,9 @@ $ cargo run --release -p rust-analyzer -- analysis-bench ../chalk/ --highlight . | |||
192 | $ cargo run --release -p rust-analyzer -- analysis-bench ../chalk/ --complete ../chalk/chalk-engine/src/logic.rs:94:0 | 192 | $ cargo run --release -p rust-analyzer -- analysis-bench ../chalk/ --complete ../chalk/chalk-engine/src/logic.rs:94:0 |
193 | ``` | 193 | ``` |
194 | 194 | ||
195 | # Release Process | 195 | Look for `fn benchmark_xxx` tests for a quick way to reproduce performance problems. |
196 | |||
197 | ## Release Process | ||
196 | 198 | ||
197 | Release process is handled by `release`, `dist` and `promote` xtasks, `release` being the main one. | 199 | Release process is handled by `release`, `dist` and `promote` xtasks, `release` being the main one. |
198 | 200 | ||
@@ -229,7 +231,7 @@ Make sure to remove the new changelog post created when running `cargo xtask rel | |||
229 | We release "nightly" every night automatically and promote the latest nightly to "stable" manually, every week. | 231 | We release "nightly" every night automatically and promote the latest nightly to "stable" manually, every week. |
230 | We don't do "patch" releases, unless something truly egregious comes up. | 232 | We don't do "patch" releases, unless something truly egregious comes up. |
231 | 233 | ||
232 | # Permissions | 234 | ## Permissions |
233 | 235 | ||
234 | There are three sets of people with extra permissions: | 236 | There are three sets of people with extra permissions: |
235 | 237 | ||
diff --git a/docs/dev/architecture.md b/docs/dev/architecture.md index fb991133a..3ffd9e8cb 100644 --- a/docs/dev/architecture.md +++ b/docs/dev/architecture.md | |||
@@ -42,7 +42,7 @@ The underlying engine makes sure that model is computed lazily (on-demand) and c | |||
42 | ## Entry Points | 42 | ## Entry Points |
43 | 43 | ||
44 | `crates/rust-analyzer/src/bin/main.rs` contains the main function which spawns LSP. | 44 | `crates/rust-analyzer/src/bin/main.rs` contains the main function which spawns LSP. |
45 | This is *the* entry point, but it front-loads a lot of complexity, so its fine to just skim through it. | 45 | This is *the* entry point, but it front-loads a lot of complexity, so it's fine to just skim through it. |
46 | 46 | ||
47 | `crates/rust-analyzer/src/handlers.rs` implements all LSP requests and is a great place to start if you are already familiar with LSP. | 47 | `crates/rust-analyzer/src/handlers.rs` implements all LSP requests and is a great place to start if you are already familiar with LSP. |
48 | 48 | ||
@@ -67,7 +67,7 @@ They are handled by Rust code in the xtask directory. | |||
67 | 67 | ||
68 | VS Code plugin. | 68 | VS Code plugin. |
69 | 69 | ||
70 | ### `libs/` | 70 | ### `lib/` |
71 | 71 | ||
72 | rust-analyzer independent libraries which we publish to crates.io. | 72 | rust-analyzer independent libraries which we publish to crates.io. |
73 | It's not heavily utilized at the moment. | 73 | It's not heavily utilized at the moment. |
@@ -139,7 +139,8 @@ If an AST method returns an `Option`, it *can* be `None` at runtime, even if thi | |||
139 | ### `crates/base_db` | 139 | ### `crates/base_db` |
140 | 140 | ||
141 | We use the [salsa](https://github.com/salsa-rs/salsa) crate for incremental and on-demand computation. | 141 | We use the [salsa](https://github.com/salsa-rs/salsa) crate for incremental and on-demand computation. |
142 | Roughly, you can think of salsa as a key-value store, but it can also compute derived values using specified functions. The `base_db` crate provides basic infrastructure for interacting with salsa. | 142 | Roughly, you can think of salsa as a key-value store, but it can also compute derived values using specified functions. |
143 | The `base_db` crate provides basic infrastructure for interacting with salsa. | ||
143 | Crucially, it defines most of the "input" queries: facts supplied by the client of the analyzer. | 144 | Crucially, it defines most of the "input" queries: facts supplied by the client of the analyzer. |
144 | Reading the docs of the `base_db::input` module should be useful: everything else is strictly derived from those inputs. | 145 | Reading the docs of the `base_db::input` module should be useful: everything else is strictly derived from those inputs. |
145 | 146 | ||
@@ -221,7 +222,7 @@ Internally, `ide` is split across several crates. `ide_assists`, `ide_completion | |||
221 | The `ide` contains a public API/façade, as well as implementation for a plethora of smaller features. | 222 | The `ide` contains a public API/façade, as well as implementation for a plethora of smaller features. |
222 | 223 | ||
223 | **Architecture Invariant:** `ide` crate strives to provide a _perfect_ API. | 224 | **Architecture Invariant:** `ide` crate strives to provide a _perfect_ API. |
224 | Although at the moment it has only one consumer, the LSP server, LSP *does not* influence it's API design. | 225 | Although at the moment it has only one consumer, the LSP server, LSP *does not* influence its API design. |
225 | Instead, we keep in mind a hypothetical _ideal_ client -- an IDE tailored specifically for rust, every nook and cranny of which is packed with Rust-specific goodies. | 226 | Instead, we keep in mind a hypothetical _ideal_ client -- an IDE tailored specifically for rust, every nook and cranny of which is packed with Rust-specific goodies. |
226 | 227 | ||
227 | ### `crates/rust-analyzer` | 228 | ### `crates/rust-analyzer` |
@@ -307,7 +308,7 @@ This sections talks about the things which are everywhere and nowhere in particu | |||
307 | 308 | ||
308 | ### Code generation | 309 | ### Code generation |
309 | 310 | ||
310 | Some of the components of this repository are generated through automatic processes. | 311 | Some ]components in this repository are generated through automatic processes. |
311 | Generated code is updated automatically on `cargo test`. | 312 | Generated code is updated automatically on `cargo test`. |
312 | Generated code is generally committed to the git repository. | 313 | Generated code is generally committed to the git repository. |
313 | 314 | ||
@@ -389,7 +390,7 @@ fn spam() { | |||
389 | ``` | 390 | ``` |
390 | 391 | ||
391 | To specify input data, we use a single string literal in a special format, which can describe a set of rust files. | 392 | To specify input data, we use a single string literal in a special format, which can describe a set of rust files. |
392 | See the `Fixture` type. | 393 | See the `Fixture` its module for fixture examples and documentation. |
393 | 394 | ||
394 | **Architecture Invariant:** all code invariants are tested by `#[test]` tests. | 395 | **Architecture Invariant:** all code invariants are tested by `#[test]` tests. |
395 | There's no additional checks in CI, formatting and tidy tests are run with `cargo test`. | 396 | There's no additional checks in CI, formatting and tidy tests are run with `cargo test`. |
diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md index 8a6f9f06e..a46121bb2 100644 --- a/docs/dev/lsp-extensions.md +++ b/docs/dev/lsp-extensions.md | |||
@@ -1,5 +1,5 @@ | |||
1 | <!--- | 1 | <!--- |
2 | lsp_ext.rs hash: e8a7502bd2b2c2f5 | 2 | lsp_ext.rs hash: faae991334a151d0 |
3 | 3 | ||
4 | If you need to change the above hash to make the test pass, please check if you | 4 | If you need to change the above hash to make the test pass, please check if you |
5 | need to adjust this doc as well and ping this issue: | 5 | need to adjust this doc as well and ping this issue: |
@@ -51,8 +51,8 @@ interface SnippetTextEdit extends TextEdit { | |||
51 | 51 | ||
52 | ```typescript | 52 | ```typescript |
53 | export interface TextDocumentEdit { | 53 | export interface TextDocumentEdit { |
54 | textDocument: OptionalVersionedTextDocumentIdentifier; | 54 | textDocument: OptionalVersionedTextDocumentIdentifier; |
55 | edits: (TextEdit | SnippetTextEdit)[]; | 55 | edits: (TextEdit | SnippetTextEdit)[]; |
56 | } | 56 | } |
57 | ``` | 57 | ``` |
58 | 58 | ||
@@ -145,9 +145,9 @@ mod foo; | |||
145 | ### Unresolved Question | 145 | ### Unresolved Question |
146 | 146 | ||
147 | * An alternative would be to use a more general "gotoSuper" request, which would work for super methods, super classes and super modules. | 147 | * An alternative would be to use a more general "gotoSuper" request, which would work for super methods, super classes and super modules. |
148 | This is the approach IntelliJ Rust is takeing. | 148 | This is the approach IntelliJ Rust is taking. |
149 | However, experience shows that super module (which generally has a feeling of navigation between files) should be separate. | 149 | However, experience shows that super module (which generally has a feeling of navigation between files) should be separate. |
150 | If you want super module, but the cursor happens to be inside an overriden function, the behavior with single "gotoSuper" request is surprising. | 150 | If you want super module, but the cursor happens to be inside an overridden function, the behavior with single "gotoSuper" request is surprising. |
151 | 151 | ||
152 | ## Join Lines | 152 | ## Join Lines |
153 | 153 | ||
@@ -193,7 +193,7 @@ fn main() { | |||
193 | ### Unresolved Question | 193 | ### Unresolved Question |
194 | 194 | ||
195 | * What is the position of the cursor after `joinLines`? | 195 | * What is the position of the cursor after `joinLines`? |
196 | Currently this is left to editor's discretion, but it might be useful to specify on the server via snippets. | 196 | Currently, this is left to editor's discretion, but it might be useful to specify on the server via snippets. |
197 | However, it then becomes unclear how it works with multi cursor. | 197 | However, it then becomes unclear how it works with multi cursor. |
198 | 198 | ||
199 | ## On Enter | 199 | ## On Enter |
@@ -330,7 +330,7 @@ Moreover, it would be cool if editors didn't need to implement even basic langua | |||
330 | 330 | ||
331 | ### Unresolved Question | 331 | ### Unresolved Question |
332 | 332 | ||
333 | * Should we return a a nested brace structure, to allow paredit-like actions of jump *out* of the current brace pair? | 333 | * Should we return a nested brace structure, to allow paredit-like actions of jump *out* of the current brace pair? |
334 | This is how `SelectionRange` request works. | 334 | This is how `SelectionRange` request works. |
335 | * Alternatively, should we perhaps flag certain `SelectionRange`s as being brace pairs? | 335 | * Alternatively, should we perhaps flag certain `SelectionRange`s as being brace pairs? |
336 | 336 | ||
@@ -419,23 +419,37 @@ Returns internal status message, mostly for debugging purposes. | |||
419 | 419 | ||
420 | Reloads project information (that is, re-executes `cargo metadata`). | 420 | Reloads project information (that is, re-executes `cargo metadata`). |
421 | 421 | ||
422 | ## Status Notification | 422 | ## Server Status |
423 | 423 | ||
424 | **Experimental Client Capability:** `{ "statusNotification": boolean }` | 424 | **Experimental Client Capability:** `{ "serverStatus": boolean }` |
425 | 425 | ||
426 | **Method:** `rust-analyzer/status` | 426 | **Method:** `experimental/serverStatus` |
427 | 427 | ||
428 | **Notification:** | 428 | **Notification:** |
429 | 429 | ||
430 | ```typescript | 430 | ```typescript |
431 | interface StatusParams { | 431 | interface ServerStatusParams { |
432 | status: "loading" | "readyPartial" | "ready" | "invalid" | "needsReload", | 432 | /// `ok` means that the server is completely functional. |
433 | /// | ||
434 | /// `warning` means that the server is partially functional. | ||
435 | /// It can server requests, but some results might be wrong due to, | ||
436 | /// for example, some missing dependencies. | ||
437 | /// | ||
438 | /// `error` means that the server is not functional. For example, | ||
439 | /// there's a fatal build configuration problem. | ||
440 | health: "ok" | "warning" | "error", | ||
441 | /// Is there any pending background work which might change the status? | ||
442 | /// For example, are dependencies being downloaded? | ||
443 | quiescent: bool, | ||
444 | /// Explanatory message to show on hover. | ||
445 | message?: string, | ||
433 | } | 446 | } |
434 | ``` | 447 | ``` |
435 | 448 | ||
436 | This notification is sent from server to client. | 449 | This notification is sent from server to client. |
437 | The client can use it to display persistent status to the user (in modline). | 450 | The client can use it to display *persistent* status to the user (in modline). |
438 | For `needsReload` state, the client can provide a context-menu action to run `rust-analyzer/reloadWorkspace` request. | 451 | It is similar to the `showMessage`, but is intended for stares rather than point-in-time events. |
452 | |||
439 | 453 | ||
440 | ## Syntax Tree | 454 | ## Syntax Tree |
441 | 455 | ||
@@ -497,7 +511,7 @@ Expands macro call at a given position. | |||
497 | This request is sent from client to server to render "inlay hints" -- virtual text inserted into editor to show things like inferred types. | 511 | This request is sent from client to server to render "inlay hints" -- virtual text inserted into editor to show things like inferred types. |
498 | Generally, the client should re-query inlay hints after every modification. | 512 | Generally, the client should re-query inlay hints after every modification. |
499 | Note that we plan to move this request to `experimental/inlayHints`, as it is not really Rust-specific, but the current API is not necessary the right one. | 513 | Note that we plan to move this request to `experimental/inlayHints`, as it is not really Rust-specific, but the current API is not necessary the right one. |
500 | Upstream issue: https://github.com/microsoft/language-server-protocol/issues/956 | 514 | Upstream issues: https://github.com/microsoft/language-server-protocol/issues/956 , https://github.com/rust-analyzer/rust-analyzer/issues/2797 |
501 | 515 | ||
502 | **Request:** | 516 | **Request:** |
503 | 517 | ||
@@ -602,8 +616,7 @@ interface TestInfo { | |||
602 | 616 | ||
603 | This request is sent from client to server to move item under cursor or selection in some direction. | 617 | This request is sent from client to server to move item under cursor or selection in some direction. |
604 | 618 | ||
605 | **Method:** `experimental/moveItemUp` | 619 | **Method:** `experimental/moveItem` |
606 | **Method:** `experimental/moveItemDown` | ||
607 | 620 | ||
608 | **Request:** `MoveItemParams` | 621 | **Request:** `MoveItemParams` |
609 | 622 | ||
diff --git a/docs/dev/style.md b/docs/dev/style.md index e4a1672ca..468dedff2 100644 --- a/docs/dev/style.md +++ b/docs/dev/style.md | |||
@@ -53,11 +53,11 @@ https://www.tedinski.com/2018/02/06/system-boundaries.html | |||
53 | ## Crates.io Dependencies | 53 | ## Crates.io Dependencies |
54 | 54 | ||
55 | We try to be very conservative with usage of crates.io dependencies. | 55 | We try to be very conservative with usage of crates.io dependencies. |
56 | Don't use small "helper" crates (exception: `itertools` is allowed). | 56 | Don't use small "helper" crates (exception: `itertools` and `either` are allowed). |
57 | If there's some general reusable bit of code you need, consider adding it to the `stdx` crate. | 57 | If there's some general reusable bit of code you need, consider adding it to the `stdx` crate. |
58 | A useful exercise is to read Cargo.lock and see if some *transitive* dependencies do not make sense for rust-analyzer. | ||
58 | 59 | ||
59 | **Rationale:** keep compile times low, create ecosystem pressure for faster | 60 | **Rationale:** keep compile times low, create ecosystem pressure for faster compiles, reduce the number of things which might break. |
60 | compiles, reduce the number of things which might break. | ||
61 | 61 | ||
62 | ## Commit Style | 62 | ## Commit Style |
63 | 63 | ||
@@ -330,7 +330,7 @@ When implementing `do_thing`, it might be very useful to create a context object | |||
330 | 330 | ||
331 | ```rust | 331 | ```rust |
332 | pub fn do_thing(arg1: Arg1, arg2: Arg2) -> Res { | 332 | pub fn do_thing(arg1: Arg1, arg2: Arg2) -> Res { |
333 | let mut ctx = Ctx { arg1, arg2 } | 333 | let mut ctx = Ctx { arg1, arg2 }; |
334 | ctx.run() | 334 | ctx.run() |
335 | } | 335 | } |
336 | 336 | ||
@@ -586,7 +586,7 @@ use super::{} | |||
586 | 586 | ||
587 | **Rationale:** consistency. | 587 | **Rationale:** consistency. |
588 | Reading order is important for new contributors. | 588 | Reading order is important for new contributors. |
589 | Grouping by crate allows to spot unwanted dependencies easier. | 589 | Grouping by crate allows spotting unwanted dependencies easier. |
590 | 590 | ||
591 | ## Import Style | 591 | ## Import Style |
592 | 592 | ||
@@ -779,7 +779,7 @@ assert!(x < y); | |||
779 | assert!(x > 0); | 779 | assert!(x > 0); |
780 | 780 | ||
781 | // BAD | 781 | // BAD |
782 | assert!(x >= lo && x <= hi>); | 782 | assert!(x >= lo && x <= hi); |
783 | assert!(r1 < l2 || l1 > r2); | 783 | assert!(r1 < l2 || l1 > r2); |
784 | assert!(y > x); | 784 | assert!(y > x); |
785 | assert!(0 > x); | 785 | assert!(0 > x); |
@@ -806,9 +806,67 @@ if let Some(expected_type) = ctx.expected_type.as_ref() { | |||
806 | } | 806 | } |
807 | ``` | 807 | ``` |
808 | 808 | ||
809 | **Rational:** `match` is almost always more compact. | 809 | **Rationale:** `match` is almost always more compact. |
810 | The `else` branch can get a more precise pattern: `None` or `Err(_)` instead of `_`. | 810 | The `else` branch can get a more precise pattern: `None` or `Err(_)` instead of `_`. |
811 | 811 | ||
812 | ## Helper Functions | ||
813 | |||
814 | Avoid creating singe-use helper functions: | ||
815 | |||
816 | ```rust | ||
817 | // GOOD | ||
818 | let buf = { | ||
819 | let mut buf = get_empty_buf(&mut arena); | ||
820 | buf.add_item(item); | ||
821 | buf | ||
822 | }; | ||
823 | |||
824 | // BAD | ||
825 | |||
826 | let buf = prepare_buf(&mut arena, item); | ||
827 | |||
828 | ... | ||
829 | |||
830 | fn prepare_buf(arena: &mut Arena, item: Item) -> ItemBuf { | ||
831 | let mut res = get_empty_buf(&mut arena); | ||
832 | res.add_item(item); | ||
833 | res | ||
834 | } | ||
835 | ``` | ||
836 | |||
837 | Exception: if you want to make use of `return` or `?`. | ||
838 | |||
839 | **Rationale:** single-use functions change frequently, adding or removing parameters adds churn. | ||
840 | A block serves just as well to delineate a bit of logic, but has access to all the context. | ||
841 | Re-using originally single-purpose function often leads to bad coupling. | ||
842 | |||
843 | ## Helper Variables | ||
844 | |||
845 | Introduce helper variables freely, especially for multiline conditions: | ||
846 | |||
847 | ```rust | ||
848 | // GOOD | ||
849 | let rustfmt_not_installed = | ||
850 | captured_stderr.contains("not installed") || captured_stderr.contains("not available"); | ||
851 | |||
852 | match output.status.code() { | ||
853 | Some(1) if !rustfmt_not_installed => Ok(None), | ||
854 | _ => Err(format_err!("rustfmt failed:\n{}", captured_stderr)), | ||
855 | }; | ||
856 | |||
857 | // BAD | ||
858 | match output.status.code() { | ||
859 | Some(1) | ||
860 | if !captured_stderr.contains("not installed") | ||
861 | && !captured_stderr.contains("not available") => Ok(None), | ||
862 | _ => Err(format_err!("rustfmt failed:\n{}", captured_stderr)), | ||
863 | }; | ||
864 | ``` | ||
865 | |||
866 | **Rationale:** like blocks, single-use variables are a cognitively cheap abstraction, as they have access to all the context. | ||
867 | Extra variables help during debugging, they make it easy to print/view important intermediate results. | ||
868 | Giving a name to a condition in `if` expression often improves clarity and leads to a nicer formatted code. | ||
869 | |||
812 | ## Token names | 870 | ## Token names |
813 | 871 | ||
814 | Use `T![foo]` instead of `SyntaxKind::FOO_KW`. | 872 | Use `T![foo]` instead of `SyntaxKind::FOO_KW`. |
diff --git a/docs/dev/syntax.md b/docs/dev/syntax.md index 737cc7a72..f7a0c09fc 100644 --- a/docs/dev/syntax.md +++ b/docs/dev/syntax.md | |||
@@ -145,7 +145,7 @@ Another alternative (used by swift and roslyn) is to explicitly divide the set o | |||
145 | 145 | ||
146 | ```rust | 146 | ```rust |
147 | struct Token { | 147 | struct Token { |
148 | kind: NonTriviaTokenKind | 148 | kind: NonTriviaTokenKind, |
149 | text: String, | 149 | text: String, |
150 | leading_trivia: Vec<TriviaToken>, | 150 | leading_trivia: Vec<TriviaToken>, |
151 | trailing_trivia: Vec<TriviaToken>, | 151 | trailing_trivia: Vec<TriviaToken>, |
@@ -240,7 +240,7 @@ impl SyntaxNode { | |||
240 | let child_offset = offset; | 240 | let child_offset = offset; |
241 | offset += green_child.text_len; | 241 | offset += green_child.text_len; |
242 | Arc::new(SyntaxData { | 242 | Arc::new(SyntaxData { |
243 | offset: child_offset; | 243 | offset: child_offset, |
244 | parent: Some(Arc::clone(self)), | 244 | parent: Some(Arc::clone(self)), |
245 | green: Arc::clone(green_child), | 245 | green: Arc::clone(green_child), |
246 | }) | 246 | }) |
@@ -249,7 +249,7 @@ impl SyntaxNode { | |||
249 | } | 249 | } |
250 | 250 | ||
251 | impl PartialEq for SyntaxNode { | 251 | impl PartialEq for SyntaxNode { |
252 | fn eq(&self, other: &SyntaxNode) { | 252 | fn eq(&self, other: &SyntaxNode) -> bool { |
253 | self.offset == other.offset | 253 | self.offset == other.offset |
254 | && Arc::ptr_eq(&self.green, &other.green) | 254 | && Arc::ptr_eq(&self.green, &other.green) |
255 | } | 255 | } |
@@ -273,7 +273,7 @@ This is OK because trees traversals mostly (always, in case of rust-analyzer) ru | |||
273 | The other thread can restore the `SyntaxNode` by traversing from the root green node and looking for a node with specified range. | 273 | The other thread can restore the `SyntaxNode` by traversing from the root green node and looking for a node with specified range. |
274 | You can also use the similar trick to store a `SyntaxNode`. | 274 | You can also use the similar trick to store a `SyntaxNode`. |
275 | That is, a data structure that holds a `(GreenNode, Range<usize>)` will be `Sync`. | 275 | That is, a data structure that holds a `(GreenNode, Range<usize>)` will be `Sync`. |
276 | However rust-analyzer goes even further. | 276 | However, rust-analyzer goes even further. |
277 | It treats trees as semi-transient and instead of storing a `GreenNode`, it generally stores just the id of the file from which the tree originated: `(FileId, Range<usize>)`. | 277 | It treats trees as semi-transient and instead of storing a `GreenNode`, it generally stores just the id of the file from which the tree originated: `(FileId, Range<usize>)`. |
278 | The `SyntaxNode` is the restored by reparsing the file and traversing it from root. | 278 | The `SyntaxNode` is the restored by reparsing the file and traversing it from root. |
279 | With this trick, rust-analyzer holds only a small amount of trees in memory at the same time, which reduces memory usage. | 279 | With this trick, rust-analyzer holds only a small amount of trees in memory at the same time, which reduces memory usage. |
diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc index 36a86e78f..e74b287fb 100644 --- a/docs/user/manual.adoc +++ b/docs/user/manual.adoc | |||
@@ -178,6 +178,15 @@ $ cargo xtask install --server | |||
178 | If your editor can't find the binary even though the binary is on your `$PATH`, the likely explanation is that it doesn't see the same `$PATH` as the shell, see https://github.com/rust-analyzer/rust-analyzer/issues/1811[this issue]. | 178 | If your editor can't find the binary even though the binary is on your `$PATH`, the likely explanation is that it doesn't see the same `$PATH` as the shell, see https://github.com/rust-analyzer/rust-analyzer/issues/1811[this issue]. |
179 | On Unix, running the editor from a shell or changing the `.desktop` file to set the environment should help. | 179 | On Unix, running the editor from a shell or changing the `.desktop` file to set the environment should help. |
180 | 180 | ||
181 | ==== `rustup` | ||
182 | |||
183 | `rust-analyzer` is available in `rustup`, but only in the nightly toolchain: | ||
184 | |||
185 | [source,bash] | ||
186 | --- | ||
187 | $ rustup +nightly component add rust-analyzer-preview | ||
188 | --- | ||
189 | |||
181 | ==== Arch Linux | 190 | ==== Arch Linux |
182 | 191 | ||
183 | The `rust-analyzer` binary can be installed from the repos or AUR (Arch User Repository): | 192 | The `rust-analyzer` binary can be installed from the repos or AUR (Arch User Repository): |
@@ -245,23 +254,10 @@ let g:LanguageClient_serverCommands = { | |||
245 | 254 | ||
246 | ==== YouCompleteMe | 255 | ==== YouCompleteMe |
247 | 256 | ||
248 | 1. Install YouCompleteMe by following the instructions | 257 | Install YouCompleteMe by following the instructions |
249 | https://github.com/ycm-core/lsp-examples#rust-rust-analyzer[here] | 258 | https://github.com/ycm-core/YouCompleteMe#installation[here]. |
250 | 259 | ||
251 | 2. Configure by adding this to your vim/neovim config file (replacing the existing Rust-specific line if it exists): | 260 | rust-analyzer is the default in ycm, it should work out of the box. |
252 | + | ||
253 | [source,vim] | ||
254 | ---- | ||
255 | let g:ycm_language_server = | ||
256 | \ [ | ||
257 | \ { | ||
258 | \ 'name': 'rust', | ||
259 | \ 'cmdline': ['rust-analyzer'], | ||
260 | \ 'filetypes': ['rust'], | ||
261 | \ 'project_root_files': ['Cargo.toml'] | ||
262 | \ } | ||
263 | \ ] | ||
264 | ---- | ||
265 | 261 | ||
266 | ==== ALE | 262 | ==== ALE |
267 | 263 | ||