@@ -10,7 +10,7 @@ use syntax::{AstNode, AstPtr, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange,
10
10
11
11
use crate :: {
12
12
db:: { self , ExpandDatabase } ,
13
- map_node_range_up, span_for_offset, MacroFileIdExt ,
13
+ map_node_range_up, map_node_range_up_rooted , span_for_offset, MacroFileIdExt ,
14
14
} ;
15
15
16
16
/// `InFile<T>` stores a value of `T` inside a particular file/syntax tree.
@@ -38,6 +38,9 @@ impl<N: AstIdNode> AstId<N> {
38
38
pub fn to_node ( & self , db : & dyn ExpandDatabase ) -> N {
39
39
self . to_ptr ( db) . to_node ( & db. parse_or_expand ( self . file_id ) )
40
40
}
41
+ pub fn to_range ( & self , db : & dyn ExpandDatabase ) -> TextRange {
42
+ self . to_ptr ( db) . text_range ( )
43
+ }
41
44
pub fn to_in_file_node ( & self , db : & dyn ExpandDatabase ) -> crate :: InFile < N > {
42
45
crate :: InFile :: new ( self . file_id , self . to_ptr ( db) . to_node ( & db. parse_or_expand ( self . file_id ) ) )
43
46
}
@@ -49,6 +52,9 @@ impl<N: AstIdNode> AstId<N> {
49
52
pub type ErasedAstId = crate :: InFile < ErasedFileAstId > ;
50
53
51
54
impl ErasedAstId {
55
+ pub fn to_range ( & self , db : & dyn ExpandDatabase ) -> TextRange {
56
+ self . to_ptr ( db) . text_range ( )
57
+ }
52
58
pub fn to_ptr ( & self , db : & dyn ExpandDatabase ) -> SyntaxNodePtr {
53
59
db. ast_id_map ( self . file_id ) . get_erased ( self . value )
54
60
}
@@ -173,66 +179,27 @@ impl InFile<&SyntaxNode> {
173
179
///
174
180
/// For attributes and derives, this will point back to the attribute only.
175
181
/// For the entire item use [`InFile::original_file_range_full`].
176
- pub fn original_file_range ( self , db : & dyn db:: ExpandDatabase ) -> FileRange {
177
- match self . file_id . repr ( ) {
178
- HirFileIdRepr :: FileId ( file_id) => FileRange { file_id, range : self . value . text_range ( ) } ,
179
- HirFileIdRepr :: MacroFile ( mac_file) => {
180
- if let Some ( ( res, ctxt) ) =
181
- map_node_range_up ( db, & db. expansion_span_map ( mac_file) , self . value . text_range ( ) )
182
- {
183
- // FIXME: Figure out an API that makes proper use of ctx, this only exists to
184
- // keep pre-token map rewrite behaviour.
185
- if ctxt. is_root ( ) {
186
- return res;
187
- }
188
- }
189
- // Fall back to whole macro call.
190
- let loc = db. lookup_intern_macro_call ( mac_file. macro_call_id ) ;
191
- loc. kind . original_call_range ( db)
192
- }
193
- }
182
+ pub fn original_file_range_rooted ( self , db : & dyn db:: ExpandDatabase ) -> FileRange {
183
+ self . map ( SyntaxNode :: text_range) . original_node_file_range_rooted ( db)
194
184
}
195
185
196
186
/// Falls back to the macro call range if the node cannot be mapped up fully.
197
187
pub fn original_file_range_with_macro_call_body (
198
188
self ,
199
189
db : & dyn db:: ExpandDatabase ,
200
190
) -> FileRange {
201
- match self . file_id . repr ( ) {
202
- HirFileIdRepr :: FileId ( file_id) => FileRange { file_id, range : self . value . text_range ( ) } ,
203
- HirFileIdRepr :: MacroFile ( mac_file) => {
204
- if let Some ( ( res, ctxt) ) =
205
- map_node_range_up ( db, & db. expansion_span_map ( mac_file) , self . value . text_range ( ) )
206
- {
207
- // FIXME: Figure out an API that makes proper use of ctx, this only exists to
208
- // keep pre-token map rewrite behaviour.
209
- if ctxt. is_root ( ) {
210
- return res;
211
- }
212
- }
213
- // Fall back to whole macro call.
214
- let loc = db. lookup_intern_macro_call ( mac_file. macro_call_id ) ;
215
- loc. kind . original_call_range_with_body ( db)
216
- }
217
- }
191
+ self . map ( SyntaxNode :: text_range) . original_node_file_range_with_macro_call_body ( db)
218
192
}
219
193
220
194
/// Attempts to map the syntax node back up its macro calls.
221
195
pub fn original_file_range_opt (
222
196
self ,
223
197
db : & dyn db:: ExpandDatabase ,
224
198
) -> Option < ( FileRange , SyntaxContextId ) > {
225
- match self . file_id . repr ( ) {
226
- HirFileIdRepr :: FileId ( file_id) => {
227
- Some ( ( FileRange { file_id, range : self . value . text_range ( ) } , SyntaxContextId :: ROOT ) )
228
- }
229
- HirFileIdRepr :: MacroFile ( mac_file) => {
230
- map_node_range_up ( db, & db. expansion_span_map ( mac_file) , self . value . text_range ( ) )
231
- }
232
- }
199
+ self . map ( SyntaxNode :: text_range) . original_node_file_range_opt ( db)
233
200
}
234
201
235
- pub fn original_syntax_node (
202
+ pub fn original_syntax_node_rooted (
236
203
self ,
237
204
db : & dyn db:: ExpandDatabase ,
238
205
) -> Option < InRealFile < SyntaxNode > > {
@@ -242,25 +209,21 @@ impl InFile<&SyntaxNode> {
242
209
HirFileIdRepr :: FileId ( file_id) => {
243
210
return Some ( InRealFile { file_id, value : self . value . clone ( ) } )
244
211
}
245
- HirFileIdRepr :: MacroFile ( m) => m,
212
+ HirFileIdRepr :: MacroFile ( m) if m. is_attr_macro ( db) => m,
213
+ _ => return None ,
246
214
} ;
247
- if !file_id. is_attr_macro ( db) {
248
- return None ;
249
- }
250
215
251
- let ( FileRange { file_id, range } , ctx ) =
252
- map_node_range_up ( db, & db. expansion_span_map ( file_id) , self . value . text_range ( ) ) ?;
216
+ let FileRange { file_id, range } =
217
+ map_node_range_up_rooted ( db, & db. expansion_span_map ( file_id) , self . value . text_range ( ) ) ?;
253
218
254
- // FIXME: Figure out an API that makes proper use of ctx, this only exists to
255
- // keep pre-token map rewrite behavior.
256
- if !ctx. is_root ( ) {
257
- return None ;
258
- }
259
-
260
- let anc = db. parse ( file_id) . syntax_node ( ) . covering_element ( range) ;
261
219
let kind = self . value . kind ( ) ;
262
- // FIXME: This heuristic is brittle and with the right macro may select completely unrelated nodes?
263
- let value = anc. ancestors ( ) . find ( |it| it. kind ( ) == kind) ?;
220
+ let value = db
221
+ . parse ( file_id)
222
+ . syntax_node ( )
223
+ . covering_element ( range)
224
+ . ancestors ( )
225
+ . take_while ( |it| it. text_range ( ) == range)
226
+ . find ( |it| it. kind ( ) == kind) ?;
264
227
Some ( InRealFile :: new ( file_id, value) )
265
228
}
266
229
}
@@ -355,8 +318,8 @@ impl InFile<TextRange> {
355
318
match self . file_id . repr ( ) {
356
319
HirFileIdRepr :: FileId ( file_id) => FileRange { file_id, range : self . value } ,
357
320
HirFileIdRepr :: MacroFile ( mac_file) => {
358
- match map_node_range_up ( db, & db. expansion_span_map ( mac_file) , self . value ) {
359
- Some ( ( it , SyntaxContextId :: ROOT ) ) => it,
321
+ match map_node_range_up_rooted ( db, & db. expansion_span_map ( mac_file) , self . value ) {
322
+ Some ( it ) => it,
360
323
_ => {
361
324
let loc = db. lookup_intern_macro_call ( mac_file. macro_call_id ) ;
362
325
loc. kind . original_call_range ( db)
@@ -366,6 +329,24 @@ impl InFile<TextRange> {
366
329
}
367
330
}
368
331
332
+ pub fn original_node_file_range_with_macro_call_body (
333
+ self ,
334
+ db : & dyn db:: ExpandDatabase ,
335
+ ) -> FileRange {
336
+ match self . file_id . repr ( ) {
337
+ HirFileIdRepr :: FileId ( file_id) => FileRange { file_id, range : self . value } ,
338
+ HirFileIdRepr :: MacroFile ( mac_file) => {
339
+ match map_node_range_up_rooted ( db, & db. expansion_span_map ( mac_file) , self . value ) {
340
+ Some ( it) => it,
341
+ _ => {
342
+ let loc = db. lookup_intern_macro_call ( mac_file. macro_call_id ) ;
343
+ loc. kind . original_call_range_with_body ( db)
344
+ }
345
+ }
346
+ }
347
+ }
348
+ }
349
+
369
350
pub fn original_node_file_range_opt (
370
351
self ,
371
352
db : & dyn db:: ExpandDatabase ,
@@ -395,18 +376,12 @@ impl<N: AstNode> InFile<N> {
395
376
return None ;
396
377
}
397
378
398
- let ( FileRange { file_id, range } , ctx ) = map_node_range_up (
379
+ let FileRange { file_id, range } = map_node_range_up_rooted (
399
380
db,
400
381
& db. expansion_span_map ( file_id) ,
401
382
self . value . syntax ( ) . text_range ( ) ,
402
383
) ?;
403
384
404
- // FIXME: Figure out an API that makes proper use of ctx, this only exists to
405
- // keep pre-token map rewrite behaviour.
406
- if !ctx. is_root ( ) {
407
- return None ;
408
- }
409
-
410
385
// FIXME: This heuristic is brittle and with the right macro may select completely unrelated nodes?
411
386
let anc = db. parse ( file_id) . syntax_node ( ) . covering_element ( range) ;
412
387
let value = anc. ancestors ( ) . find_map ( N :: cast) ?;
0 commit comments