diff options
-rw-r--r-- | docs/dev/architecture.md | 15 | ||||
-rw-r--r-- | docs/dev/lsp-extensions.md | 2 | ||||
-rw-r--r-- | docs/dev/style.md | 12 | ||||
-rw-r--r-- | docs/dev/syntax.md | 29 |
4 files changed, 31 insertions, 27 deletions
diff --git a/docs/dev/architecture.md b/docs/dev/architecture.md index feda20dd7..e97e082fc 100644 --- a/docs/dev/architecture.md +++ b/docs/dev/architecture.md | |||
@@ -115,7 +115,7 @@ This is important because it is possible to useful tooling using only syntax tre | |||
115 | Without semantic information, you don't need to be able to _build_ code, which makes the tooling more robust. | 115 | Without semantic information, you don't need to be able to _build_ code, which makes the tooling more robust. |
116 | See also https://web.stanford.edu/~mlfbrown/paper.pdf. | 116 | See also https://web.stanford.edu/~mlfbrown/paper.pdf. |
117 | You can view the `syntax` crate as an entry point to rust-analyzer. | 117 | You can view the `syntax` crate as an entry point to rust-analyzer. |
118 | `sytax` crate is an **API Boundary**. | 118 | `syntax` crate is an **API Boundary**. |
119 | 119 | ||
120 | **Architecture Invariant:** syntax tree is a value type. | 120 | **Architecture Invariant:** syntax tree is a value type. |
121 | The tree is fully determined by the contents of its syntax nodes, it doesn't need global context (like an interner) and doesn't store semantic info. | 121 | The tree is fully determined by the contents of its syntax nodes, it doesn't need global context (like an interner) and doesn't store semantic info. |
@@ -198,14 +198,14 @@ It is an **API Boundary**. | |||
198 | If you want to use IDE parts of rust-analyzer via LSP, custom flatbuffers-based protocol or just as a library in your text editor, this is the right API. | 198 | If you want to use IDE parts of rust-analyzer via LSP, custom flatbuffers-based protocol or just as a library in your text editor, this is the right API. |
199 | 199 | ||
200 | **Architecture Invariant:** `ide` crate's API is build out of POD types with public fields. | 200 | **Architecture Invariant:** `ide` crate's API is build out of POD types with public fields. |
201 | The API uses editor's terminology, it talks about offsets and string labels rathe than in terms of definitions or types. | 201 | The API uses editor's terminology, it talks about offsets and string labels rather than in terms of definitions or types. |
202 | It is effectively the view in MVC and viewmodel in [MVVM](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93viewmodel). | 202 | It is effectively the view in MVC and viewmodel in [MVVM](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93viewmodel). |
203 | All arguments and return types are conceptually serializable. | 203 | All arguments and return types are conceptually serializable. |
204 | In particular, syntax tress and and hir types are generally absent from the API (but are used heavily in the implementation). | 204 | In particular, syntax tress and and hir types are generally absent from the API (but are used heavily in the implementation). |
205 | Shout outs to LSP developers for popularizing the idea that "UI" is a good place to draw a boundary at. | 205 | Shout outs to LSP developers for popularizing the idea that "UI" is a good place to draw a boundary at. |
206 | 206 | ||
207 | `ide` is also the first crate which has the notion of change over time. | 207 | `ide` is also the first crate which has the notion of change over time. |
208 | `AnalysisHost` is a state to which you can transactonally `apply_change`. | 208 | `AnalysisHost` is a state to which you can transactionally `apply_change`. |
209 | `Analysis` is an immutable snapshot of the state. | 209 | `Analysis` is an immutable snapshot of the state. |
210 | 210 | ||
211 | Internally, `ide` is split across several crates. `ide_assists`, `ide_completion` and `ide_ssr` implement large isolated features. | 211 | Internally, `ide` is split across several crates. `ide_assists`, `ide_completion` and `ide_ssr` implement large isolated features. |
@@ -254,6 +254,10 @@ A single `rust-analyzer` process can serve many projects, so it is important tha | |||
254 | These crates implement macros as token tree -> token tree transforms. | 254 | These crates implement macros as token tree -> token tree transforms. |
255 | They are independent from the rest of the code. | 255 | They are independent from the rest of the code. |
256 | 256 | ||
257 | ### `crates/cfg` | ||
258 | |||
259 | This crate is responsible for parsing, evaluation and general definition of `cfg` attributes. | ||
260 | |||
257 | ### `crates/vfs`, `crates/vfs-notify` | 261 | ### `crates/vfs`, `crates/vfs-notify` |
258 | 262 | ||
259 | These crates implement a virtual fils system. | 263 | These crates implement a virtual fils system. |
@@ -265,7 +269,8 @@ For this reason, all path APIs generally take some existing path as a "file syst | |||
265 | 269 | ||
266 | ### `crates/stdx` | 270 | ### `crates/stdx` |
267 | 271 | ||
268 | This crate contains various non-rust-analyzer specific utils, which could have been in std. | 272 | This crate contains various non-rust-analyzer specific utils, which could have been in std, as well |
273 | as copies of unstable std items we would like to make use of already, like `std::str::split_once`. | ||
269 | 274 | ||
270 | ### `crates/profile` | 275 | ### `crates/profile` |
271 | 276 | ||
@@ -285,7 +290,7 @@ There are tests to check that the generated code is fresh. | |||
285 | 290 | ||
286 | In particular, we generate: | 291 | In particular, we generate: |
287 | 292 | ||
288 | * API for working with syntax trees (`syntax::ast`, the `ungrammar` crate). | 293 | * API for working with syntax trees (`syntax::ast`, the [`ungrammar`](https://github.com/rust-analyzer/ungrammar) crate). |
289 | * Various sections of the manual: | 294 | * Various sections of the manual: |
290 | 295 | ||
291 | * features | 296 | * features |
diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md index d7f287894..b2defa737 100644 --- a/docs/dev/lsp-extensions.md +++ b/docs/dev/lsp-extensions.md | |||
@@ -238,7 +238,7 @@ As proper cursor positioning is raison-d'etat for `onEnter`, it uses `SnippetTex | |||
238 | * How to deal with synchronicity of the request? | 238 | * How to deal with synchronicity of the request? |
239 | One option is to require the client to block until the server returns the response. | 239 | One option is to require the client to block until the server returns the response. |
240 | Another option is to do a OT-style merging of edits from client and server. | 240 | Another option is to do a OT-style merging of edits from client and server. |
241 | A third option is to do a record-replay: client applies heuristic on enter immediatelly, then applies all user's keypresses. | 241 | A third option is to do a record-replay: client applies heuristic on enter immediately, then applies all user's keypresses. |
242 | When the server is ready with the response, the client rollbacks all the changes and applies the recorded actions on top of the correct response. | 242 | When the server is ready with the response, the client rollbacks all the changes and applies the recorded actions on top of the correct response. |
243 | * How to deal with multiple carets? | 243 | * How to deal with multiple carets? |
244 | * Should we extend this to arbitrary typed events and not just `onEnter`? | 244 | * Should we extend this to arbitrary typed events and not just `onEnter`? |
diff --git a/docs/dev/style.md b/docs/dev/style.md index e2f1b6996..0482bc190 100644 --- a/docs/dev/style.md +++ b/docs/dev/style.md | |||
@@ -159,7 +159,7 @@ Express function preconditions in types and force the caller to provide them (ra | |||
159 | 159 | ||
160 | ```rust | 160 | ```rust |
161 | // GOOD | 161 | // GOOD |
162 | fn frbonicate(walrus: Walrus) { | 162 | fn frobnicate(walrus: Walrus) { |
163 | ... | 163 | ... |
164 | } | 164 | } |
165 | 165 | ||
@@ -374,7 +374,7 @@ Avoid making a lot of code type parametric, *especially* on the boundaries betwe | |||
374 | 374 | ||
375 | ```rust | 375 | ```rust |
376 | // GOOD | 376 | // GOOD |
377 | fn frbonicate(f: impl FnMut()) { | 377 | fn frobnicate(f: impl FnMut()) { |
378 | frobnicate_impl(&mut f) | 378 | frobnicate_impl(&mut f) |
379 | } | 379 | } |
380 | fn frobnicate_impl(f: &mut dyn FnMut()) { | 380 | fn frobnicate_impl(f: &mut dyn FnMut()) { |
@@ -382,7 +382,7 @@ fn frobnicate_impl(f: &mut dyn FnMut()) { | |||
382 | } | 382 | } |
383 | 383 | ||
384 | // BAD | 384 | // BAD |
385 | fn frbonicate(f: impl FnMut()) { | 385 | fn frobnicate(f: impl FnMut()) { |
386 | // lots of code | 386 | // lots of code |
387 | } | 387 | } |
388 | ``` | 388 | ``` |
@@ -391,11 +391,11 @@ Avoid `AsRef` polymorphism, it pays back only for widely used libraries: | |||
391 | 391 | ||
392 | ```rust | 392 | ```rust |
393 | // GOOD | 393 | // GOOD |
394 | fn frbonicate(f: &Path) { | 394 | fn frobnicate(f: &Path) { |
395 | } | 395 | } |
396 | 396 | ||
397 | // BAD | 397 | // BAD |
398 | fn frbonicate(f: impl AsRef<Path>) { | 398 | fn frobnicate(f: impl AsRef<Path>) { |
399 | } | 399 | } |
400 | ``` | 400 | ``` |
401 | 401 | ||
@@ -705,7 +705,7 @@ fn foo() -> Option<Bar> { | |||
705 | } | 705 | } |
706 | ``` | 706 | ``` |
707 | 707 | ||
708 | **Rationale:** reduce congnitive stack usage. | 708 | **Rationale:** reduce cognitive stack usage. |
709 | 709 | ||
710 | ## Comparisons | 710 | ## Comparisons |
711 | 711 | ||
diff --git a/docs/dev/syntax.md b/docs/dev/syntax.md index 1edafab68..737cc7a72 100644 --- a/docs/dev/syntax.md +++ b/docs/dev/syntax.md | |||
@@ -92,19 +92,18 @@ [email protected] | |||
92 | [email protected] ")" | 92 | [email protected] ")" |
93 | [email protected] " " | 93 | [email protected] " " |
94 | [email protected] | 94 | [email protected] |
95 | [email protected] | 95 | [email protected] "{" |
96 | [email protected] "{" | 96 | [email protected] " " |
97 | [email protected] " " | 97 | [email protected] |
98 | [email protected] | 98 | [email protected] |
99 | [email protected] | 99 | [email protected] "90" |
100 | [email protected] "90" | 100 | [email protected] " " |
101 | [email protected] " " | 101 | [email protected] "+" |
102 | [email protected] "+" | 102 | [email protected] " " |
103 | [email protected] " " | 103 | [email protected] |
104 | [email protected] | 104 | [email protected] "2" |
105 | [email protected] "2" | 105 | [email protected] " " |
106 | [email protected] " " | 106 | [email protected] "}" |
107 | [email protected] "}" | ||
108 | ``` | 107 | ``` |
109 | 108 | ||
110 | #### Optimizations | 109 | #### Optimizations |
@@ -387,7 +386,7 @@ trait HasVisibility: AstNode { | |||
387 | fn visibility(&self) -> Option<Visibility>; | 386 | fn visibility(&self) -> Option<Visibility>; |
388 | } | 387 | } |
389 | 388 | ||
390 | impl HasVisbility for FnDef { | 389 | impl HasVisibility for FnDef { |
391 | fn visibility(&self) -> Option<Visibility> { | 390 | fn visibility(&self) -> Option<Visibility> { |
392 | self.syntax.children().find_map(Visibility::cast) | 391 | self.syntax.children().find_map(Visibility::cast) |
393 | } | 392 | } |
@@ -527,7 +526,7 @@ In practice, incremental reparsing doesn't actually matter much for IDE use-case | |||
527 | 526 | ||
528 | ### Parsing Algorithm | 527 | ### Parsing Algorithm |
529 | 528 | ||
530 | We use a boring hand-crafted recursive descent + pratt combination, with a special effort of continuting the parsing if an error is detected. | 529 | We use a boring hand-crafted recursive descent + pratt combination, with a special effort of continuing the parsing if an error is detected. |
531 | 530 | ||
532 | ### Parser Recap | 531 | ### Parser Recap |
533 | 532 | ||