Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/syntax/src/syntax_editor/edit_algo.rs')
| -rw-r--r-- | crates/syntax/src/syntax_editor/edit_algo.rs | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/crates/syntax/src/syntax_editor/edit_algo.rs b/crates/syntax/src/syntax_editor/edit_algo.rs index 01c1f0d49b..e697d97061 100644 --- a/crates/syntax/src/syntax_editor/edit_algo.rs +++ b/crates/syntax/src/syntax_editor/edit_algo.rs @@ -150,6 +150,35 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { // Map change targets to the correct syntax nodes let tree_mutator = TreeMutator::new(&root); let mut changed_elements = vec![]; + let mut changed_elements_set = rustc_hash::FxHashSet::default(); + let mut deduplicate_node = |node_or_token: &mut SyntaxElement| { + let node; + let node = match node_or_token { + SyntaxElement::Token(token) => match token.parent() { + None => return, + Some(parent) => { + node = parent; + &node + } + }, + SyntaxElement::Node(node) => node, + }; + if changed_elements_set.contains(node) { + let new_node = node.clone_subtree().clone_for_update(); + match node_or_token { + SyntaxElement::Node(node) => *node = new_node, + SyntaxElement::Token(token) => { + *token = new_node + .children_with_tokens() + .filter_map(SyntaxElement::into_token) + .find(|it| it.kind() == token.kind() && it.text() == token.text()) + .unwrap(); + } + } + } else { + changed_elements_set.insert(node.clone()); + } + }; for index in independent_changes { match &mut changes[index as usize] { @@ -180,6 +209,18 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { } } + match &mut changes[index as usize] { + Change::Insert(_, element) | Change::Replace(_, Some(element)) => { + deduplicate_node(element); + } + Change::InsertAll(_, elements) + | Change::ReplaceWithMany(_, elements) + | Change::ReplaceAll(_, elements) => { + elements.iter_mut().for_each(&mut deduplicate_node); + } + Change::Replace(_, None) => (), + } + // Collect changed elements match &changes[index as usize] { Change::Insert(_, element) => changed_elements.push(element.clone()), |