Skip to content

Commit 7a5ff0f

Browse files
committed
Simpilfy origin_range logic
1 parent 3e25b17 commit 7a5ff0f

File tree

2 files changed

+51
-38
lines changed

2 files changed

+51
-38
lines changed

crates/ra_hir/src/semantics.rs

Lines changed: 27 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ use hir_def::{
88
};
99
use ra_db::{FileId, FileRange};
1010
use ra_syntax::{
11-
algo::{find_covering_element, skip_trivia_token},
12-
ast, match_ast, AstNode, Direction, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxToken,
11+
algo::skip_trivia_token, ast, match_ast, AstNode, Direction, SyntaxNode, SyntaxToken,
1312
TextRange, TextUnit,
1413
};
1514
use rustc_hash::{FxHashMap, FxHashSet};
@@ -21,6 +20,7 @@ use crate::{
2120
Function, HirFileId, InFile, Local, MacroDef, Module, Name, Origin, Path, PathResolution,
2221
ScopeDef, StructField, Trait, Type, TypeParam, VariantDef,
2322
};
23+
use hir_expand::ExpansionInfo;
2424
use ra_prof::profile;
2525

2626
/// Primary API to get semantic information, like types, from syntax trees.
@@ -337,22 +337,12 @@ impl<'a, DB: HirDatabase> SemanticsScope<'a, DB> {
337337

338338
// FIXME: Change `HasSource` trait to work with `Semantics` and remove this?
339339
pub fn original_range(db: &impl HirDatabase, node: InFile<&SyntaxNode>) -> FileRange {
340-
let mut elem: InFile<SyntaxElement> = node.map(|n| n.clone().into());
341-
342-
while let Some((range, Origin::Call)) = original_range_and_origin(db, elem.as_ref()) {
340+
if let Some(range) = original_range_opt(db, node) {
343341
let original_file = range.file_id.original_file(db);
344-
345342
if range.file_id == original_file.into() {
346343
return FileRange { file_id: original_file, range: range.value };
347344
}
348345

349-
if range.file_id != elem.file_id {
350-
if let Some(root) = db.parse_or_expand(range.file_id) {
351-
elem = range.with_value(find_covering_element(&root, range.value));
352-
continue;
353-
}
354-
}
355-
356346
log::error!("Fail to mapping up more for {:?}", range);
357347
return FileRange { file_id: range.file_id.original_file(db), range: range.value };
358348
}
@@ -370,43 +360,42 @@ pub fn original_range(db: &impl HirDatabase, node: InFile<&SyntaxNode>) -> FileR
370360
FileRange { file_id: node.file_id.original_file(db), range: node.value.text_range() }
371361
}
372362

373-
fn original_range_and_origin(
363+
fn original_range_opt(
374364
db: &impl HirDatabase,
375-
elem: InFile<&SyntaxElement>,
376-
) -> Option<(InFile<TextRange>, Origin)> {
377-
let expansion = elem.file_id.expansion_info(db)?;
378-
379-
let node = match elem.as_ref().value {
380-
NodeOrToken::Node(it) => elem.with_value(it),
381-
NodeOrToken::Token(it) => {
382-
let (tt, origin) = expansion.map_token_up(elem.with_value(it))?;
383-
return Some((tt.map(|it| it.text_range()), origin));
384-
}
385-
};
365+
node: InFile<&SyntaxNode>,
366+
) -> Option<InFile<TextRange>> {
367+
let expansion = node.file_id.expansion_info(db)?;
386368

387369
// the input node has only one token ?
388370
let single = skip_trivia_token(node.value.first_token()?, Direction::Next)?
389371
== skip_trivia_token(node.value.last_token()?, Direction::Prev)?;
390372

391373
Some(node.value.descendants().find_map(|it| {
392374
let first = skip_trivia_token(it.first_token()?, Direction::Next)?;
393-
let last = skip_trivia_token(it.last_token()?, Direction::Prev)?;
394-
395-
if !single && first == last {
396-
return None;
397-
}
375+
let first = ascend_call_token(db, &expansion, node.with_value(first))?;
398376

399-
// Try to map first and last tokens of node, and, if success, return the union range of mapped tokens
400-
let (first, first_origin) = expansion.map_token_up(node.with_value(&first))?;
401-
let (last, last_origin) = expansion.map_token_up(node.with_value(&last))?;
377+
let last = skip_trivia_token(it.last_token()?, Direction::Prev)?;
378+
let last = ascend_call_token(db, &expansion, node.with_value(last))?;
402379

403-
if first.file_id != last.file_id || first_origin != last_origin {
380+
if (!single && first == last) || (first.file_id != last.file_id) {
404381
return None;
405382
}
406383

407-
Some((
408-
first.with_value(first.value.text_range().extend_to(&last.value.text_range())),
409-
first_origin,
410-
))
384+
Some(first.with_value(first.value.text_range().extend_to(&last.value.text_range())))
411385
})?)
412386
}
387+
388+
fn ascend_call_token(
389+
db: &impl HirDatabase,
390+
expansion: &ExpansionInfo,
391+
token: InFile<SyntaxToken>,
392+
) -> Option<InFile<SyntaxToken>> {
393+
let (mapped, origin) = expansion.map_token_up(token.as_ref())?;
394+
if origin != Origin::Call {
395+
return None;
396+
}
397+
if let Some(info) = mapped.file_id.expansion_info(db) {
398+
return ascend_call_token(db, &info, mapped);
399+
}
400+
Some(mapped)
401+
}

crates/ra_ide/src/hover.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,30 @@ fn func(foo: i32) { if true { <|>foo; }; }
738738
assert_eq!(hover_on, "bar")
739739
}
740740

741+
#[test]
742+
fn test_hover_through_func_in_macro_recursive() {
743+
let hover_on = check_hover_result(
744+
"
745+
//- /lib.rs
746+
macro_rules! id_deep {
747+
($($tt:tt)*) => { $($tt)* }
748+
}
749+
macro_rules! id {
750+
($($tt:tt)*) => { id_deep!($($tt)*) }
751+
}
752+
fn bar() -> u32 {
753+
0
754+
}
755+
fn foo() {
756+
let a = id!([0u32, bar(<|>)] );
757+
}
758+
",
759+
&["u32"],
760+
);
761+
762+
assert_eq!(hover_on, "bar()")
763+
}
764+
741765
#[test]
742766
fn test_hover_through_literal_string_in_macro() {
743767
let hover_on = check_hover_result(

0 commit comments

Comments
 (0)