@@ -22,41 +22,47 @@ impl SyntaxMapping {
22
22
Self :: default ( )
23
23
}
24
24
25
+ /// Like [`SyntaxMapping::upmap_child`] but for syntax elements.
25
26
pub fn upmap_child_element (
26
27
& self ,
27
28
child : & SyntaxElement ,
28
29
input_ancestor : & SyntaxNode ,
29
- output_ancestor : SyntaxNode ,
30
- ) -> SyntaxElement {
30
+ output_ancestor : & SyntaxNode ,
31
+ ) -> Result < SyntaxElement , MissingMapping > {
31
32
match child {
32
33
SyntaxElement :: Node ( node) => {
33
- SyntaxElement :: Node ( self . upmap_child ( node, input_ancestor, output_ancestor) )
34
+ self . upmap_child ( node, input_ancestor, output_ancestor) . map ( SyntaxElement :: Node )
34
35
}
35
36
SyntaxElement :: Token ( token) => {
36
37
let upmap_parent =
37
- self . upmap_child ( & token. parent ( ) . unwrap ( ) , input_ancestor, output_ancestor) ;
38
+ self . upmap_child ( & token. parent ( ) . unwrap ( ) , input_ancestor, output_ancestor) ? ;
38
39
39
40
let element = upmap_parent. children_with_tokens ( ) . nth ( token. index ( ) ) . unwrap ( ) ;
40
41
debug_assert ! (
41
42
element. as_token( ) . is_some_and( |it| it. kind( ) == token. kind( ) ) ,
42
43
"token upmapping mapped to the wrong node ({token:?} -> {element:?})"
43
44
) ;
44
45
45
- element
46
+ Ok ( element)
46
47
}
47
48
}
48
49
}
49
50
51
+ /// Maps a child node of the input ancestor to the corresponding node in
52
+ /// the output ancestor.
50
53
pub fn upmap_child (
51
54
& self ,
52
55
child : & SyntaxNode ,
53
56
input_ancestor : & SyntaxNode ,
54
- output_ancestor : SyntaxNode ,
55
- ) -> SyntaxNode {
56
- debug_assert ! ( child. ancestors( ) . any( |ancestor| & ancestor == input_ancestor) ) ;
57
+ output_ancestor : & SyntaxNode ,
58
+ ) -> Result < SyntaxNode , MissingMapping > {
59
+ debug_assert ! (
60
+ child == input_ancestor
61
+ || child. ancestors( ) . any( |ancestor| & ancestor == input_ancestor)
62
+ ) ;
57
63
58
64
// Build a list mapping up to the first mappable ancestor
59
- let to_first_upmap =
65
+ let to_first_upmap = if child != input_ancestor {
60
66
std:: iter:: successors ( Some ( ( child. index ( ) , child. clone ( ) ) ) , |( _, current) | {
61
67
let parent = current. parent ( ) . unwrap ( ) ;
62
68
@@ -67,32 +73,22 @@ impl SyntaxMapping {
67
73
Some ( ( parent. index ( ) , parent) )
68
74
} )
69
75
. map ( |( i, _) | i)
70
- . collect :: < Vec < _ > > ( ) ;
76
+ . collect :: < Vec < _ > > ( )
77
+ } else {
78
+ vec ! [ ]
79
+ } ;
71
80
72
81
// Progressively up-map the input ancestor until we get to the output ancestor
73
- let to_output_ancestor = if input_ancestor != & output_ancestor {
74
- std:: iter:: successors ( Some ( ( input_ancestor. index ( ) , self . upmap_node ( input_ancestor) . unwrap_or_else ( || input_ancestor. clone ( ) ) ) ) , |( _, current) | {
75
- let Some ( parent) = current. parent ( ) else {
76
- unreachable ! ( "no mappings exist between {current:?} (ancestor of {input_ancestor:?}) and {output_ancestor:?}" )
77
- } ;
78
-
79
- if & parent == & output_ancestor {
80
- return None ;
81
- }
82
-
83
- Some ( ( parent. index ( ) , match self . upmap_node ( & parent) {
84
- Some ( next) => next,
85
- None => parent
86
- } ) )
87
- } ) . map ( |( i, _) | i) . collect :: < Vec < _ > > ( )
82
+ let to_output_ancestor = if input_ancestor != output_ancestor {
83
+ self . upmap_to_ancestor ( input_ancestor, output_ancestor) ?
88
84
} else {
89
85
vec ! [ ]
90
86
} ;
91
87
92
88
let to_map_down =
93
89
to_output_ancestor. into_iter ( ) . rev ( ) . chain ( to_first_upmap. into_iter ( ) . rev ( ) ) ;
94
90
95
- let mut target = output_ancestor;
91
+ let mut target = output_ancestor. clone ( ) ;
96
92
97
93
for index in to_map_down {
98
94
target = target
@@ -104,20 +100,86 @@ impl SyntaxMapping {
104
100
105
101
debug_assert_eq ! ( child. kind( ) , target. kind( ) ) ;
106
102
107
- target
103
+ Ok ( target)
108
104
}
109
105
110
- pub fn upmap_node ( & self , input : & SyntaxNode ) -> Option < SyntaxNode > {
111
- let MappingEntry { parent, child_slot } = self . node_mappings . get ( input) ?;
106
+ fn upmap_to_ancestor (
107
+ & self ,
108
+ input_ancestor : & SyntaxNode ,
109
+ output_ancestor : & SyntaxNode ,
110
+ ) -> Result < Vec < usize > , MissingMapping > {
111
+ eprintln ! ( "mapping ancestor {input_ancestor:#?} to {output_ancestor:#?}" ) ;
112
+ let mut current =
113
+ self . upmap_node_single ( input_ancestor) . unwrap_or_else ( || input_ancestor. clone ( ) ) ;
114
+ let mut upmap_chain = vec ! [ current. index( ) ] ;
115
+
116
+ loop {
117
+ let Some ( parent) = current. parent ( ) else { break } ;
118
+
119
+ if & parent == output_ancestor {
120
+ return Ok ( upmap_chain) ;
121
+ }
112
122
113
- let output = self . entry_parents [ * parent as usize ]
114
- . children_with_tokens ( )
115
- . nth ( * child_slot as usize )
116
- . and_then ( SyntaxElement :: into_node)
117
- . unwrap ( ) ;
123
+ current = match self . upmap_node_single ( & parent) {
124
+ Some ( next) => next,
125
+ None => parent,
126
+ } ;
127
+ upmap_chain. push ( current. index ( ) ) ;
128
+ }
118
129
119
- debug_assert_eq ! ( input. kind( ) , output. kind( ) ) ;
120
- Some ( output)
130
+ Err ( MissingMapping ( current) )
131
+ }
132
+
133
+ pub fn upmap_element (
134
+ & self ,
135
+ input : & SyntaxElement ,
136
+ output_root : & SyntaxNode ,
137
+ ) -> Option < Result < SyntaxElement , MissingMapping > > {
138
+ match input {
139
+ SyntaxElement :: Node ( node) => {
140
+ Some ( self . upmap_node ( node, output_root) ?. map ( SyntaxElement :: Node ) )
141
+ }
142
+ SyntaxElement :: Token ( token) => {
143
+ let upmap_parent = match self . upmap_node ( & token. parent ( ) . unwrap ( ) , output_root) ? {
144
+ Ok ( it) => it,
145
+ Err ( err) => return Some ( Err ( err) ) ,
146
+ } ;
147
+
148
+ let element = upmap_parent. children_with_tokens ( ) . nth ( token. index ( ) ) . unwrap ( ) ;
149
+ debug_assert ! (
150
+ element. as_token( ) . is_some_and( |it| it. kind( ) == token. kind( ) ) ,
151
+ "token upmapping mapped to the wrong node ({token:?} -> {element:?})"
152
+ ) ;
153
+
154
+ Some ( Ok ( element) )
155
+ }
156
+ }
157
+ }
158
+
159
+ pub fn upmap_node (
160
+ & self ,
161
+ input : & SyntaxNode ,
162
+ output_root : & SyntaxNode ,
163
+ ) -> Option < Result < SyntaxNode , MissingMapping > > {
164
+ // Try to follow the mapping tree, if it exists
165
+ let input_mapping = self . upmap_node_single ( input) ;
166
+ let input_ancestor =
167
+ input. ancestors ( ) . find_map ( |ancestor| self . upmap_node_single ( & ancestor) ) ;
168
+
169
+ match ( input_mapping, input_ancestor) {
170
+ ( Some ( input_mapping) , _) => {
171
+ // A mapping exists at the input, follow along the tree
172
+ Some ( self . upmap_child ( & input_mapping, & input_mapping, & output_root) )
173
+ }
174
+ ( None , Some ( input_ancestor) ) => {
175
+ // A mapping exists at an ancestor, follow along the tree
176
+ Some ( self . upmap_child ( input, & input_ancestor, & output_root) )
177
+ }
178
+ ( None , None ) => {
179
+ // No mapping exists at all, is the same position in the final tree
180
+ None
181
+ }
182
+ }
121
183
}
122
184
123
185
pub fn merge ( & mut self , mut other : SyntaxMapping ) {
@@ -130,6 +192,20 @@ impl SyntaxMapping {
130
192
} ) ) ;
131
193
}
132
194
195
+ /// Follows the input one step along the syntax mapping tree
196
+ fn upmap_node_single ( & self , input : & SyntaxNode ) -> Option < SyntaxNode > {
197
+ let MappingEntry { parent, child_slot } = self . node_mappings . get ( input) ?;
198
+
199
+ let output = self . entry_parents [ * parent as usize ]
200
+ . children_with_tokens ( )
201
+ . nth ( * child_slot as usize )
202
+ . and_then ( SyntaxElement :: into_node)
203
+ . unwrap ( ) ;
204
+
205
+ debug_assert_eq ! ( input. kind( ) , output. kind( ) ) ;
206
+ Some ( output)
207
+ }
208
+
133
209
fn add_mapping ( & mut self , syntax_mapping : SyntaxMappingBuilder ) {
134
210
let SyntaxMappingBuilder { parent_node, node_mappings } = syntax_mapping;
135
211
@@ -183,6 +259,9 @@ impl SyntaxMappingBuilder {
183
259
}
184
260
}
185
261
262
+ #[ derive( Debug ) ]
263
+ pub struct MissingMapping ( pub SyntaxNode ) ;
264
+
186
265
#[ derive( Debug , Clone , Copy ) ]
187
266
struct MappingEntry {
188
267
parent : u32 ,
0 commit comments