1- use std:: { collections:: VecDeque , ops:: RangeInclusive } ;
1+ use std:: { cmp :: Ordering , collections:: VecDeque , ops:: RangeInclusive } ;
22
33use rowan:: TextRange ;
44use rustc_hash:: FxHashMap ;
@@ -30,14 +30,29 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit {
3030
3131 let SyntaxEditor { root, mut changes, mappings, annotations } = editor;
3232
33- // Sort changes by range then change kind, so that we can:
33+ let mut node_depths = FxHashMap :: < SyntaxNode , usize > :: default ( ) ;
34+ let mut get_node_depth = |node : SyntaxNode | {
35+ * node_depths. entry ( node) . or_insert_with_key ( |node| node. ancestors ( ) . count ( ) )
36+ } ;
37+
38+ // Sort changes by range, then depth, then change kind, so that we can:
3439 // - ensure that parent edits are ordered before child edits
3540 // - ensure that inserts will be guaranteed to be inserted at the right range
3641 // - easily check for disjoint replace ranges
3742 changes. sort_by ( |a, b| {
3843 a. target_range ( )
3944 . start ( )
4045 . cmp ( & b. target_range ( ) . start ( ) )
46+ . then_with ( || {
47+ let a_target = a. target_parent ( ) ;
48+ let b_target = b. target_parent ( ) ;
49+
50+ if a_target == b_target {
51+ return Ordering :: Equal ;
52+ }
53+
54+ get_node_depth ( a_target) . cmp ( & get_node_depth ( b_target) )
55+ } )
4156 . then ( a. change_kind ( ) . cmp ( & b. change_kind ( ) ) )
4257 } ) ;
4358
@@ -49,8 +64,8 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit {
4964 l. change_kind ( ) == ChangeKind :: Replace && r. change_kind ( ) == ChangeKind :: Replace
5065 } )
5166 . all ( |( l, r) | {
52- ( l. target_parent ( ) != r. target_parent ( )
53- || l. target_range ( ) . intersect ( r. target_range ( ) ) . is_none ( ) )
67+ get_node_depth ( l. target_parent ( ) ) != get_node_depth ( r. target_parent ( ) )
68+ || l. target_range ( ) . intersect ( r. target_range ( ) ) . is_none ( )
5469 } ) ;
5570
5671 if stdx:: never!(
0 commit comments