tree_sitter_edit/
print.rs1use std::io;
2use std::io::Write;
3
4use tree_sitter::Tree;
5
6use crate::editor::Editor;
7
8pub fn render(
16 w: &mut impl Write,
17 tree: &Tree,
18 source: &[u8],
19 editor: &impl Editor,
20) -> Result<bool, io::Error> {
21 let mut changed = false;
22 let mut start = 0;
23 for edit in editor.in_order_edits(source, tree) {
24 if edit.position < start {
25 continue;
26 }
27 changed = true;
28 w.write_all(&source[start..edit.position])?;
30 w.write_all(&edit.insert)?;
31 start = edit.position + edit.delete;
32 }
33 w.write_all(&source[start..source.len()])?;
34 Ok(changed)
35}
36
37#[cfg(test)]
38mod tests {
39 use tree_sitter::Node;
40
41 use super::*;
42 use crate::editors::{Delete, Id, Replace};
43 use crate::id::NodeId;
44
45 fn vec_str(v: &[u8]) -> &str {
46 std::str::from_utf8(v).unwrap()
47 }
48
49 fn parse(src: &str) -> Tree {
50 let mut parser = tree_sitter::Parser::new();
51 parser
52 .set_language(&tree_sitter_c::LANGUAGE.into())
53 .expect("Error loading C grammar");
54 parser.parse(src, None).expect("Failed to parse test")
55 }
56
57 fn do_render(tree: &Tree, src: &str, editor: &impl Editor) -> Vec<u8> {
58 let mut v: Vec<u8> = Vec::new();
59 render(&mut v, tree, src.as_bytes(), editor).expect("I/O error on a vector?");
60 v
61 }
62
63 fn parse_then_render(src: &str, editor: &impl Editor) -> Vec<u8> {
64 do_render(&parse(src), src, editor)
65 }
66
67 #[test]
68 fn parse_then_render_nil() {
69 let src = r#""#;
70 let r = parse_then_render(src, &Id {});
71 assert_eq!(src, vec_str(&r));
72 }
73
74 #[test]
75 fn parse_then_render_main_id() {
76 let src = r#"int main(int argc, char *argv[]) { return 0; }"#;
77 let r = parse_then_render(src, &Id::new());
78 assert_eq!(src, vec_str(&r));
79 }
80
81 #[test]
82 fn parse_then_render_main_omit() {
83 let src = r#"int main(int argc, char *argv[]) { return 0; }"#;
84 let tree = parse(src);
85 let editor = Delete::new(NodeId::new(&tree.root_node()));
86 let r = do_render(&tree, src, &editor);
87 assert_eq!("", vec_str(&r));
88 }
89
90 fn find_kind(tree: &Tree, node: &Node<'_>, kind: &str) -> Option<NodeId> {
91 if node.kind() == kind {
92 return Some(NodeId::new(node));
93 }
94 for child in node.children(&mut tree.walk()) {
95 if let Some(n) = find_kind(tree, &child, kind) {
96 return Some(n);
97 }
98 }
99 None
100 }
101
102 #[test]
103 fn parse_then_render_replace_binary_expr() {
104 let src = r#"int main(int argc, char *argv[]) { return 0 + 0; }"#;
105 let tree = parse(src);
106 let binop = find_kind(&tree, &tree.root_node(), "binary_expression").unwrap();
107 let editor = Replace {
108 id: binop,
109 bytes: "1".as_bytes().to_vec(),
110 };
111 let edited = r#"int main(int argc, char *argv[]) { return 1; }"#;
112 let r = do_render(&tree, src, &editor);
113 assert_eq!(edited, vec_str(&r));
114 }
115
116 #[test]
117 fn parse_then_render_replace_binary_expr_bigger() {
118 let src = r#"int main(int argc, char *argv[]) { return 0 + 0; }"#;
119 let tree = parse(src);
120 let binop = find_kind(&tree, &tree.root_node(), "binary_expression").unwrap();
121 let editor = Replace {
122 id: binop,
123 bytes: "100 + 100000".as_bytes().to_vec(),
124 };
125 let edited = r#"int main(int argc, char *argv[]) { return 100 + 100000; }"#;
126 let r = do_render(&tree, src, &editor);
127 assert_eq!(edited, vec_str(&r));
128 }
129}