Unnamed repository; edit this file 'description' to name the repository.
| -rw-r--r-- | crates/syntax/src/syntax_editor.rs | 56 | ||||
| -rw-r--r-- | crates/syntax/src/syntax_editor/edit_algo.rs | 5 |
2 files changed, 58 insertions, 3 deletions
diff --git a/crates/syntax/src/syntax_editor.rs b/crates/syntax/src/syntax_editor.rs index edd063ffd4..704240e9ad 100644 --- a/crates/syntax/src/syntax_editor.rs +++ b/crates/syntax/src/syntax_editor.rs @@ -702,6 +702,62 @@ mod tests { } #[test] + fn test_dependent_change_prefers_nearest_changed_ancestor() { + let root = make::block_expr( + [], + Some( + make::block_expr( + [make::let_stmt( + make::ext::simple_ident_pat(make::name("second")).into(), + None, + Some(make::expr_literal("2").into()), + ) + .into()], + None, + ) + .into(), + ), + ); + + let (editor, root) = SyntaxEditor::with_ast_node(&root); + let make = editor.make(); + + let inner_block = + root.syntax().descendants().flat_map(ast::BlockExpr::cast).nth(1).unwrap(); + + let outer_replacement = make.block_expr([], Some(ast::Expr::BlockExpr(root.clone()))); + let inner_replacement = + make.block_expr([], Some(ast::Expr::BlockExpr(inner_block.clone()))); + + let first_let = make.let_stmt( + make::ext::simple_ident_pat(make::name("first")).into(), + None, + Some(make::expr_literal("1").into()), + ); + + editor.insert( + Position::first_child_of(inner_block.stmt_list().unwrap().syntax()), + first_let.syntax(), + ); + editor.replace(inner_block.syntax(), inner_replacement.syntax()); + editor.replace(root.syntax(), outer_replacement.syntax()); + + let edit = editor.finish(); + + let expect = expect![[r#" + { + { + { + let first = 1;{ + let second = 2; + } + } + } + }"#]]; + expect.assert_eq(&edit.new_root.to_string()); + } + + #[test] fn test_replace_root_with_dependent() { let root = make::block_expr( [make::let_stmt( diff --git a/crates/syntax/src/syntax_editor/edit_algo.rs b/crates/syntax/src/syntax_editor/edit_algo.rs index 27ea03ec09..36f50e3918 100644 --- a/crates/syntax/src/syntax_editor/edit_algo.rs +++ b/crates/syntax/src/syntax_editor/edit_algo.rs @@ -111,8 +111,7 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { // Check if this change is dependent on another change (i.e. it's contained within another range) if let Some(index) = changed_ancestors .iter() - .rev() - .position(|ancestor| ancestor.affected_range().contains_range(change.target_range())) + .rposition(|ancestor| ancestor.affected_range().contains_range(change.target_range())) { // Pop off any ancestors that aren't applicable changed_ancestors.drain((index + 1)..); @@ -284,7 +283,7 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { } } - for DependentChange { parent, child } in dependent_changes.into_iter() { + for DependentChange { parent, child } in dependent_changes.into_iter().rev() { let (input_ancestor, output_ancestor) = match &changes[parent as usize] { // No change will depend on an insert since changes can only depend on nodes in the root tree Change::Insert(_, _) | Change::InsertAll(_, _) => unreachable!(), |