@@ -24,9 +24,9 @@ use std::{hash::Hash, iter, sync::Arc};
2424
2525use base_db:: { impl_intern_key, salsa, CrateId , FileId , FileRange } ;
2626use syntax:: {
27- algo:: skip_trivia_token,
27+ algo:: { self , skip_trivia_token} ,
2828 ast:: { self , AstNode , HasAttrs } ,
29- Direction , SyntaxNode , SyntaxToken , TextRange ,
29+ Direction , SyntaxNode , SyntaxToken ,
3030} ;
3131
3232use crate :: {
@@ -600,13 +600,15 @@ impl<'a> InFile<&'a SyntaxNode> {
600600
601601 /// Attempts to map the syntax node back up its macro calls.
602602 pub fn original_file_range_opt ( self , db : & dyn db:: AstDatabase ) -> Option < FileRange > {
603- match original_range_opt ( db, self ) {
604- Some ( range) => {
605- let original_file = range. file_id . original_file ( db) ;
606- if range. file_id != original_file. into ( ) {
603+ match ascend_node_border_tokens ( db, self ) {
604+ Some ( InFile { file_id, value : ( first, last) } ) => {
605+ let original_file = file_id. original_file ( db) ;
606+ let range = first. text_range ( ) . cover ( last. text_range ( ) ) ;
607+ if file_id != original_file. into ( ) {
607608 tracing:: error!( "Failed mapping up more for {:?}" , range) ;
609+ return None ;
608610 }
609- Some ( FileRange { file_id : original_file, range : range . value } )
611+ Some ( FileRange { file_id : original_file, range } )
610612 }
611613 _ if !self . file_id . is_macro ( ) => Some ( FileRange {
612614 file_id : self . file_id . original_file ( db) ,
@@ -617,28 +619,29 @@ impl<'a> InFile<&'a SyntaxNode> {
617619 }
618620}
619621
620- fn original_range_opt (
622+ fn ascend_node_border_tokens (
621623 db : & dyn db:: AstDatabase ,
622- node : InFile < & SyntaxNode > ,
623- ) -> Option < InFile < TextRange > > {
624- let expansion = node . file_id . expansion_info ( db) ?;
624+ InFile { file_id , value : node } : InFile < & SyntaxNode > ,
625+ ) -> Option < InFile < ( SyntaxToken , SyntaxToken ) > > {
626+ let expansion = file_id. expansion_info ( db) ?;
625627
626628 // the input node has only one token ?
627- let single = skip_trivia_token ( node. value . first_token ( ) ?, Direction :: Next ) ?
628- == skip_trivia_token ( node. value . last_token ( ) ?, Direction :: Prev ) ?;
629+ let first = skip_trivia_token ( node. first_token ( ) ?, Direction :: Next ) ?;
630+ let last = skip_trivia_token ( node. last_token ( ) ?, Direction :: Prev ) ?;
631+ let is_single_token = first == last;
629632
630- node. value . descendants ( ) . find_map ( |it| {
633+ node. descendants ( ) . find_map ( |it| {
631634 let first = skip_trivia_token ( it. first_token ( ) ?, Direction :: Next ) ?;
632- let first = ascend_call_token ( db, & expansion, node . with_value ( first) ) ?;
635+ let first = ascend_call_token ( db, & expansion, InFile :: new ( file_id , first) ) ?;
633636
634637 let last = skip_trivia_token ( it. last_token ( ) ?, Direction :: Prev ) ?;
635- let last = ascend_call_token ( db, & expansion, node . with_value ( last) ) ?;
638+ let last = ascend_call_token ( db, & expansion, InFile :: new ( file_id , last) ) ?;
636639
637- if ( !single && first == last) || ( first. file_id != last. file_id ) {
640+ if ( !is_single_token && first == last) || ( first. file_id != last. file_id ) {
638641 return None ;
639642 }
640643
641- Some ( first. with_value ( first. value . text_range ( ) . cover ( last. value . text_range ( ) ) ) )
644+ Some ( InFile :: new ( first. file_id , ( first. value , last. value ) ) )
642645 } )
643646}
644647
@@ -674,6 +677,23 @@ impl<N: AstNode> InFile<N> {
674677 self . value . syntax ( ) . descendants ( ) . filter_map ( T :: cast) . map ( move |n| self . with_value ( n) )
675678 }
676679
680+ pub fn original_ast_node ( self , db : & dyn db:: AstDatabase ) -> Option < InFile < N > > {
681+ match ascend_node_border_tokens ( db, self . syntax ( ) ) {
682+ Some ( InFile { file_id, value : ( first, last) } ) => {
683+ let original_file = file_id. original_file ( db) ;
684+ if file_id != original_file. into ( ) {
685+ let range = first. text_range ( ) . cover ( last. text_range ( ) ) ;
686+ tracing:: error!( "Failed mapping up more for {:?}" , range) ;
687+ return None ;
688+ }
689+ let anc = algo:: least_common_ancestor ( & first. parent ( ) ?, & last. parent ( ) ?) ?;
690+ Some ( InFile :: new ( file_id, anc. ancestors ( ) . find_map ( N :: cast) ?) )
691+ }
692+ _ if !self . file_id . is_macro ( ) => Some ( self ) ,
693+ _ => None ,
694+ }
695+ }
696+
677697 pub fn syntax ( & self ) -> InFile < & SyntaxNode > {
678698 self . with_value ( self . value . syntax ( ) )
679699 }
0 commit comments