@@ -7,7 +7,10 @@ use hir_def::{
7
7
TraitId ,
8
8
} ;
9
9
use ra_db:: { FileId , FileRange } ;
10
- use ra_syntax:: { ast, AstNode , SyntaxNode , SyntaxToken , TextRange , TextUnit } ;
10
+ use ra_syntax:: {
11
+ algo:: find_covering_element, ast, AstNode , NodeOrToken , SyntaxElement , SyntaxNode , SyntaxToken ,
12
+ TextRange , TextUnit ,
13
+ } ;
11
14
use rustc_hash:: { FxHashMap , FxHashSet } ;
12
15
13
16
use crate :: {
@@ -273,10 +276,28 @@ impl<'a, DB: HirDatabase> SemanticsScope<'a, DB> {
273
276
274
277
// FIXME: Change `HasSource` trait to work with `Semantics` and remove this?
275
278
pub fn original_range ( db : & impl HirDatabase , node : InFile < & SyntaxNode > ) -> FileRange {
276
- if let Some ( ( range, Origin :: Call ) ) = original_range_and_origin ( db, node) {
277
- return range;
279
+ let mut elem: InFile < SyntaxElement > = node. map ( |n| n. clone ( ) . into ( ) ) ;
280
+
281
+ while let Some ( ( range, Origin :: Call ) ) = original_range_and_origin ( db, elem. as_ref ( ) ) {
282
+ let original_file = range. file_id . original_file ( db) ;
283
+
284
+ if range. file_id == original_file. into ( ) {
285
+ return FileRange { file_id : original_file, range : range. value } ;
286
+ }
287
+
288
+ // Fail to mapping up more, return the original file range instead
289
+ if range. file_id != elem. file_id {
290
+ if let Some ( root) = db. parse_or_expand ( range. file_id ) {
291
+ elem = range. with_value ( find_covering_element ( & root, range. value ) ) ;
292
+ continue ;
293
+ }
294
+ }
295
+
296
+ log:: error!( "Fail to mapping up more for {:?}" , range) ;
297
+ return FileRange { file_id : range. file_id . original_file ( db) , range : range. value } ;
278
298
}
279
299
300
+ // Fall back to whole macro call
280
301
if let Some ( expansion) = node. file_id . expansion_info ( db) {
281
302
if let Some ( call_node) = expansion. call_node ( ) {
282
303
return FileRange {
@@ -291,15 +312,22 @@ pub fn original_range(db: &impl HirDatabase, node: InFile<&SyntaxNode>) -> FileR
291
312
292
313
fn original_range_and_origin (
293
314
db : & impl HirDatabase ,
294
- node : InFile < & SyntaxNode > ,
295
- ) -> Option < ( FileRange , Origin ) > {
296
- let expansion = node. file_id . expansion_info ( db) ?;
315
+ elem : InFile < & SyntaxElement > ,
316
+ ) -> Option < ( InFile < TextRange > , Origin ) > {
317
+ let expansion = elem. file_id . expansion_info ( db) ?;
318
+
319
+ let node = match elem. as_ref ( ) . value {
320
+ NodeOrToken :: Node ( it) => elem. with_value ( it) ,
321
+ NodeOrToken :: Token ( it) => {
322
+ let ( tt, origin) = expansion. map_token_up ( elem. with_value ( it) ) ?;
323
+ return Some ( ( tt. map ( |it| it. text_range ( ) ) , origin) ) ;
324
+ }
325
+ } ;
297
326
298
327
// the input node has only one token ?
299
328
let single = node. value . first_token ( ) ? == node. value . last_token ( ) ?;
300
329
301
- // FIXME: We should handle recurside macro expansions
302
- let ( range, origin) = node. value . descendants ( ) . find_map ( |it| {
330
+ return Some ( node. value . descendants ( ) . find_map ( |it| {
303
331
let first = it. first_token ( ) ?;
304
332
let last = it. last_token ( ) ?;
305
333
@@ -320,12 +348,7 @@ fn original_range_and_origin(
320
348
first. with_value ( union_range ( first. value . text_range ( ) , last. value . text_range ( ) ) ) ,
321
349
first_origin,
322
350
) )
323
- } ) ?;
324
-
325
- return Some ( (
326
- FileRange { file_id : range. file_id . original_file ( db) , range : range. value } ,
327
- origin,
328
- ) ) ;
351
+ } ) ?) ;
329
352
330
353
fn union_range ( a : TextRange , b : TextRange ) -> TextRange {
331
354
let start = a. start ( ) . min ( b. start ( ) ) ;
0 commit comments