diff options
Diffstat (limited to 'docs')
-rw-r--r-- | docs/dev/README.md | 4 | ||||
-rw-r--r-- | docs/dev/architecture.md | 13 | ||||
-rw-r--r-- | docs/dev/lsp-extensions.md | 44 | ||||
-rw-r--r-- | docs/dev/style.md | 10 | ||||
-rw-r--r-- | docs/dev/syntax.md | 8 |
5 files changed, 48 insertions, 31 deletions
diff --git a/docs/dev/README.md b/docs/dev/README.md index eab21a765..9c0eb1358 100644 --- a/docs/dev/README.md +++ b/docs/dev/README.md | |||
@@ -24,7 +24,7 @@ Rust Analyzer is a part of [RLS-2.0 working | |||
24 | 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). |
25 | Discussion happens in this Zulip stream: | 25 | Discussion happens in this Zulip stream: |
26 | 26 | ||
27 | 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 |
28 | 28 | ||
29 | # Issue Labels | 29 | # Issue Labels |
30 | 30 | ||
@@ -32,6 +32,8 @@ https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Fwg-rls-2.2E0 | |||
32 | are good issues to get into the project. | 32 | are good issues to get into the project. |
33 | * [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) |
34 | 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. | ||
35 | * [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), |
36 | [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), |
37 | [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), |
diff --git a/docs/dev/architecture.md b/docs/dev/architecture.md index fb991133a..39edf9e19 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 73be59a82..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 | ||
diff --git a/docs/dev/style.md b/docs/dev/style.md index 48ce4b92a..468dedff2 100644 --- a/docs/dev/style.md +++ b/docs/dev/style.md | |||
@@ -53,9 +53,9 @@ 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 of the *transitive* dependencies do not make sense for rust-analyzer. | 58 | A useful exercise is to read Cargo.lock and see if some *transitive* dependencies do not make sense for rust-analyzer. |
59 | 59 | ||
60 | **Rationale:** keep compile times low, create ecosystem pressure for faster compiles, reduce the number of things which might break. | 60 | **Rationale:** keep compile times low, create ecosystem pressure for faster compiles, reduce the number of things which might break. |
61 | 61 | ||
@@ -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); |
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. |