Skip to content

Commit

Permalink
different is_missing implementation + tree debugging function
Browse files Browse the repository at this point in the history
  • Loading branch information
SpontanCombust committed Jan 18, 2024
1 parent 7e69f7d commit 83a37bf
Showing 1 changed file with 74 additions and 1 deletion.
75 changes: 74 additions & 1 deletion crates/core/src/syntax_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,13 @@ impl<'script, T> SyntaxNode<'script, T> {
}

pub fn is_missing(&self) -> bool {
self.tree_node.is_missing()
// More reliable way than tree_sitter::Node::is_missing().
// That's because in the node tree only leaves can be marked as missing.
// TS is also a bit annoying when it comes to those leave nodes.
// Named nodes can never be leaves, they always contain an unnamed node inside them,
// even if this node corresponds to a single token.
let range = self.range();
range.start == range.end
}

/// Returns text that this node spans in the text document
Expand All @@ -135,6 +141,73 @@ impl<'script, T> SyntaxNode<'script, T> {
Some(doc.text_at(self.range()))
}
}


/// Returns tree-sitter's node structure in a form of XML.
/// Use for debugging purposes.
pub fn debug_ts_tree(&self, doc: &ScriptDocument) -> String {
let mut buf = String::new();
let mut cursor = self.tree_node.walk();

let mut needs_newline = false;
let mut indent_level = 0;
let mut did_visit_children = false;
let mut tags: Vec<&str> = Vec::new();

loop {
let node = cursor.node();
let is_named = node.is_named();
if did_visit_children {
if is_named {
let tag = tags.pop();
buf += &format!("</{}>\n", tag.expect("there is a tag"));
needs_newline = true;
}
if cursor.goto_next_sibling() {
did_visit_children = false;
} else if cursor.goto_parent() {
did_visit_children = true;
indent_level -= 1;
} else {
break;
}
} else {
if is_named {
if needs_newline {
buf += &format!("\n");
}
for _ in 0..indent_level {
buf += &format!(" ");
}
buf += &format!("<{}", node.kind());
if let Some(field_name) = cursor.field_name() {
buf += &format!(" type=\"{}\"", field_name);
}
buf += &format!(">");
tags.push(node.kind());
needs_newline = true;
}
if cursor.goto_first_child() {
did_visit_children = false;
indent_level += 1;
} else {
let node_range = node.range();
let lsp_range = Range::new(
Position::new(node_range.start_point.row as u32, node_range.start_point.column as u32),
Position::new(node_range.end_point.row as u32, node_range.end_point.column as u32)
);

buf += &doc.text_at(lsp_range);
did_visit_children = true;
}
if node.is_missing() {
buf += &format!("MISSING");
}
}
}

buf
}
}

impl<T> PartialEq for SyntaxNode<'_, T> {
Expand Down

0 comments on commit 83a37bf

Please sign in to comment.