mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 21:43:37 +00:00
fix: Fix callHierarchy LSP violation
This commit is contained in:
parent
8a4b1fd96e
commit
6c8c49b01b
2 changed files with 187 additions and 31 deletions
|
@ -9,14 +9,15 @@ use ide_db::{
|
|||
search::FileReference,
|
||||
FxIndexMap, RootDatabase,
|
||||
};
|
||||
use syntax::{ast, AstNode, SyntaxKind::IDENT, TextRange};
|
||||
use span::FileRange;
|
||||
use syntax::{ast, AstNode, SyntaxKind::IDENT};
|
||||
|
||||
use crate::{goto_definition, FilePosition, NavigationTarget, RangeInfo, TryToNav};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CallItem {
|
||||
pub target: NavigationTarget,
|
||||
pub ranges: Vec<TextRange>,
|
||||
pub ranges: Vec<FileRange>,
|
||||
}
|
||||
|
||||
pub(crate) fn call_hierarchy(
|
||||
|
@ -61,9 +62,10 @@ pub(crate) fn incoming_calls(
|
|||
def.try_to_nav(sema.db)
|
||||
});
|
||||
if let Some(nav) = nav {
|
||||
calls.add(nav.call_site, sema.original_range(name.syntax()).range);
|
||||
let range = sema.original_range(name.syntax());
|
||||
calls.add(nav.call_site, range);
|
||||
if let Some(other) = nav.def_site {
|
||||
calls.add(other, sema.original_range(name.syntax()).range);
|
||||
calls.add(other, range);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -107,12 +109,13 @@ pub(crate) fn outgoing_calls(
|
|||
hir::CallableKind::TupleStruct(it) => it.try_to_nav(db),
|
||||
_ => None,
|
||||
}
|
||||
.zip(Some(expr.syntax().text_range()))
|
||||
.zip(Some(sema.original_range(expr.syntax())))
|
||||
}
|
||||
ast::CallableExpr::MethodCall(expr) => {
|
||||
let range = expr.name_ref()?.syntax().text_range();
|
||||
let function = sema.resolve_method_call(&expr)?;
|
||||
function.try_to_nav(db).zip(Some(range))
|
||||
function
|
||||
.try_to_nav(db)
|
||||
.zip(Some(sema.original_range(expr.name_ref()?.syntax())))
|
||||
}
|
||||
}?;
|
||||
Some(nav_target.into_iter().zip(iter::repeat(range)))
|
||||
|
@ -125,11 +128,11 @@ pub(crate) fn outgoing_calls(
|
|||
|
||||
#[derive(Default)]
|
||||
struct CallLocations {
|
||||
funcs: FxIndexMap<NavigationTarget, Vec<TextRange>>,
|
||||
funcs: FxIndexMap<NavigationTarget, Vec<FileRange>>,
|
||||
}
|
||||
|
||||
impl CallLocations {
|
||||
fn add(&mut self, target: NavigationTarget, range: TextRange) {
|
||||
fn add(&mut self, target: NavigationTarget, range: FileRange) {
|
||||
self.funcs.entry(target).or_default().push(range);
|
||||
}
|
||||
|
||||
|
@ -153,7 +156,14 @@ mod tests {
|
|||
expected_outgoing: Expect,
|
||||
) {
|
||||
fn debug_render(item: crate::CallItem) -> String {
|
||||
format!("{} : {:?}", item.target.debug_render(), item.ranges)
|
||||
format!(
|
||||
"{} : {}",
|
||||
item.target.debug_render(),
|
||||
item.ranges.iter().format_with(", ", |range, f| f(&format_args!(
|
||||
"{:?}:{:?}",
|
||||
range.file_id, range.range
|
||||
)))
|
||||
)
|
||||
}
|
||||
|
||||
let (analysis, pos) = fixture::position(ra_fixture);
|
||||
|
@ -183,7 +193,7 @@ fn caller() {
|
|||
}
|
||||
"#,
|
||||
expect![["callee Function FileId(0) 0..14 3..9"]],
|
||||
expect![["caller Function FileId(0) 15..44 18..24 : [33..39]"]],
|
||||
expect!["caller Function FileId(0) 15..44 18..24 : FileId(0):33..39"],
|
||||
expect![[]],
|
||||
);
|
||||
}
|
||||
|
@ -199,7 +209,7 @@ fn caller() {
|
|||
}
|
||||
"#,
|
||||
expect![["callee Function FileId(0) 0..14 3..9"]],
|
||||
expect![["caller Function FileId(0) 15..44 18..24 : [33..39]"]],
|
||||
expect!["caller Function FileId(0) 15..44 18..24 : FileId(0):33..39"],
|
||||
expect![[]],
|
||||
);
|
||||
}
|
||||
|
@ -216,7 +226,7 @@ fn caller() {
|
|||
}
|
||||
"#,
|
||||
expect![["callee Function FileId(0) 0..14 3..9"]],
|
||||
expect![["caller Function FileId(0) 15..58 18..24 : [33..39, 47..53]"]],
|
||||
expect!["caller Function FileId(0) 15..58 18..24 : FileId(0):33..39, FileId(0):47..53"],
|
||||
expect![[]],
|
||||
);
|
||||
}
|
||||
|
@ -236,9 +246,9 @@ fn caller2() {
|
|||
}
|
||||
"#,
|
||||
expect![["callee Function FileId(0) 0..14 3..9"]],
|
||||
expect![["
|
||||
caller1 Function FileId(0) 15..45 18..25 : [34..40]
|
||||
caller2 Function FileId(0) 47..77 50..57 : [66..72]"]],
|
||||
expect![[r#"
|
||||
caller1 Function FileId(0) 15..45 18..25 : FileId(0):34..40
|
||||
caller2 Function FileId(0) 47..77 50..57 : FileId(0):66..72"#]],
|
||||
expect![[]],
|
||||
);
|
||||
}
|
||||
|
@ -265,8 +275,8 @@ mod tests {
|
|||
"#,
|
||||
expect![["callee Function FileId(0) 0..14 3..9"]],
|
||||
expect![[r#"
|
||||
caller1 Function FileId(0) 15..45 18..25 : [34..40]
|
||||
test_caller Function FileId(0) 95..149 110..121 tests : [134..140]"#]],
|
||||
caller1 Function FileId(0) 15..45 18..25 : FileId(0):34..40
|
||||
test_caller Function FileId(0) 95..149 110..121 tests : FileId(0):134..140"#]],
|
||||
expect![[]],
|
||||
);
|
||||
}
|
||||
|
@ -287,7 +297,7 @@ fn caller() {
|
|||
pub fn callee() {}
|
||||
"#,
|
||||
expect!["callee Function FileId(1) 0..18 7..13 foo"],
|
||||
expect![["caller Function FileId(0) 27..56 30..36 : [45..51]"]],
|
||||
expect!["caller Function FileId(0) 27..56 30..36 : FileId(0):45..51"],
|
||||
expect![[]],
|
||||
);
|
||||
}
|
||||
|
@ -305,7 +315,7 @@ fn call$0er() {
|
|||
"#,
|
||||
expect![["caller Function FileId(0) 15..58 18..24"]],
|
||||
expect![[]],
|
||||
expect![["callee Function FileId(0) 0..14 3..9 : [33..39, 47..53]"]],
|
||||
expect!["callee Function FileId(0) 0..14 3..9 : FileId(0):33..39, FileId(0):47..53"],
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -326,7 +336,7 @@ pub fn callee() {}
|
|||
"#,
|
||||
expect![["caller Function FileId(0) 27..56 30..36"]],
|
||||
expect![[]],
|
||||
expect!["callee Function FileId(1) 0..18 7..13 foo : [45..51]"],
|
||||
expect!["callee Function FileId(1) 0..18 7..13 foo : FileId(0):45..51"],
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -348,8 +358,8 @@ fn caller3() {
|
|||
}
|
||||
"#,
|
||||
expect![["caller2 Function FileId(0) 33..64 36..43"]],
|
||||
expect![["caller1 Function FileId(0) 0..31 3..10 : [19..26]"]],
|
||||
expect![["caller3 Function FileId(0) 66..83 69..76 : [52..59]"]],
|
||||
expect!["caller1 Function FileId(0) 0..31 3..10 : FileId(0):19..26"],
|
||||
expect!["caller3 Function FileId(0) 66..83 69..76 : FileId(0):52..59"],
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -368,8 +378,8 @@ fn main() {
|
|||
}
|
||||
"#,
|
||||
expect![["a Function FileId(0) 0..18 3..4"]],
|
||||
expect![["main Function FileId(0) 31..52 34..38 : [47..48]"]],
|
||||
expect![["b Function FileId(0) 20..29 23..24 : [13..14]"]],
|
||||
expect!["main Function FileId(0) 31..52 34..38 : FileId(0):47..48"],
|
||||
expect!["b Function FileId(0) 20..29 23..24 : FileId(0):13..14"],
|
||||
);
|
||||
|
||||
check_hierarchy(
|
||||
|
@ -385,7 +395,7 @@ fn main() {
|
|||
}
|
||||
"#,
|
||||
expect![["b Function FileId(0) 20..29 23..24"]],
|
||||
expect![["a Function FileId(0) 0..18 3..4 : [13..14]"]],
|
||||
expect!["a Function FileId(0) 0..18 3..4 : FileId(0):13..14"],
|
||||
expect![[]],
|
||||
);
|
||||
}
|
||||
|
@ -410,7 +420,7 @@ fn caller() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"callee Function FileId(0) 144..159 152..158"#]],
|
||||
expect![[r#"caller Function FileId(0) 160..194 163..169 : [184..190]"#]],
|
||||
expect!["caller Function FileId(0) 160..194 163..169 : FileId(0):184..190"],
|
||||
expect![[]],
|
||||
);
|
||||
check_hierarchy(
|
||||
|
@ -431,7 +441,7 @@ fn caller() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"callee Function FileId(0) 144..159 152..158"#]],
|
||||
expect![[r#"caller Function FileId(0) 160..194 163..169 : [184..190]"#]],
|
||||
expect!["caller Function FileId(0) 160..194 163..169 : FileId(0):184..190"],
|
||||
expect![[]],
|
||||
);
|
||||
}
|
||||
|
@ -461,6 +471,148 @@ fn caller$0() {
|
|||
expect![[]],
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn test_call_hierarchy_in_macros_incoming_different_files() {
|
||||
check_hierarchy(
|
||||
r#"
|
||||
//- /lib.rs
|
||||
#[macro_use]
|
||||
mod foo;
|
||||
define!(callee)
|
||||
fn caller() {
|
||||
call!(call$0ee);
|
||||
}
|
||||
//- /foo.rs
|
||||
macro_rules! define {
|
||||
($ident:ident) => {
|
||||
fn $ident {}
|
||||
}
|
||||
}
|
||||
macro_rules! call {
|
||||
($ident:ident) => {
|
||||
$ident()
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect!["callee Function FileId(0) 22..37 30..36"],
|
||||
expect!["caller Function FileId(0) 38..72 41..47 : FileId(0):62..68"],
|
||||
expect![[]],
|
||||
);
|
||||
check_hierarchy(
|
||||
r#"
|
||||
//- /lib.rs
|
||||
#[macro_use]
|
||||
mod foo;
|
||||
define!(cal$0lee)
|
||||
fn caller() {
|
||||
call!(callee);
|
||||
}
|
||||
//- /foo.rs
|
||||
macro_rules! define {
|
||||
($ident:ident) => {
|
||||
fn $ident {}
|
||||
}
|
||||
}
|
||||
macro_rules! call {
|
||||
($ident:ident) => {
|
||||
$ident()
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect!["callee Function FileId(0) 22..37 30..36"],
|
||||
expect!["caller Function FileId(0) 38..72 41..47 : FileId(0):62..68"],
|
||||
expect![[]],
|
||||
);
|
||||
check_hierarchy(
|
||||
r#"
|
||||
//- /lib.rs
|
||||
#[macro_use]
|
||||
mod foo;
|
||||
define!(cal$0lee)
|
||||
call!(callee);
|
||||
//- /foo.rs
|
||||
macro_rules! define {
|
||||
($ident:ident) => {
|
||||
fn $ident {}
|
||||
}
|
||||
}
|
||||
macro_rules! call {
|
||||
($ident:ident) => {
|
||||
fn caller() {
|
||||
$ident()
|
||||
}
|
||||
fn $ident() {
|
||||
$ident()
|
||||
}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect!["callee Function FileId(0) 22..37 30..36"],
|
||||
expect![[r#"
|
||||
callee Function FileId(0) 38..52 44..50 : FileId(0):44..50
|
||||
caller Function FileId(0) 38..52 : FileId(0):44..50
|
||||
caller Function FileId(1) 130..136 130..136 : FileId(0):44..50"#]],
|
||||
expect![[]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_call_hierarchy_in_macros_outgoing_different_files() {
|
||||
check_hierarchy(
|
||||
r#"
|
||||
//- /lib.rs
|
||||
#[macro_use]
|
||||
mod foo;
|
||||
define!(callee)
|
||||
fn caller$0() {
|
||||
call!(callee);
|
||||
}
|
||||
//- /foo.rs
|
||||
macro_rules! define {
|
||||
($ident:ident) => {
|
||||
fn $ident {}
|
||||
}
|
||||
}
|
||||
macro_rules! call {
|
||||
($ident:ident) => {
|
||||
$ident()
|
||||
callee()
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect!["caller Function FileId(0) 38..72 41..47"],
|
||||
expect![[]],
|
||||
// FIXME
|
||||
expect![[]],
|
||||
);
|
||||
check_hierarchy(
|
||||
r#"
|
||||
//- /lib.rs
|
||||
#[macro_use]
|
||||
mod foo;
|
||||
define!(callee)
|
||||
fn caller$0() {
|
||||
call!(callee);
|
||||
}
|
||||
//- /foo.rs
|
||||
macro_rules! define {
|
||||
() => {
|
||||
fn callee {}
|
||||
}
|
||||
}
|
||||
macro_rules! call {
|
||||
($ident:ident) => {
|
||||
$ident()
|
||||
callee()
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect!["caller Function FileId(0) 38..72 41..47"],
|
||||
expect![[]],
|
||||
// FIXME
|
||||
expect![[]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_trait_method_call_hierarchy() {
|
||||
|
@ -481,7 +633,7 @@ fn caller() {
|
|||
}
|
||||
"#,
|
||||
expect!["callee Function FileId(0) 15..27 18..24 T1"],
|
||||
expect![["caller Function FileId(0) 82..115 85..91 : [104..110]"]],
|
||||
expect!["caller Function FileId(0) 82..115 85..91 : FileId(0):104..110"],
|
||||
expect![[]],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1640,7 +1640,9 @@ pub(crate) fn handle_call_hierarchy_incoming(
|
|||
from_ranges: call_item
|
||||
.ranges
|
||||
.into_iter()
|
||||
.map(|it| to_proto::range(&line_index, it))
|
||||
// This is the range relative to the item
|
||||
.filter(|it| it.file_id == file_id)
|
||||
.map(|it| to_proto::range(&line_index, it.range))
|
||||
.collect(),
|
||||
});
|
||||
}
|
||||
|
@ -1675,7 +1677,9 @@ pub(crate) fn handle_call_hierarchy_outgoing(
|
|||
from_ranges: call_item
|
||||
.ranges
|
||||
.into_iter()
|
||||
.map(|it| to_proto::range(&line_index, it))
|
||||
// This is the range relative to the caller
|
||||
.filter(|it| it.file_id == fpos.file_id)
|
||||
.map(|it| to_proto::range(&line_index, it.range))
|
||||
.collect(),
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue