Last active
December 27, 2024 23:40
-
-
Save mgsloan/e1820867f597a31b465b513f2b24431b to your computer and use it in GitHub Desktop.
Find tree sitter node enclosing range, could be used in zed-industries/refactor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Look up a TreeSitter node based on a range from SCIP. | |
pub fn find_node<'a>( | |
start_node: tree_sitter::Node<'a>, | |
range: &Range<tree_sitter::Point>, | |
) -> Result<tree_sitter::Node<'a>> { | |
let mut cursor = start_node.walk(); | |
// Descend to the first leaf that touches the start of the range, and if the range is | |
// non-empty, extends beyond the start. | |
while cursor.goto_first_child_for_point(range.start).is_some() { | |
if !range.is_empty() && cursor.node().end_position() == range.start { | |
cursor.goto_next_sibling(); | |
} | |
} | |
// Ascend to the smallest ancestor that strictly contains the range. | |
loop { | |
let node = cursor.node(); | |
let node_range = node.range(); | |
if node_range.start_point <= range.start && node_range.end_point >= range.end { | |
if node_range.start_point == range.start && node_range.end_point == range.end { | |
return Ok(node); | |
} else { | |
return Err(anyhow::anyhow!( | |
"Mismatch between SCIP index and TreeSitter parse. \ | |
Expected to find node at {}-{}, but containing ancestor is {}-{}.", | |
range.start, | |
range.end, | |
node_range.start_point, | |
node_range.end_point, | |
)); | |
} | |
} | |
if !cursor.goto_parent() { | |
return Err(anyhow::anyhow!( | |
"Mismatch between SCIP index and TreeSitter parse. \ | |
Expected to find node at {}-{}, but ran out of ancestor nodes.", | |
range.start, | |
range.end, | |
)); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment