Skip to content

Commit ba9f93e

Browse files
committed
fix: Fix callHierarchy LSP violation
1 parent 77bca53 commit ba9f93e

File tree

2 files changed

+187
-31
lines changed

2 files changed

+187
-31
lines changed

src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs

+181-29
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@ use ide_db::{
99
search::FileReference,
1010
FxIndexMap, RootDatabase,
1111
};
12-
use syntax::{ast, AstNode, SyntaxKind::IDENT, TextRange};
12+
use span::FileRange;
13+
use syntax::{ast, AstNode, SyntaxKind::IDENT};
1314

1415
use crate::{goto_definition, FilePosition, NavigationTarget, RangeInfo, TryToNav};
1516

1617
#[derive(Debug, Clone)]
1718
pub struct CallItem {
1819
pub target: NavigationTarget,
19-
pub ranges: Vec<TextRange>,
20+
pub ranges: Vec<FileRange>,
2021
}
2122

2223
pub(crate) fn call_hierarchy(
@@ -61,9 +62,10 @@ pub(crate) fn incoming_calls(
6162
def.try_to_nav(sema.db)
6263
});
6364
if let Some(nav) = nav {
64-
calls.add(nav.call_site, sema.original_range(name.syntax()).range);
65+
let range = sema.original_range(name.syntax());
66+
calls.add(nav.call_site, range);
6567
if let Some(other) = nav.def_site {
66-
calls.add(other, sema.original_range(name.syntax()).range);
68+
calls.add(other, range);
6769
}
6870
}
6971
}
@@ -107,12 +109,13 @@ pub(crate) fn outgoing_calls(
107109
hir::CallableKind::TupleStruct(it) => it.try_to_nav(db),
108110
_ => None,
109111
}
110-
.zip(Some(expr.syntax().text_range()))
112+
.zip(Some(sema.original_range(expr.syntax())))
111113
}
112114
ast::CallableExpr::MethodCall(expr) => {
113-
let range = expr.name_ref()?.syntax().text_range();
114115
let function = sema.resolve_method_call(&expr)?;
115-
function.try_to_nav(db).zip(Some(range))
116+
function
117+
.try_to_nav(db)
118+
.zip(Some(sema.original_range(expr.name_ref()?.syntax())))
116119
}
117120
}?;
118121
Some(nav_target.into_iter().zip(iter::repeat(range)))
@@ -125,11 +128,11 @@ pub(crate) fn outgoing_calls(
125128

126129
#[derive(Default)]
127130
struct CallLocations {
128-
funcs: FxIndexMap<NavigationTarget, Vec<TextRange>>,
131+
funcs: FxIndexMap<NavigationTarget, Vec<FileRange>>,
129132
}
130133

131134
impl CallLocations {
132-
fn add(&mut self, target: NavigationTarget, range: TextRange) {
135+
fn add(&mut self, target: NavigationTarget, range: FileRange) {
133136
self.funcs.entry(target).or_default().push(range);
134137
}
135138

@@ -153,7 +156,14 @@ mod tests {
153156
expected_outgoing: Expect,
154157
) {
155158
fn debug_render(item: crate::CallItem) -> String {
156-
format!("{} : {:?}", item.target.debug_render(), item.ranges)
159+
format!(
160+
"{} : {}",
161+
item.target.debug_render(),
162+
item.ranges.iter().format_with(", ", |range, f| f(&format_args!(
163+
"{:?}:{:?}",
164+
range.file_id, range.range
165+
)))
166+
)
157167
}
158168

159169
let (analysis, pos) = fixture::position(ra_fixture);
@@ -183,7 +193,7 @@ fn caller() {
183193
}
184194
"#,
185195
expect![["callee Function FileId(0) 0..14 3..9"]],
186-
expect![["caller Function FileId(0) 15..44 18..24 : [33..39]"]],
196+
expect!["caller Function FileId(0) 15..44 18..24 : FileId(0):33..39"],
187197
expect![[]],
188198
);
189199
}
@@ -199,7 +209,7 @@ fn caller() {
199209
}
200210
"#,
201211
expect![["callee Function FileId(0) 0..14 3..9"]],
202-
expect![["caller Function FileId(0) 15..44 18..24 : [33..39]"]],
212+
expect!["caller Function FileId(0) 15..44 18..24 : FileId(0):33..39"],
203213
expect![[]],
204214
);
205215
}
@@ -216,7 +226,7 @@ fn caller() {
216226
}
217227
"#,
218228
expect![["callee Function FileId(0) 0..14 3..9"]],
219-
expect![["caller Function FileId(0) 15..58 18..24 : [33..39, 47..53]"]],
229+
expect!["caller Function FileId(0) 15..58 18..24 : FileId(0):33..39, FileId(0):47..53"],
220230
expect![[]],
221231
);
222232
}
@@ -236,9 +246,9 @@ fn caller2() {
236246
}
237247
"#,
238248
expect![["callee Function FileId(0) 0..14 3..9"]],
239-
expect![["
240-
caller1 Function FileId(0) 15..45 18..25 : [34..40]
241-
caller2 Function FileId(0) 47..77 50..57 : [66..72]"]],
249+
expect![[r#"
250+
caller1 Function FileId(0) 15..45 18..25 : FileId(0):34..40
251+
caller2 Function FileId(0) 47..77 50..57 : FileId(0):66..72"#]],
242252
expect![[]],
243253
);
244254
}
@@ -265,8 +275,8 @@ mod tests {
265275
"#,
266276
expect![["callee Function FileId(0) 0..14 3..9"]],
267277
expect![[r#"
268-
caller1 Function FileId(0) 15..45 18..25 : [34..40]
269-
test_caller Function FileId(0) 95..149 110..121 tests : [134..140]"#]],
278+
caller1 Function FileId(0) 15..45 18..25 : FileId(0):34..40
279+
test_caller Function FileId(0) 95..149 110..121 tests : FileId(0):134..140"#]],
270280
expect![[]],
271281
);
272282
}
@@ -287,7 +297,7 @@ fn caller() {
287297
pub fn callee() {}
288298
"#,
289299
expect!["callee Function FileId(1) 0..18 7..13 foo"],
290-
expect![["caller Function FileId(0) 27..56 30..36 : [45..51]"]],
300+
expect!["caller Function FileId(0) 27..56 30..36 : FileId(0):45..51"],
291301
expect![[]],
292302
);
293303
}
@@ -305,7 +315,7 @@ fn call$0er() {
305315
"#,
306316
expect![["caller Function FileId(0) 15..58 18..24"]],
307317
expect![[]],
308-
expect![["callee Function FileId(0) 0..14 3..9 : [33..39, 47..53]"]],
318+
expect!["callee Function FileId(0) 0..14 3..9 : FileId(0):33..39, FileId(0):47..53"],
309319
);
310320
}
311321

@@ -326,7 +336,7 @@ pub fn callee() {}
326336
"#,
327337
expect![["caller Function FileId(0) 27..56 30..36"]],
328338
expect![[]],
329-
expect!["callee Function FileId(1) 0..18 7..13 foo : [45..51]"],
339+
expect!["callee Function FileId(1) 0..18 7..13 foo : FileId(0):45..51"],
330340
);
331341
}
332342

