1
- use std:: { collections:: VecDeque , ops:: RangeInclusive } ;
1
+ use std:: { cmp :: Ordering , collections:: VecDeque , ops:: RangeInclusive } ;
2
2
3
3
use rowan:: TextRange ;
4
4
use rustc_hash:: FxHashMap ;
@@ -30,14 +30,29 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit {
30
30
31
31
let SyntaxEditor { root, mut changes, mappings, annotations } = editor;
32
32
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:
34
39
// - ensure that parent edits are ordered before child edits
35
40
// - ensure that inserts will be guaranteed to be inserted at the right range
36
41
// - easily check for disjoint replace ranges
37
42
changes. sort_by ( |a, b| {
38
43
a. target_range ( )
39
44
. start ( )
40
45
. 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
+ } )
41
56
. then ( a. change_kind ( ) . cmp ( & b. change_kind ( ) ) )
42
57
} ) ;
43
58
@@ -49,8 +64,8 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit {
49
64
l. change_kind ( ) == ChangeKind :: Replace && r. change_kind ( ) == ChangeKind :: Replace
50
65
} )
51
66
. 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 ( )
54
69
} ) ;
55
70
56
71
if stdx:: never!(
0 commit comments