]> git.lizzy.rs Git - rust.git/blobdiff - docs/dev/syntax.md
internal: use idiomatic form of assertions
[rust.git] / docs / dev / syntax.md
index 1edafab680e9930476b1c31d8b647f60687b087f..4f45aa321b3ba4a1a05e02aad0087320b7ee7571 100644 (file)
@@ -6,7 +6,7 @@ This guide describes the current state of syntax trees and parsing in rust-analy
 
 ## Source Code
 
-The things described are implemented in two places
+The things described are implemented in three places
 
 * [rowan](https://github.com/rust-analyzer/rowan/tree/v0.9.0) -- a generic library for rowan syntax trees.
 * [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.
@@ -15,9 +15,9 @@ The things described are implemented in two places
 
 ## Design Goals
 
-* Syntax trees are lossless, or full fidelity. All comments and whitespace are preserved.
+* Syntax trees are lossless, or full fidelity. All comments and whitespace get preserved.
 * Syntax trees are semantic-less. They describe *strictly* the structure of a sequence of characters, they don't have hygiene, name resolution or type information attached.
-* Syntax trees are simple value type. It is possible to create trees for a syntax without any external context.
+* Syntax trees are simple value types. It is possible to create trees for a syntax without any external context.
 * Syntax trees have intuitive traversal API (parent, children, siblings, etc).
 * Parsing is lossless (even if the input is invalid, the tree produced by the parser represents it exactly).
 * Parsing is resilient (even if the input is invalid, parser tries to see as much syntax tree fragments in the input as it can).
@@ -92,26 +92,25 @@ FN@0..17
     R_PAREN@5..6 ")"
   WHITESPACE@6..7 " "
   BLOCK_EXPR@7..17
-    BLOCK@7..17
-      L_CURLY@7..8 "{"
-      WHITESPACE@8..9 " "
-      BIN_EXPR@9..15
-        LITERAL@9..11
-          INT_NUMBER@9..11 "90"
-        WHITESPACE@11..12 " "
-        PLUS@12..13 "+"
-        WHITESPACE@13..14 " "
-        LITERAL@14..15
-          INT_NUMBER@14..15 "2"
-      WHITESPACE@15..16 " "
-      R_CURLY@16..17 "}"
+    L_CURLY@7..8 "{"
+    WHITESPACE@8..9 " "
+    BIN_EXPR@9..15
+      LITERAL@9..11
+        INT_NUMBER@9..11 "90"
+      WHITESPACE@11..12 " "
+      PLUS@12..13 "+"
+      WHITESPACE@13..14 " "
+      LITERAL@14..15
+        INT_NUMBER@14..15 "2"
+    WHITESPACE@15..16 " "
+    R_CURLY@16..17 "}"
 ```
 
 #### Optimizations
 
 (significant amount of implementation work here was done by [CAD97](https://github.com/cad97)).
 
-To reduce the amount of allocations, the GreenNode is a DST, which uses a single allocation for header and children. Thus, it is only usable behind a pointer
+To reduce the amount of allocations, the GreenNode is a [DST](https://doc.rust-lang.org/reference/dynamically-sized-types.html), which uses a single allocation for header and children. Thus, it is only usable behind a pointer.
 
 ```
 *-----------+------+----------+------------+--------+--------+-----+--------*
@@ -146,7 +145,7 @@ Another alternative (used by swift and roslyn) is to explicitly divide the set o
 
 ```rust
 struct Token {
-    kind: NonTriviaTokenKind
+    kind: NonTriviaTokenKind,
     text: String,
     leading_trivia: Vec<TriviaToken>,
     trailing_trivia: Vec<TriviaToken>,
@@ -241,7 +240,7 @@ impl SyntaxNode {
             let child_offset = offset;
             offset += green_child.text_len;
             Arc::new(SyntaxData {
-                offset: child_offset;
+                offset: child_offset,
                 parent: Some(Arc::clone(self)),
                 green: Arc::clone(green_child),
             })
@@ -250,7 +249,7 @@ impl SyntaxNode {
 }
 
 impl PartialEq for SyntaxNode {
-    fn eq(&self, other: &SyntaxNode) {
+    fn eq(&self, other: &SyntaxNode) -> bool {
         self.offset == other.offset
             && Arc::ptr_eq(&self.green, &other.green)
     }
@@ -274,7 +273,7 @@ This is OK because trees traversals mostly (always, in case of rust-analyzer) ru
 The other thread can restore the `SyntaxNode` by traversing from the root green node and looking for a node with specified range.
 You can also use the similar trick to store a `SyntaxNode`.
 That is, a data structure that holds a `(GreenNode, Range<usize>)` will be `Sync`.
-However rust-analyzer goes even further.
+However, rust-analyzer goes even further.
 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>)`.
 The `SyntaxNode` is the restored by reparsing the file and traversing it from root.
 With this trick, rust-analyzer holds only a small amount of trees in memory at the same time, which reduces memory usage.
@@ -387,7 +386,7 @@ trait HasVisibility: AstNode {
     fn visibility(&self) -> Option<Visibility>;
 }
 
-impl HasVisbility for FnDef {
+impl HasVisibility for FnDef {
     fn visibility(&self) -> Option<Visibility> {
         self.syntax.children().find_map(Visibility::cast)
     }
@@ -527,7 +526,7 @@ In practice, incremental reparsing doesn't actually matter much for IDE use-case
 
 ### Parsing Algorithm
 
-We use a boring hand-crafted recursive descent + pratt combination, with a special effort of continuting the parsing if an error is detected.
+We use a boring hand-crafted recursive descent + pratt combination, with a special effort of continuing the parsing if an error is detected.
 
 ### Parser Recap