summaryrefslogtreecommitdiff
path: root/crates/typst-syntax
diff options
context:
space:
mode:
authorPgBiel <9021226+PgBiel@users.noreply.github.com>2024-06-11 14:27:35 -0300
committerPgBiel <9021226+PgBiel@users.noreply.github.com>2024-06-26 12:17:53 -0300
commitfe860f8b6bee5c8fcbc6c762b03a8f42fccb9240 (patch)
tree4d2c04bb8e2a37beeaaecba02469d898ebfafcb5 /crates/typst-syntax
parentf8958961cb70cc77ec36f40bb99504ab9eca88f8 (diff)
initial attached comment detection
Diffstat (limited to 'crates/typst-syntax')
-rw-r--r--crates/typst-syntax/src/ast.rs13
-rw-r--r--crates/typst-syntax/src/node.rs42
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()?;