@@ -10,7 +10,7 @@ use syntax::{AstNode, AstPtr, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange,
1010
1111use crate :: {
1212 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 ,
1414} ;
1515
1616/// `InFile<T>` stores a value of `T` inside a particular file/syntax tree.
@@ -38,6 +38,9 @@ impl<N: AstIdNode> AstId<N> {
3838 pub fn to_node ( & self , db : & dyn ExpandDatabase ) -> N {
3939 self . to_ptr ( db) . to_node ( & db. parse_or_expand ( self . file_id ) )
4040 }
41+ pub fn to_range ( & self , db : & dyn ExpandDatabase ) -> TextRange {
42+ self . to_ptr ( db) . text_range ( )
43+ }
4144 pub fn to_in_file_node ( & self , db : & dyn ExpandDatabase ) -> crate :: InFile < N > {
4245 crate :: InFile :: new ( self . file_id , self . to_ptr ( db) . to_node ( & db. parse_or_expand ( self . file_id ) ) )
4346 }
@@ -49,6 +52,9 @@ impl<N: AstIdNode> AstId<N> {
4952pub type ErasedAstId = crate :: InFile < ErasedFileAstId > ;
5053
5154impl ErasedAstId {
55+ pub fn to_range ( & self , db : & dyn ExpandDatabase ) -> TextRange {
56+ self . to_ptr ( db) . text_range ( )
57+ }
5258 pub fn to_ptr ( & self , db : & dyn ExpandDatabase ) -> SyntaxNodePtr {
5359 db. ast_id_map ( self . file_id ) . get_erased ( self . value )
5460 }
@@ -173,66 +179,27 @@ impl InFile<&SyntaxNode> {
173179 ///
174180 /// For attributes and derives, this will point back to the attribute only.
175181 /// 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)
194184 }
195185
196186 /// Falls back to the macro call range if the node cannot be mapped up fully.
197187 pub fn original_file_range_with_macro_call_body (
198188 self ,
199189 db : & dyn db:: ExpandDatabase ,
200190 ) -> 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)
218192 }
219193
220194 /// Attempts to map the syntax node back up its macro calls.
221195 pub fn original_file_range_opt (
222196 self ,
223197 db : & dyn db:: ExpandDatabase ,
224198 ) -> 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)
233200 }
234201
235- pub fn original_syntax_node (
202+ pub fn original_syntax_node_rooted (
236203 self ,
237204 db : & dyn db:: ExpandDatabase ,
238205 ) -> Option < InRealFile < SyntaxNode > > {
@@ -242,25 +209,21 @@ impl InFile<&SyntaxNode> {
242209 HirFileIdRepr :: FileId ( file_id) => {
243210 return Some ( InRealFile { file_id, value : self . value . clone ( ) } )
244211 }
245- HirFileIdRepr :: MacroFile ( m) => m,
212+ HirFileIdRepr :: MacroFile ( m) if m. is_attr_macro ( db) => m,
213+ _ => return None ,
246214 } ;
247- if !file_id. is_attr_macro ( db) {
248- return None ;
249- }
250215
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 ( ) ) ?;
253218
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) ;
261219 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) ?;
264227 Some ( InRealFile :: new ( file_id, value) )
265228 }
266229}
@@ -355,8 +318,8 @@ impl InFile<TextRange> {
355318 match self . file_id . repr ( ) {
356319 HirFileIdRepr :: FileId ( file_id) => FileRange { file_id, range : self . value } ,
357320 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,
360323 _ => {
361324 let loc = db. lookup_intern_macro_call ( mac_file. macro_call_id ) ;
362325 loc. kind . original_call_range ( db)
@@ -366,6 +329,24 @@ impl InFile<TextRange> {
366329 }
367330 }
368331
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+
369350 pub fn original_node_file_range_opt (
370351 self ,
371352 db : & dyn db:: ExpandDatabase ,
@@ -395,18 +376,12 @@ impl<N: AstNode> InFile<N> {
395376 return None ;
396377 }
397378
398- let ( FileRange { file_id, range } , ctx ) = map_node_range_up (
379+ let FileRange { file_id, range } = map_node_range_up_rooted (
399380 db,
400381 & db. expansion_span_map ( file_id) ,
401382 self . value . syntax ( ) . text_range ( ) ,
402383 ) ?;
403384
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-
410385 // FIXME: This heuristic is brittle and with the right macro may select completely unrelated nodes?
411386 let anc = db. parse ( file_id) . syntax_node ( ) . covering_element ( range) ;
412387 let value = anc. ancestors ( ) . find_map ( N :: cast) ?;
0 commit comments