diff options
| author | PgBiel <9021226+PgBiel@users.noreply.github.com> | 2024-06-11 14:27:35 -0300 |
|---|---|---|
| committer | PgBiel <9021226+PgBiel@users.noreply.github.com> | 2024-06-26 12:17:53 -0300 |
| commit | fe860f8b6bee5c8fcbc6c762b03a8f42fccb9240 (patch) | |
| tree | 4d2c04bb8e2a37beeaaecba02469d898ebfafcb5 /crates/typst-syntax | |
| parent | f8958961cb70cc77ec36f40bb99504ab9eca88f8 (diff) | |
initial attached comment detection
Diffstat (limited to 'crates/typst-syntax')
| -rw-r--r-- | crates/typst-syntax/src/ast.rs | 13 | ||||
| -rw-r--r-- | crates/typst-syntax/src/node.rs | 42 |
2 files changed, 52 insertions, 3 deletions
diff --git a/crates/typst-syntax/src/ast.rs b/crates/typst-syntax/src/ast.rs index 1cd9cd42..85c4ca47 100644 --- a/crates/typst-syntax/src/ast.rs +++ b/crates/typst-syntax/src/ast.rs @@ -80,6 +80,19 @@ impl<'a> Markup<'a> { } } +node! { + /// A comment: `// something`. + LineComment +} + +impl<'a> LineComment<'a> { + /// The comment's contents, excluding the initial '//' marker. + pub fn content(self) -> &'a str { + let text = self.0.text(); + text.strip_prefix("//").unwrap_or(text) + } +} + /// An expression in markup, math or code. #[derive(Debug, Copy, Clone, Hash)] pub enum Expr<'a> { diff --git a/crates/typst-syntax/src/node.rs b/crates/typst-syntax/src/node.rs index bc378e66..08cb346c 100644 --- a/crates/typst-syntax/src/node.rs +++ b/crates/typst-syntax/src/node.rs @@ -773,13 +773,17 @@ impl<'a> LinkedNode<'a> { self.parent.as_deref() } - /// Get the first previous non-trivia sibling node. - pub fn prev_sibling(&self) -> Option<Self> { + fn prev_sibling_inner(&self) -> Option<Self> { let parent = self.parent()?; let index = self.index.checked_sub(1)?; let node = parent.node.children().nth(index)?; let offset = self.offset - node.len(); - let prev = Self { node, parent: self.parent.clone(), index, offset }; + Some(Self { node, parent: self.parent.clone(), index, offset }) + } + + /// Get the first previous non-trivia sibling node. + pub fn prev_sibling(&self) -> Option<Self> { + let prev = self.prev_sibling_inner()?; if prev.kind().is_trivia() { prev.prev_sibling() } else { @@ -787,6 +791,38 @@ impl<'a> LinkedNode<'a> { } } + /// Get the first sibling comment node at the line above this node. + /// This is done by moving backwards until the rightmost newline, and then + /// checking for comments before the previous newline. + pub fn prev_attached_comment(&self) -> Option<Self> { + if self.kind() == SyntaxKind::Parbreak + || self.kind() == SyntaxKind::Space && self.text().contains('\n') + { + // We hit a newline, so let's check for comments before the next + // newline. + let mut sibling_before_newline = self.prev_sibling_inner()?; + while sibling_before_newline.kind().is_trivia() + && !matches!( + sibling_before_newline.kind(), + SyntaxKind::Space | SyntaxKind::LineComment | SyntaxKind::Parbreak + ) + { + sibling_before_newline = sibling_before_newline.prev_sibling_inner()?; + } + if sibling_before_newline.kind() == SyntaxKind::LineComment { + // Found a comment on the previous line + Some(sibling_before_newline) + } else { + // No comments on the previous line + None + } + } else { + self.prev_sibling_inner() + .as_ref() + .and_then(Self::prev_attached_comment) + } + } + /// Get the next non-trivia sibling node. pub fn next_sibling(&self) -> Option<Self> { let parent = self.parent()?; |
