tree_sitter_cli/fuzz/
scope_sequence.rs1use tree_sitter::{Point, Range, Tree};
2
3#[derive(Debug)]
4pub struct ScopeSequence(Vec<ScopeStack>);
5
6type ScopeStack = Vec<&'static str>;
7
8impl ScopeSequence {
9 #[must_use]
10 pub fn new(tree: &Tree) -> Self {
11 let mut result = Self(Vec::new());
12 let mut scope_stack = Vec::new();
13
14 let mut cursor = tree.walk();
15 let mut visited_children = false;
16 loop {
17 let node = cursor.node();
18 for _ in result.0.len()..node.start_byte() {
19 result.0.push(scope_stack.clone());
20 }
21 if visited_children {
22 for _ in result.0.len()..node.end_byte() {
23 result.0.push(scope_stack.clone());
24 }
25 scope_stack.pop();
26 if cursor.goto_next_sibling() {
27 visited_children = false;
28 } else if !cursor.goto_parent() {
29 break;
30 }
31 } else {
32 scope_stack.push(cursor.node().kind());
33 if !cursor.goto_first_child() {
34 visited_children = true;
35 }
36 }
37 }
38
39 result
40 }
41
42 pub fn check_changes(
43 &self,
44 other: &Self,
45 text: &[u8],
46 known_changed_ranges: &[Range],
47 ) -> Result<(), String> {
48 let mut position = Point { row: 0, column: 0 };
49 for i in 0..(self.0.len().max(other.0.len())) {
50 let stack = &self.0.get(i);
51 let other_stack = &other.0.get(i);
52 if *stack != *other_stack && ![b'\r', b'\n'].contains(&text[i]) {
53 let containing_range = known_changed_ranges
54 .iter()
55 .find(|range| range.start_point <= position && position < range.end_point);
56 if containing_range.is_none() {
57 let line = &text[(i - position.column)..]
58 .split(|c| *c == b'\n')
59 .next()
60 .unwrap();
61 return Err(format!(
62 concat!(
63 "Position: {}\n",
64 "Byte offset: {}\n",
65 "Line: {}\n",
66 "{}^\n",
67 "Old scopes: {:?}\n",
68 "New scopes: {:?}\n",
69 "Invalidated ranges: {:?}",
70 ),
71 position,
72 i,
73 String::from_utf8_lossy(line),
74 String::from(" ").repeat(position.column + "Line: ".len()),
75 stack,
76 other_stack,
77 known_changed_ranges,
78 ));
79 }
80 }
81
82 if text[i] == b'\n' {
83 position.row += 1;
84 position.column = 0;
85 } else {
86 position.column += 1;
87 }
88 }
89 Ok(())
90 }
91}