Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/syntax/src/syntax_editor.rs56
-rw-r--r--crates/syntax/src/syntax_editor/edit_algo.rs5
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!(),