@@ -348,8 +358,8 @@ fn caller3() {
348358
}
349359
"#,
350360
expect![["caller2 Function FileId(0) 33..64 36..43"]],
351-
expect![["caller1 Function FileId(0) 0..31 3..10 : [19..26]"]],
352-
expect![["caller3 Function FileId(0) 66..83 69..76 : [52..59]"]],
361+
expect!["caller1 Function FileId(0) 0..31 3..10 : FileId(0):19..26"],
362+
expect!["caller3 Function FileId(0) 66..83 69..76 : FileId(0):52..59"],
353363
);
354364
}
355365

@@ -368,8 +378,8 @@ fn main() {
368378
}
369379
"#,
370380
expect![["a Function FileId(0) 0..18 3..4"]],
371-
expect![["main Function FileId(0) 31..52 34..38 : [47..48]"]],
372-
expect![["b Function FileId(0) 20..29 23..24 : [13..14]"]],
381+
expect!["main Function FileId(0) 31..52 34..38 : FileId(0):47..48"],
382+
expect!["b Function FileId(0) 20..29 23..24 : FileId(0):13..14"],
373383
);
374384

375385
check_hierarchy(
@@ -385,7 +395,7 @@ fn main() {
385395
}
386396
"#,
387397
expect![["b Function FileId(0) 20..29 23..24"]],
388-
expect![["a Function FileId(0) 0..18 3..4 : [13..14]"]],
398+
expect!["a Function FileId(0) 0..18 3..4 : FileId(0):13..14"],
389399
expect![[]],
390400
);
391401
}
@@ -410,7 +420,7 @@ fn caller() {
410420
}
411421
"#,
412422
expect![[r#"callee Function FileId(0) 144..159 152..158"#]],
413-
expect![[r#"caller Function FileId(0) 160..194 163..169 : [184..190]"#]],
423+
expect!["caller Function FileId(0) 160..194 163..169 : FileId(0):184..190"],
414424
expect![[]],
415425
);
416426
check_hierarchy(
@@ -431,7 +441,7 @@ fn caller() {
431441
}
432442
"#,
433443
expect![[r#"callee Function FileId(0) 144..159 152..158"#]],
434-
expect![[r#"caller Function FileId(0) 160..194 163..169 : [184..190]"#]],
444+
expect!["caller Function FileId(0) 160..194 163..169 : FileId(0):184..190"],
435445
expect![[]],
436446
);
437447
}
@@ -461,6 +471,148 @@ fn caller$0() {
461471
expect![[]],
462472
);
463473
}
474+
#[test]
475+
fn test_call_hierarchy_in_macros_incoming_different_files() {
476+
check_hierarchy(
477+
r#"
478+
//- /lib.rs
479+
#[macro_use]
480+
mod foo;
481+
define!(callee)
482+
fn caller() {
483+
call!(call$0ee);
484+
}
485+
//- /foo.rs
486+
macro_rules! define {
487+
($ident:ident) => {
488+
fn $ident {}
489+
}
490+
}
491+
macro_rules! call {
492+
($ident:ident) => {
493+
$ident()
494+
}
495+
}
496+
"#,
497+
expect!["callee Function FileId(0) 22..37 30..36"],
498+
expect!["caller Function FileId(0) 38..72 41..47 : FileId(0):62..68"],
499+
expect![[]],
500+
);
501+
check_hierarchy(
502+
r#"
503+
//- /lib.rs
504+
#[macro_use]
505+
mod foo;
506+
define!(cal$0lee)
507+
fn caller() {
508+
call!(callee);
509+
}
510+
//- /foo.rs
511+
macro_rules! define {
512+
($ident:ident) => {
513+
fn $ident {}
514+
}
515+
}
516+
macro_rules! call {
517+
($ident:ident) => {
518+
$ident()
519+
}
520+
}
521+
"#,
522+
expect!["callee Function FileId(0) 22..37 30..36"],
523+
expect!["caller Function FileId(0) 38..72 41..47 : FileId(0):62..68"],
524+
expect![[]],
525+
);
526+
check_hierarchy(
527+
r#"
528+
//- /lib.rs
529+
#[macro_use]
530+
mod foo;
531+
define!(cal$0lee)
532+
call!(callee);
533+
//- /foo.rs
534+
macro_rules! define {
535+
($ident:ident) => {
536+
fn $ident {}
537+
}
538+
}
539+
macro_rules! call {
540+
($ident:ident) => {
541+
fn caller() {
542+
$ident()
543+
}
544+
fn $ident() {
545+
$ident()
546+
}
547+
}
548+
}
549+
"#,
550+
expect!["callee Function FileId(0) 22..37 30..36"],
551+
expect![[r#"
552+
callee Function FileId(0) 38..52 44..50 : FileId(0):44..50
553+
caller Function FileId(0) 38..52 : FileId(0):44..50
554+
caller Function FileId(1) 130..136 130..136 : FileId(0):44..50"#]],
555+
expect![[]],
556+
);
557+
}
558+
559+
#[test]
560+
fn test_call_hierarchy_in_macros_outgoing_different_files() {
561+
check_hierarchy(
562+
r#"
563+
//- /lib.rs
564+
#[macro_use]
565+
mod foo;
566+
define!(callee)
567+
fn caller$0() {
568+
call!(callee);
569+
}
570+
//- /foo.rs
571+
macro_rules! define {
572+
($ident:ident) => {
573+
fn $ident {}
574+
}
575+
}
576+
macro_rules! call {
577+
($ident:ident) => {
578+
$ident()
579+
callee()
580+
}
581+
}
582+
"#,
583+
expect!["caller Function FileId(0) 38..72 41..47"],
584+
expect![[]],
585+
// FIXME
586+
expect![[]],
587+
);
588+
check_hierarchy(
589+
r#"
590+
//- /lib.rs
591+
#[macro_use]
592+
mod foo;
593+
define!(callee)
594+
fn caller$0() {
595+
call!(callee);
596+
}
597+
//- /foo.rs
598+
macro_rules! define {
599+
() => {
600+
fn callee {}
601+
}
602+
}
603+
macro_rules! call {
604+
($ident:ident) => {
605+
$ident()
606+
callee()
607+
}
608+
}
609+
"#,
610+
expect!["caller Function FileId(0) 38..72 41..47"],
611+
expect![[]],
612+
// FIXME
613+
expect![[]],
614+
);
615+
}
464616

465617
#[test]
466618
fn test_trait_method_call_hierarchy() {
@@ -481,7 +633,7 @@ fn caller() {
481633
}
482634
"#,
483635
expect!["callee Function FileId(0) 15..27 18..24 T1"],
484-
expect![["caller Function FileId(0) 82..115 85..91 : [104..110]"]],
636+
expect!["caller Function FileId(0) 82..115 85..91 : FileId(0):104..110"],
485637
expect![[]],
486638
);
487639
}

src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -1640,7 +1640,9 @@ pub(crate) fn handle_call_hierarchy_incoming(
16401640
from_ranges: call_item
16411641
.ranges
16421642
.into_iter()
1643-
.map(|it| to_proto::range(&line_index, it))
1643+
// This is the range relative to the item
1644+
.filter(|it| it.file_id == file_id)
1645+
.map(|it| to_proto::range(&line_index, it.range))
16441646
.collect(),
16451647
});
16461648
}
@@ -1675,7 +1677,9 @@ pub(crate) fn handle_call_hierarchy_outgoing(
16751677
from_ranges: call_item
16761678
.ranges
16771679
.into_iter()
1678-
.map(|it| to_proto::range(&line_index, it))
1680+
// This is the range relative to the caller
1681+
.filter(|it| it.file_id == fpos.file_id)
1682+
.map(|it| to_proto::range(&line_index, it.range))
16791683
.collect(),
16801684
});
16811685
}

0 commit comments

Comments
 (0)