Unnamed repository; edit this file 'description' to name the repository.
Fix syntax_editor duplicated changed tokens
A4-Tacks 5 months ago
parent b8bbebf · commit d48361b
-rw-r--r--crates/syntax/src/syntax_editor.rs18
-rw-r--r--crates/syntax/src/syntax_editor/edit_algo.rs24
2 files changed, 40 insertions, 2 deletions
diff --git a/crates/syntax/src/syntax_editor.rs b/crates/syntax/src/syntax_editor.rs
index a0ead400cd..5683d891be 100644
--- a/crates/syntax/src/syntax_editor.rs
+++ b/crates/syntax/src/syntax_editor.rs
@@ -655,6 +655,24 @@ mod tests {
}
#[test]
+ fn test_more_times_replace_node_to_mutable_token() {
+ let arg_list =
+ make::arg_list([make::expr_literal("1").into(), make::expr_literal("2").into()]);
+
+ let mut editor = SyntaxEditor::new(arg_list.syntax().clone());
+ let target_expr = make::token(parser::SyntaxKind::UNDERSCORE);
+
+ for arg in arg_list.args() {
+ editor.replace(arg.syntax(), &target_expr);
+ }
+
+ let edit = editor.finish();
+
+ let expect = expect![["(_, _)"]];
+ expect.assert_eq(&edit.new_root.to_string());
+ }
+
+ #[test]
fn test_more_times_replace_node_to_mutable() {
let arg_list =
make::arg_list([make::expr_literal("1").into(), make::expr_literal("2").into()]);
diff --git a/crates/syntax/src/syntax_editor/edit_algo.rs b/crates/syntax/src/syntax_editor/edit_algo.rs
index d54837b9f2..e697d97061 100644
--- a/crates/syntax/src/syntax_editor/edit_algo.rs
+++ b/crates/syntax/src/syntax_editor/edit_algo.rs
@@ -152,9 +152,29 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit {
let mut changed_elements = vec![];
let mut changed_elements_set = rustc_hash::FxHashSet::default();
let mut deduplicate_node = |node_or_token: &mut SyntaxElement| {
- let SyntaxElement::Node(node) = node_or_token else { return };
+ 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) {
- *node = node.clone_subtree().clone_for_update();
+ 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());
}