1use thiserror::Error;
2
3use crate::prelude::*;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum NodeTarget {
7 CstNodeId(CstNodeId),
8 CommandNodeId(CommandNodeId),
9}
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub struct CommandNodeId(usize);
13
14impl From<CommandNodeId> for NodeTarget {
15 fn from(value: CommandNodeId) -> Self {
16 NodeTarget::CommandNodeId(value)
17 }
18}
19
20impl From<CstNodeId> for NodeTarget {
21 fn from(value: CstNodeId) -> Self {
22 NodeTarget::CstNodeId(value)
23 }
24}
25
26#[derive(Debug, PartialEq, Eq, Clone, Default)]
27pub struct CstCommands {
28 insert_num: usize,
29 commands: Vec<Command>,
30}
31
32impl CstCommands {
33 pub fn delete_node(&mut self, id: impl Into<NodeTarget>) {
34 self.commands.push(Command::DeleteNode(id.into()));
35 }
36
37 pub fn delete_recursive(&mut self, id: impl Into<NodeTarget>) {
38 self.commands.push(Command::DeleteRecursive(id.into()));
39 }
40
41 #[must_use]
42 pub fn insert_dynamic_terminal(
43 &mut self,
44 kind: TerminalKind,
45 data: impl Into<String>,
46 ) -> CommandNodeId {
47 self.commands.push(Command::InsertDynamicTerminal {
48 kind,
49 data: data.into(),
50 });
51 let id = CommandNodeId(self.insert_num);
52 self.insert_num += 1;
53 id
54 }
55
56 #[must_use]
57 pub fn insert_node(&mut self, data: CstNode) -> CommandNodeId {
58 self.commands.push(Command::Insert { data });
59 let id = CommandNodeId(self.insert_num);
60 self.insert_num += 1;
61 id
62 }
63
64 pub fn update_node(&mut self, id: impl Into<NodeTarget>, data: CstNode) {
65 self.commands.push(Command::Update {
66 id: id.into(),
67 data,
68 });
69 }
70
71 pub fn update_children(
72 &mut self,
73 id: impl Into<NodeTarget>,
74 children: impl IntoIterator<Item = impl Into<NodeTarget>>,
75 ) {
76 self.commands.push(Command::UpdateChildren {
77 id: id.into(),
78 children: children.into_iter().map(|c| c.into()).collect(),
79 });
80 }
81
82 pub fn add_nodes_before(
84 &mut self,
85 id: impl Into<NodeTarget>,
86 before: impl Into<NodeTarget>,
87 data: impl IntoIterator<Item = impl Into<NodeTarget>>,
88 ) {
89 self.commands.push(Command::AddNodesBefore {
90 id: id.into(),
91 before: before.into(),
92 data: data.into_iter().map(|d| d.into()).collect(),
93 });
94 }
95
96 pub fn add_nodes_after(
98 &mut self,
99 id: impl Into<NodeTarget>,
100 after: impl Into<NodeTarget>,
101 data: impl IntoIterator<Item = impl Into<NodeTarget>>,
102 ) {
103 self.commands.push(Command::AddNodesAfter {
104 id: id.into(),
105 after: after.into(),
106 data: data.into_iter().map(|d| d.into()).collect(),
107 });
108 }
109}
110
111#[derive(Debug, Error)]
112pub enum CommandApplyError {
113 #[error("before node not found")]
114 BeforeNodeNotFound { id: CstNodeId, before: CstNodeId },
115}
116
117impl CstCommands {
118 pub fn apply_to(self, tree: &mut Cst) -> Result<(), CommandApplyError> {
119 let mut inserted = vec![];
120 let to_id = |inserted: &[CstNodeId], target: NodeTarget| -> CstNodeId {
121 match target {
122 NodeTarget::CstNodeId(id) => id,
123 NodeTarget::CommandNodeId(id) => inserted[id.0],
124 }
125 };
126 for command in self.commands.into_iter() {
127 match command {
128 Command::Insert { data } => {
129 let id = tree.add_node(data);
130 inserted.push(id);
131 }
132 Command::DeleteNode(node_target) => {
133 tree.remove_node(to_id(&inserted, node_target));
134 }
135 Command::DeleteRecursive(node_target) => {
136 tree.remove_node(to_id(&inserted, node_target));
137 }
138 Command::ChangeParent { id, parent } => {
139 tree.change_parent(to_id(&inserted, id), to_id(&inserted, parent));
140 }
141 Command::Update { id, data } => {
142 tree.update_node(to_id(&inserted, id), data);
143 }
144 Command::UpdateChildren { id, children } => {
145 tree.update_children(
146 to_id(&inserted, id),
147 children.into_iter().map(|c| to_id(&inserted, c)),
148 );
149 }
150 Command::AddNodesBefore { id, before, data } => {
151 let mut children = tree.children(to_id(&inserted, id)).collect::<Vec<_>>();
152 let Some(before_index) =
153 children.iter().position(|c| to_id(&inserted, before) == *c)
154 else {
155 return Err(CommandApplyError::BeforeNodeNotFound {
156 id: to_id(&inserted, id),
157 before: to_id(&inserted, before),
158 });
159 };
160 children.splice(
161 before_index..before_index,
162 data.into_iter().map(|d| to_id(&inserted, d)),
163 );
164 tree.update_children(to_id(&inserted, id), children);
165 }
166 Command::AddNodesAfter { id, after, data } => {
167 let mut children = tree.children(to_id(&inserted, id)).collect::<Vec<_>>();
168 let Some(after_index) =
169 children.iter().position(|c| to_id(&inserted, after) == *c)
170 else {
171 return Err(CommandApplyError::BeforeNodeNotFound {
172 id: to_id(&inserted, id),
173 before: to_id(&inserted, after),
174 });
175 };
176 children.splice(
177 (after_index + 1)..(after_index + 1),
178 data.into_iter().map(|d| to_id(&inserted, d)),
179 );
180 tree.update_children(to_id(&inserted, id), children);
181 }
182 Command::InsertDynamicTerminal { kind, data } => {
183 let token_id = tree.insert_dynamic_terminal(data);
184 let node_id = tree.add_node(CstNode::Terminal {
185 kind,
186 data: TerminalData::Dynamic(token_id),
187 });
188 inserted.push(node_id);
189 }
190 }
191 }
192 Ok(())
193 }
194}
195
196#[derive(Debug, Clone, PartialEq, Eq)]
197pub enum Command {
198 DeleteNode(NodeTarget),
199 DeleteRecursive(NodeTarget),
200 ChangeParent {
201 id: NodeTarget,
202 parent: NodeTarget,
203 },
204 Insert {
205 data: CstNode,
206 },
207 Update {
208 id: NodeTarget,
209 data: CstNode,
210 },
211 UpdateChildren {
212 id: NodeTarget,
213 children: Vec<NodeTarget>,
214 },
215 AddNodesBefore {
216 id: NodeTarget,
217 before: NodeTarget,
218 data: Vec<NodeTarget>,
219 },
220 AddNodesAfter {
221 id: NodeTarget,
222 after: NodeTarget,
223 data: Vec<NodeTarget>,
224 },
225 InsertDynamicTerminal {
226 kind: TerminalKind,
227 data: String,
228 },
229}
230
231#[cfg(test)]
232mod tests {
233 use super::*;
234 use crate::node_kind::{NonTerminalKind, TerminalKind};
235 use crate::tree::{
236 ConcreteSyntaxTree, CstNodeData, CstNodeId, DynamicTokenId, NonTerminalData,
237 };
238 fn create_test_tree() -> ConcreteSyntaxTree<TerminalKind, NonTerminalKind> {
239 let root_data =
240 CstNodeData::new_non_terminal(NonTerminalKind::Root, NonTerminalData::Dynamic);
241 ConcreteSyntaxTree::new(root_data)
242 }
243
244 #[test]
245 fn test_delete_node() {
246 let mut tree = create_test_tree();
247 let root = tree.root();
248
249 let node_data =
251 CstNodeData::new_non_terminal(NonTerminalKind::Root, NonTerminalData::Dynamic);
252 let child = tree.add_node_with_parent(node_data, root);
253
254 let mut commands = CstCommands::default();
255 commands.delete_node(child);
256
257 commands.apply_to(&mut tree).unwrap();
258
259 assert!(tree.has_no_children(root));
260 }
261
262 #[test]
263 fn test_delete_recursive() {
264 let mut tree = create_test_tree();
265 let root = tree.root();
266
267 let node_data =
269 CstNodeData::new_non_terminal(NonTerminalKind::Root, NonTerminalData::Dynamic);
270 let child = tree.add_node_with_parent(node_data, root);
271
272 let grandchild_data =
274 CstNodeData::new_non_terminal(NonTerminalKind::Eure, NonTerminalData::Dynamic);
275 let _grandchild = tree.add_node_with_parent(grandchild_data, child);
276
277 let mut commands = CstCommands::default();
278 commands.delete_node(child);
279
280 commands.apply_to(&mut tree).unwrap();
281
282 let root_children: Vec<_> = tree.children(root).collect();
283 assert!(!root_children.contains(&child));
284
285 let mut tree = create_test_tree();
286 let root = tree.root();
287
288 let node_data =
290 CstNodeData::new_non_terminal(NonTerminalKind::Root, NonTerminalData::Dynamic);
291 let child = tree.add_node_with_parent(node_data, root);
292
293 let mut commands = CstCommands::default();
294 commands.delete_recursive(child);
295
296 commands.apply_to(&mut tree).unwrap();
297
298 let root_children: Vec<_> = tree.children(root).collect();
299 assert!(!root_children.contains(&child));
300 }
301
302 #[test]
303 fn test_change_parent() {
304 let mut tree = create_test_tree();
305 let root = tree.root();
306
307 let node_data1 =
308 CstNodeData::new_non_terminal(NonTerminalKind::Root, NonTerminalData::Dynamic);
309 let child1 = tree.add_node_with_parent(node_data1, root);
310
311 let node_data2 =
312 CstNodeData::new_non_terminal(NonTerminalKind::Eure, NonTerminalData::Dynamic);
313 let child2 = tree.add_node_with_parent(node_data2, root);
314
315 let grandchild_data =
316 CstNodeData::new_non_terminal(NonTerminalKind::Root, NonTerminalData::Dynamic);
317 let grandchild = tree.add_node_with_parent(grandchild_data, child1);
318
319 let mut commands = CstCommands::default();
320 commands.commands.push(Command::ChangeParent {
321 id: grandchild.into(),
322 parent: child2.into(),
323 });
324
325 commands.apply_to(&mut tree).unwrap();
326
327 let child2_children: Vec<_> = tree.children(child2).collect();
328 assert!(child2_children.contains(&grandchild));
329 }
330
331 #[test]
332 fn test_insert() {
333 let mut tree = create_test_tree();
334 let root = tree.root();
335
336 let node_data =
337 CstNodeData::new_non_terminal(NonTerminalKind::Root, NonTerminalData::Dynamic);
338
339 let mut commands = CstCommands::default();
340 let node = commands.insert_node(node_data);
341 commands.update_children(root, vec![node]);
342
343 commands.apply_to(&mut tree).unwrap();
344
345 let children: Vec<_> = tree.children(root).collect();
346 assert_eq!(children.len(), 1);
347
348 let child_data = tree.node_data(children[0]).unwrap();
349 assert!(matches!(
350 child_data,
351 CstNodeData::NonTerminal {
352 kind: NonTerminalKind::Root,
353 ..
354 }
355 ));
356 }
357
358 #[test]
359 fn test_update() {
360 let mut tree = create_test_tree();
361 let root = tree.root();
362
363 let node_data =
365 CstNodeData::new_non_terminal(NonTerminalKind::Root, NonTerminalData::Dynamic);
366 let child = tree.add_node_with_parent(node_data, root);
367
368 let new_data =
369 CstNodeData::new_non_terminal(NonTerminalKind::Eure, NonTerminalData::Dynamic);
370
371 let mut commands = CstCommands::default();
372 commands.update_node(child, new_data);
373
374 commands.apply_to(&mut tree).unwrap();
375
376 let updated_data = tree.node_data(child).unwrap();
377 assert!(matches!(
378 updated_data,
379 CstNodeData::NonTerminal {
380 kind: NonTerminalKind::Eure,
381 ..
382 }
383 ));
384 }
385
386 #[test]
387 fn test_add_nodes_before() {
388 let mut tree = create_test_tree();
389 let root = tree.root();
390
391 let node_data1 =
392 CstNodeData::new_non_terminal(NonTerminalKind::Root, NonTerminalData::Dynamic);
393 let child1 = tree.add_node_with_parent(node_data1, root);
394
395 let node_data2 =
396 CstNodeData::new_non_terminal(NonTerminalKind::Eure, NonTerminalData::Dynamic);
397 let child2 = tree.add_node_with_parent(node_data2, root);
398
399 let node_data3 =
400 CstNodeData::new_non_terminal(NonTerminalKind::Section, NonTerminalData::Dynamic);
401 let child3 = tree.add_node(node_data3);
402
403 let mut commands = CstCommands::default();
404 commands.add_nodes_before(root, child2, vec![child3]);
405
406 commands.apply_to(&mut tree).unwrap();
407
408 let children: Vec<_> = tree.children(root).collect();
409
410 assert_eq!(children.len(), 3);
411
412 assert!(children.contains(&child1));
413 assert!(children.contains(&child2));
414 assert!(children.contains(&child3));
415
416 assert!(tree.children(root).any(|id| id == child3));
417 }
418
419 #[test]
420 fn test_insert_dynamic_terminal() {
421 let mut tree = create_test_tree();
422 let root = tree.root();
423
424 let mut commands = CstCommands::default();
425 let token_id = commands.insert_dynamic_terminal(TerminalKind::Text, "test_text");
426 commands.update_children(root, vec![token_id]);
427
428 commands.apply_to(&mut tree).unwrap();
429
430 assert_eq!(tree.dynamic_token(DynamicTokenId(0)), Some("test_text"));
431 }
432
433 #[test]
434 fn test_insert_dynamic_terminal_with_add_nodes_before() {
435 let mut tree = create_test_tree();
436 let root = tree.root();
437
438 let node_data1 =
440 CstNodeData::new_non_terminal(NonTerminalKind::Root, NonTerminalData::Dynamic);
441 let child1 = tree.add_node_with_parent(node_data1, root);
442
443 let node_data2 =
444 CstNodeData::new_non_terminal(NonTerminalKind::Eure, NonTerminalData::Dynamic);
445 let child2 = tree.add_node_with_parent(node_data2, root);
446
447 let mut commands = CstCommands::default();
449 let ws_node_id = commands.insert_dynamic_terminal(TerminalKind::Whitespace, " ");
450 commands.add_nodes_before(root, child2, vec![ws_node_id]);
451
452 commands.apply_to(&mut tree).unwrap();
453
454 let children: Vec<_> = tree.children(root).collect();
455 assert_eq!(children.len(), 3);
456
457 let child1_pos = children.iter().position(|&id| id == child1).unwrap();
459 let child2_pos = children.iter().position(|&id| id == child2).unwrap();
460
461 assert!(child1_pos < child2_pos);
463
464 let ws_node = children
466 .iter()
467 .find(|&&id| id != child1 && id != child2)
468 .unwrap();
469 let ws_data = tree.node_data(*ws_node).unwrap();
470
471 assert!(matches!(
472 ws_data,
473 CstNodeData::Terminal {
474 kind: TerminalKind::Whitespace,
475 data: TerminalData::Dynamic(_),
476 }
477 ));
478
479 if let CstNodeData::Terminal {
481 data: TerminalData::Dynamic(token_id),
482 ..
483 } = ws_data
484 {
485 assert_eq!(tree.dynamic_token(token_id), Some(" "));
486 }
487 }
488
489 #[test]
490 fn test_commands_with_errors() {
491 let mut tree = create_test_tree();
492 let root = tree.root();
493
494 let invalid_node = CstNodeId(999);
495
496 let mut commands = CstCommands::default();
497 commands.delete_node(invalid_node);
498
499 assert!(commands.apply_to(&mut tree).is_ok());
500
501 let mut commands = CstCommands::default();
502 let node_data =
503 CstNodeData::new_non_terminal(NonTerminalKind::Root, NonTerminalData::Dynamic);
504 let child = tree.add_node(node_data);
505 commands.add_nodes_before(root, invalid_node, vec![child]);
506
507 let result = commands.apply_to(&mut tree);
508 assert!(result.is_err());
509 }
510}