syntax/syntax_editor/
edit_algo.rs

1//! Implementation of applying changes to a syntax tree.
2
3use std::{
4    cmp::Ordering,
5    collections::VecDeque,
6    ops::{Range, RangeInclusive},
7};
8
9use rowan::TextRange;
10use rustc_hash::FxHashMap;
11use stdx::format_to;
12
13use crate::{
14    SyntaxElement, SyntaxNode, SyntaxNodePtr,
15    syntax_editor::{Change, ChangeKind, PositionRepr, mapping::MissingMapping},
16};
17
18use super::{SyntaxEdit, SyntaxEditor};
19
20pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit {
21    // Algorithm overview:
22    //
23    // - Sort changes by (range, type)
24    //   - Ensures that parent edits are before child edits
25    //   - Ensures that inserts will be guaranteed to be inserted at the right range
26    // - Validate changes
27    //   - Checking for invalid changes is easy since the changes will be sorted by range
28    // - Fixup change targets
29    //   - standalone change? map to original syntax tree
30    //   - dependent change?
31    //     - try to map to parent change (either independent or another dependent)
32    //     - note: need to keep track of a parent change stack, since a change can be a parent of multiple changes
33    // - Apply changes
34    //   - find changes to apply to real tree by applying nested changes first
35    //   - changed nodes become part of the changed node set (useful for the formatter to only change those parts)
36    // - Propagate annotations
37
38    let SyntaxEditor { root, mut changes, mappings, annotations } = editor;
39
40    let mut node_depths = FxHashMap::<SyntaxNode, usize>::default();
41    let mut get_node_depth = |node: SyntaxNode| {
42        *node_depths.entry(node).or_insert_with_key(|node| node.ancestors().count())
43    };
44
45    // Sort changes by range, then depth, then change kind, so that we can:
46    // - ensure that parent edits are ordered before child edits
47    // - ensure that inserts will be guaranteed to be inserted at the right range
48    // - easily check for disjoint replace ranges
49    changes.sort_by(|a, b| {
50        a.target_range()
51            .start()
52            .cmp(&b.target_range().start())
53            .then_with(|| {
54                let a_target = a.target_parent();
55                let b_target = b.target_parent();
56
57                if a_target == b_target {
58                    return Ordering::Equal;
59                }
60
61                get_node_depth(a_target).cmp(&get_node_depth(b_target))
62            })
63            .then(a.change_kind().cmp(&b.change_kind()))
64    });
65
66    let disjoint_replaces_ranges = changes
67        .iter()
68        .zip(changes.iter().skip(1))
69        .filter(|(l, r)| {
70            // We only care about checking for disjoint replace ranges
71            matches!(
72                (l.change_kind(), r.change_kind()),
73                (
74                    ChangeKind::Replace | ChangeKind::ReplaceRange,
75                    ChangeKind::Replace | ChangeKind::ReplaceRange
76                )
77            )
78        })
79        .all(|(l, r)| {
80            get_node_depth(l.target_parent()) != get_node_depth(r.target_parent())
81                || (l.target_range().end() <= r.target_range().start())
82        });
83
84    if !disjoint_replaces_ranges {
85        report_intersecting_changes(&changes, get_node_depth, &root);
86
87        return SyntaxEdit {
88            old_root: root.clone(),
89            new_root: root,
90            annotations: Default::default(),
91            changed_elements: vec![],
92        };
93    }
94
95    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
96    struct DependentChange {
97        parent: u32,
98        child: u32,
99    }
100
101    // Build change tree
102    let mut changed_ancestors: VecDeque<ChangedAncestor> = VecDeque::new();
103    let mut dependent_changes = vec![];
104    let mut independent_changes = vec![];
105    let mut outdated_changes = vec![];
106
107    for (change_index, change) in changes.iter().enumerate() {
108        // Check if this change is dependent on another change (i.e. it's contained within another range)
109        if let Some(index) = changed_ancestors
110            .iter()
111            .rev()
112            .position(|ancestor| ancestor.affected_range().contains_range(change.target_range()))
113        {
114            // Pop off any ancestors that aren't applicable
115            changed_ancestors.drain((index + 1)..);
116
117            // FIXME: Resolve changes that depend on a range of elements
118            let ancestor = &changed_ancestors[index];
119
120            if let Change::Replace(_, None) = changes[ancestor.change_index] {
121                outdated_changes.push(change_index as u32);
122            } else {
123                dependent_changes.push(DependentChange {
124                    parent: ancestor.change_index as u32,
125                    child: change_index as u32,
126                });
127            }
128        } else {
129            // This change is independent of any other change
130
131            // Drain the changed ancestors since we're no longer in a set of dependent changes
132            changed_ancestors.drain(..);
133
134            independent_changes.push(change_index as u32);
135        }
136
137        // Add to changed ancestors, if applicable
138        match change {
139            Change::Replace(SyntaxElement::Node(target), _)
140            | Change::ReplaceWithMany(SyntaxElement::Node(target), _) => {
141                changed_ancestors.push_back(ChangedAncestor::single(target, change_index))
142            }
143            Change::ReplaceAll(range, _) => {
144                changed_ancestors.push_back(ChangedAncestor::multiple(range, change_index))
145            }
146            _ => (),
147        }
148    }
149
150    // Map change targets to the correct syntax nodes
151    let tree_mutator = TreeMutator::new(&root);
152    let mut changed_elements = vec![];
153    let mut changed_elements_set = rustc_hash::FxHashSet::default();
154    let mut deduplicate_node = |node_or_token: &mut SyntaxElement| {
155        let node;
156        let node = match node_or_token {
157            SyntaxElement::Token(token) => match token.parent() {
158                None => return,
159                Some(parent) => {
160                    node = parent;
161                    &node
162                }
163            },
164            SyntaxElement::Node(node) => node,
165        };
166        if changed_elements_set.contains(node) {
167            let new_node = node.clone_subtree().clone_for_update();
168            match node_or_token {
169                SyntaxElement::Node(node) => *node = new_node,
170                SyntaxElement::Token(token) => {
171                    *token = new_node
172                        .children_with_tokens()
173                        .filter_map(SyntaxElement::into_token)
174                        .find(|it| it.kind() == token.kind() && it.text() == token.text())
175                        .unwrap();
176                }
177            }
178        } else {
179            changed_elements_set.insert(node.clone());
180        }
181    };
182
183    for index in independent_changes {
184        match &mut changes[index as usize] {
185            Change::Insert(target, _) | Change::InsertAll(target, _) => {
186                match &mut target.repr {
187                    PositionRepr::FirstChild(parent) => {
188                        *parent = tree_mutator.make_syntax_mut(parent);
189                    }
190                    PositionRepr::After(child) => {
191                        *child = tree_mutator.make_element_mut(child);
192                    }
193                };
194            }
195            Change::Replace(SyntaxElement::Node(target), Some(SyntaxElement::Node(new_target))) => {
196                *target = tree_mutator.make_syntax_mut(target);
197                if new_target.ancestors().any(|node| node == tree_mutator.immutable) {
198                    *new_target = new_target.clone_for_update();
199                }
200            }
201            Change::Replace(target, _) | Change::ReplaceWithMany(target, _) => {
202                *target = tree_mutator.make_element_mut(target);
203            }
204            Change::ReplaceAll(range, _) => {
205                let start = tree_mutator.make_element_mut(range.start());
206                let end = tree_mutator.make_element_mut(range.end());
207
208                *range = start..=end;
209            }
210        }
211
212        match &mut changes[index as usize] {
213            Change::Insert(_, element) | Change::Replace(_, Some(element)) => {
214                deduplicate_node(element);
215            }
216            Change::InsertAll(_, elements)
217            | Change::ReplaceWithMany(_, elements)
218            | Change::ReplaceAll(_, elements) => {
219                elements.iter_mut().for_each(&mut deduplicate_node);
220            }
221            Change::Replace(_, None) => (),
222        }
223
224        // Collect changed elements
225        match &changes[index as usize] {
226            Change::Insert(_, element) => changed_elements.push(element.clone()),
227            Change::InsertAll(_, elements) => changed_elements.extend(elements.iter().cloned()),
228            Change::Replace(_, Some(element)) => changed_elements.push(element.clone()),
229            Change::Replace(_, None) => {}
230            Change::ReplaceWithMany(_, elements) => {
231                changed_elements.extend(elements.iter().cloned())
232            }
233            Change::ReplaceAll(_, elements) => changed_elements.extend(elements.iter().cloned()),
234        }
235    }
236
237    for DependentChange { parent, child } in dependent_changes.into_iter() {
238        let (input_ancestor, output_ancestor) = match &changes[parent as usize] {
239            // No change will depend on an insert since changes can only depend on nodes in the root tree
240            Change::Insert(_, _) | Change::InsertAll(_, _) => unreachable!(),
241            Change::Replace(target, Some(new_target)) => {
242                (to_owning_node(target), to_owning_node(new_target))
243            }
244            Change::Replace(_, None) => {
245                unreachable!("deletions should not generate dependent changes")
246            }
247            Change::ReplaceAll(_, _) | Change::ReplaceWithMany(_, _) => {
248                unimplemented!("cannot resolve changes that depend on replacing many elements")
249            }
250        };
251
252        let upmap_target_node = |target: &SyntaxNode| match mappings.upmap_child(
253            target,
254            &input_ancestor,
255            &output_ancestor,
256        ) {
257            Ok(it) => it,
258            Err(MissingMapping(current)) => unreachable!(
259                "no mappings exist between {current:?} (ancestor of {input_ancestor:?}) and {output_ancestor:?}"
260            ),
261        };
262
263        let upmap_target = |target: &SyntaxElement| match mappings.upmap_child_element(
264            target,
265            &input_ancestor,
266            &output_ancestor,
267        ) {
268            Ok(it) => it,
269            Err(MissingMapping(current)) => unreachable!(
270                "no mappings exist between {current:?} (ancestor of {input_ancestor:?}) and {output_ancestor:?}"
271            ),
272        };
273
274        match &mut changes[child as usize] {
275            Change::Insert(target, _) | Change::InsertAll(target, _) => match &mut target.repr {
276                PositionRepr::FirstChild(parent) => {
277                    *parent = upmap_target_node(parent);
278                }
279                PositionRepr::After(child) => {
280                    *child = upmap_target(child);
281                }
282            },
283            Change::Replace(target, _) | Change::ReplaceWithMany(target, _) => {
284                *target = upmap_target(target);
285            }
286            Change::ReplaceAll(range, _) => {
287                *range = upmap_target(range.start())..=upmap_target(range.end());
288            }
289        }
290    }
291
292    // We reverse here since we pushed to this in ascending order,
293    // and we want to remove elements in descending order
294    for idx in outdated_changes.into_iter().rev() {
295        changes.remove(idx as usize);
296    }
297
298    // Apply changes
299    let mut root = tree_mutator.mutable_clone;
300
301    for change in changes {
302        match change {
303            Change::Insert(position, element) => {
304                let (parent, index) = position.place();
305                parent.splice_children(index..index, vec![element]);
306            }
307            Change::InsertAll(position, elements) => {
308                let (parent, index) = position.place();
309                parent.splice_children(index..index, elements);
310            }
311            Change::Replace(target, None) => {
312                target.detach();
313            }
314            Change::Replace(SyntaxElement::Node(target), Some(new_target)) if target == root => {
315                root = new_target.into_node().expect("root node replacement should be a node");
316            }
317            Change::Replace(target, Some(new_target)) => {
318                let parent = target.parent().unwrap();
319                parent.splice_children(target.index()..target.index() + 1, vec![new_target]);
320            }
321            Change::ReplaceWithMany(target, elements) => {
322                let parent = target.parent().unwrap();
323                parent.splice_children(target.index()..target.index() + 1, elements);
324            }
325            Change::ReplaceAll(range, elements) => {
326                let start = range.start().index();
327                let end = range.end().index();
328                let parent = range.start().parent().unwrap();
329                parent.splice_children(start..end + 1, elements);
330            }
331        }
332    }
333
334    // Propagate annotations
335    let annotations = annotations.into_iter().filter_map(|(element, annotation)| {
336        match mappings.upmap_element(&element, &root) {
337            // Needed to follow the new tree to find the resulting element
338            Some(Ok(mapped)) => Some((mapped, annotation)),
339            // Element did not need to be mapped
340            None => Some((element, annotation)),
341            // Element did not make it to the final tree
342            Some(Err(_)) => None,
343        }
344    });
345
346    let mut annotation_groups = FxHashMap::default();
347
348    for (element, annotation) in annotations {
349        annotation_groups.entry(annotation).or_insert(vec![]).push(element);
350    }
351
352    SyntaxEdit {
353        old_root: tree_mutator.immutable,
354        new_root: root,
355        changed_elements,
356        annotations: annotation_groups,
357    }
358}
359
360fn report_intersecting_changes(
361    changes: &[Change],
362    mut get_node_depth: impl FnMut(rowan::SyntaxNode<crate::RustLanguage>) -> usize,
363    root: &rowan::SyntaxNode<crate::RustLanguage>,
364) {
365    let intersecting_changes = changes
366        .iter()
367        .zip(changes.iter().skip(1))
368        .filter(|(l, r)| {
369            // We only care about checking for disjoint replace ranges.
370            matches!(
371                (l.change_kind(), r.change_kind()),
372                (
373                    ChangeKind::Replace | ChangeKind::ReplaceRange,
374                    ChangeKind::Replace | ChangeKind::ReplaceRange
375                )
376            )
377        })
378        .filter(|(l, r)| {
379            get_node_depth(l.target_parent()) == get_node_depth(r.target_parent())
380                && (l.target_range().end() > r.target_range().start())
381        });
382
383    let mut error_msg = String::from("some replace change ranges intersect!\n");
384
385    let parent_str = root.to_string();
386
387    for (l, r) in intersecting_changes {
388        let mut highlighted_str = parent_str.clone();
389        let l_range = l.target_range();
390        let r_range = r.target_range();
391
392        let i_range = l_range.intersect(r_range).unwrap();
393        let i_str = format!("\x1b[46m{}", &parent_str[i_range]);
394
395        let pre_range: Range<usize> = l_range.start().into()..i_range.start().into();
396        let pre_str = format!("\x1b[44m{}", &parent_str[pre_range]);
397
398        let (highlight_range, highlight_str) = if l_range == r_range {
399            format_to!(error_msg, "\x1b[46mleft change:\x1b[0m  {l:?} {l}\n");
400            format_to!(error_msg, "\x1b[46mequals\x1b[0m\n");
401            format_to!(error_msg, "\x1b[46mright change:\x1b[0m {r:?} {r}\n");
402            let i_highlighted = format!("{i_str}\x1b[0m\x1b[K");
403            let total_range: Range<usize> = i_range.into();
404            (total_range, i_highlighted)
405        } else {
406            format_to!(error_msg, "\x1b[44mleft change:\x1b[0m  {l:?} {l}\n");
407            let range_end = if l_range.contains_range(r_range) {
408                format_to!(error_msg, "\x1b[46mcovers\x1b[0m\n");
409                format_to!(error_msg, "\x1b[46mright change:\x1b[0m {r:?} {r}\n");
410                l_range.end()
411            } else {
412                format_to!(error_msg, "\x1b[46mintersects\x1b[0m\n");
413                format_to!(error_msg, "\x1b[42mright change:\x1b[0m {r:?} {r}\n");
414                r_range.end()
415            };
416
417            let post_range: Range<usize> = i_range.end().into()..range_end.into();
418
419            let post_str = format!("\x1b[42m{}", &parent_str[post_range]);
420            let result = format!("{pre_str}{i_str}{post_str}\x1b[0m\x1b[K");
421            let total_range: Range<usize> = l_range.start().into()..range_end.into();
422            (total_range, result)
423        };
424        highlighted_str.replace_range(highlight_range, &highlight_str);
425
426        format_to!(error_msg, "{highlighted_str}\n");
427    }
428
429    stdx::always!(false, "{}", error_msg);
430}
431
432fn to_owning_node(element: &SyntaxElement) -> SyntaxNode {
433    match element {
434        SyntaxElement::Node(node) => node.clone(),
435        SyntaxElement::Token(token) => token.parent().unwrap(),
436    }
437}
438
439struct ChangedAncestor {
440    kind: ChangedAncestorKind,
441    change_index: usize,
442}
443
444enum ChangedAncestorKind {
445    Single { node: SyntaxNode },
446    Range { _changed_elements: RangeInclusive<SyntaxElement>, _in_parent: SyntaxNode },
447}
448
449impl ChangedAncestor {
450    fn single(node: &SyntaxNode, change_index: usize) -> Self {
451        let kind = ChangedAncestorKind::Single { node: node.clone() };
452
453        Self { kind, change_index }
454    }
455
456    fn multiple(range: &RangeInclusive<SyntaxElement>, change_index: usize) -> Self {
457        Self {
458            kind: ChangedAncestorKind::Range {
459                _changed_elements: range.clone(),
460                _in_parent: range.start().parent().unwrap(),
461            },
462            change_index,
463        }
464    }
465
466    fn affected_range(&self) -> TextRange {
467        match &self.kind {
468            ChangedAncestorKind::Single { node } => node.text_range(),
469            ChangedAncestorKind::Range { _changed_elements: changed_nodes, _in_parent: _ } => {
470                TextRange::new(
471                    changed_nodes.start().text_range().start(),
472                    changed_nodes.end().text_range().end(),
473                )
474            }
475        }
476    }
477}
478
479struct TreeMutator {
480    immutable: SyntaxNode,
481    mutable_clone: SyntaxNode,
482}
483
484impl TreeMutator {
485    fn new(immutable: &SyntaxNode) -> TreeMutator {
486        let immutable = immutable.clone();
487        let mutable_clone = immutable.clone_for_update();
488        TreeMutator { immutable, mutable_clone }
489    }
490
491    fn make_element_mut(&self, element: &SyntaxElement) -> SyntaxElement {
492        match element {
493            SyntaxElement::Node(node) => SyntaxElement::Node(self.make_syntax_mut(node)),
494            SyntaxElement::Token(token) => {
495                let parent = self.make_syntax_mut(&token.parent().unwrap());
496                parent.children_with_tokens().nth(token.index()).unwrap()
497            }
498        }
499    }
500
501    fn make_syntax_mut(&self, node: &SyntaxNode) -> SyntaxNode {
502        let ptr = SyntaxNodePtr::new(node);
503        ptr.to_node(&self.mutable_clone)
504    }
505}