@@ -19,6 +19,12 @@ pub struct CallItem {
19
19
pub ranges : Vec < FileRange > ,
20
20
}
21
21
22
+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
23
+ pub struct CallHierarchyConfig {
24
+ /// Whether to exclude tests from the call hierarchy
25
+ pub exclude_tests : bool ,
26
+ }
27
+
22
28
pub ( crate ) fn call_hierarchy (
23
29
db : & RootDatabase ,
24
30
position : FilePosition ,
@@ -28,6 +34,7 @@ pub(crate) fn call_hierarchy(
28
34
29
35
pub ( crate ) fn incoming_calls (
30
36
db : & RootDatabase ,
37
+ CallHierarchyConfig { exclude_tests } : CallHierarchyConfig ,
31
38
FilePosition { file_id, offset } : FilePosition ,
32
39
) -> Option < Vec < CallItem > > {
33
40
let sema = & Semantics :: new ( db) ;
@@ -56,11 +63,18 @@ pub(crate) fn incoming_calls(
56
63
references. iter ( ) . filter_map ( |FileReference { name, .. } | name. as_name_ref ( ) ) ;
57
64
for name in references {
58
65
// This target is the containing function
59
- let nav = sema. ancestors_with_macros ( name. syntax ( ) . clone ( ) ) . find_map ( |node| {
66
+ let def_nav = sema. ancestors_with_macros ( name. syntax ( ) . clone ( ) ) . find_map ( |node| {
60
67
let def = ast:: Fn :: cast ( node) . and_then ( |fn_| sema. to_def ( & fn_) ) ?;
61
- def. try_to_nav ( sema. db )
68
+ // We should return def before check if it is a test, so that we
69
+ // will not continue to search for outer fn in nested fns
70
+ def. try_to_nav ( sema. db ) . map ( |nav| ( def, nav) )
62
71
} ) ;
63
- if let Some ( nav) = nav {
72
+
73
+ if let Some ( ( def, nav) ) = def_nav {
74
+ if exclude_tests && def. is_test ( db) {
75
+ continue ;
76
+ }
77
+
64
78
let range = sema. original_range ( name. syntax ( ) ) ;
65
79
calls. add ( nav. call_site , range. into ( ) ) ;
66
80
if let Some ( other) = nav. def_site {
@@ -75,6 +89,7 @@ pub(crate) fn incoming_calls(
75
89
76
90
pub ( crate ) fn outgoing_calls (
77
91
db : & RootDatabase ,
92
+ CallHierarchyConfig { exclude_tests } : CallHierarchyConfig ,
78
93
FilePosition { file_id, offset } : FilePosition ,
79
94
) -> Option < Vec < CallItem > > {
80
95
let sema = Semantics :: new ( db) ;
@@ -103,7 +118,12 @@ pub(crate) fn outgoing_calls(
103
118
let expr = call. expr ( ) ?;
104
119
let callable = sema. type_of_expr ( & expr) ?. original . as_callable ( db) ?;
105
120
match callable. kind ( ) {
106
- hir:: CallableKind :: Function ( it) => it. try_to_nav ( db) ,
121
+ hir:: CallableKind :: Function ( it) => {
122
+ if exclude_tests && it. is_test ( db) {
123
+ return None ;
124
+ }
125
+ it. try_to_nav ( db)
126
+ }
107
127
hir:: CallableKind :: TupleEnumVariant ( it) => it. try_to_nav ( db) ,
108
128
hir:: CallableKind :: TupleStruct ( it) => it. try_to_nav ( db) ,
109
129
_ => None ,
@@ -112,6 +132,9 @@ pub(crate) fn outgoing_calls(
112
132
}
113
133
ast:: CallableExpr :: MethodCall ( expr) => {
114
134
let function = sema. resolve_method_call ( & expr) ?;
135
+ if exclude_tests && function. is_test ( db) {
136
+ return None ;
137
+ }
115
138
function
116
139
. try_to_nav ( db)
117
140
. zip ( Some ( sema. original_range ( expr. name_ref ( ) ?. syntax ( ) ) ) )
@@ -149,6 +172,7 @@ mod tests {
149
172
use crate :: fixture;
150
173
151
174
fn check_hierarchy (
175
+ exclude_tests : bool ,
152
176
ra_fixture : & str ,
153
177
expected_nav : Expect ,
154
178
expected_incoming : Expect ,
@@ -172,18 +196,21 @@ mod tests {
172
196
let nav = navs. pop ( ) . unwrap ( ) ;
173
197
expected_nav. assert_eq ( & nav. debug_render ( ) ) ;
174
198
199
+ let config = crate :: CallHierarchyConfig { exclude_tests } ;
200
+
175
201
let item_pos =
176
202
FilePosition { file_id : nav. file_id , offset : nav. focus_or_full_range ( ) . start ( ) } ;
177
- let incoming_calls = analysis. incoming_calls ( item_pos) . unwrap ( ) . unwrap ( ) ;
203
+ let incoming_calls = analysis. incoming_calls ( config , item_pos) . unwrap ( ) . unwrap ( ) ;
178
204
expected_incoming. assert_eq ( & incoming_calls. into_iter ( ) . map ( debug_render) . join ( "\n " ) ) ;
179
205
180
- let outgoing_calls = analysis. outgoing_calls ( item_pos) . unwrap ( ) . unwrap ( ) ;
206
+ let outgoing_calls = analysis. outgoing_calls ( config , item_pos) . unwrap ( ) . unwrap ( ) ;
181
207
expected_outgoing. assert_eq ( & outgoing_calls. into_iter ( ) . map ( debug_render) . join ( "\n " ) ) ;
182
208
}
183
209
184
210
#[ test]
185
211
fn test_call_hierarchy_on_ref ( ) {
186
212
check_hierarchy (
213
+ false ,
187
214
r#"
188
215
//- /lib.rs
189
216
fn callee() {}
@@ -200,6 +227,7 @@ fn caller() {
200
227
#[ test]
201
228
fn test_call_hierarchy_on_def ( ) {
202
229
check_hierarchy (
230
+ false ,
203
231
r#"
204
232
//- /lib.rs
205
233
fn call$0ee() {}
@@ -216,6 +244,7 @@ fn caller() {
216
244
#[ test]
217
245
fn test_call_hierarchy_in_same_fn ( ) {
218
246
check_hierarchy (
247
+ false ,
219
248
r#"
220
249
//- /lib.rs
221
250
fn callee() {}
@@ -233,6 +262,7 @@ fn caller() {
233
262
#[ test]
234
263
fn test_call_hierarchy_in_different_fn ( ) {
235
264
check_hierarchy (
265
+ false ,
236
266
r#"
237
267
//- /lib.rs
238
268
fn callee() {}
@@ -255,6 +285,7 @@ fn caller2() {
255
285
#[ test]
256
286
fn test_call_hierarchy_in_tests_mod ( ) {
257
287
check_hierarchy (
288
+ false ,
258
289
r#"
259
290
//- /lib.rs cfg:test
260
291
fn callee() {}
@@ -283,6 +314,7 @@ mod tests {
283
314
#[ test]
284
315
fn test_call_hierarchy_in_different_files ( ) {
285
316
check_hierarchy (
317
+ false ,
286
318
r#"
287
319
//- /lib.rs
288
320
mod foo;
@@ -304,6 +336,7 @@ pub fn callee() {}
304
336
#[ test]
305
337
fn test_call_hierarchy_outgoing ( ) {
306
338
check_hierarchy (
339
+ false ,
307
340
r#"
308
341
//- /lib.rs
309
342
fn callee() {}
@@ -321,6 +354,7 @@ fn call$0er() {
321
354
#[ test]
322
355
fn test_call_hierarchy_outgoing_in_different_files ( ) {
323
356
check_hierarchy (
357
+ false ,
324
358
r#"
325
359
//- /lib.rs
326
360
mod foo;
@@ -342,6 +376,7 @@ pub fn callee() {}
342
376
#[ test]
343
377
fn test_call_hierarchy_incoming_outgoing ( ) {
344
378
check_hierarchy (
379
+ false ,
345
380
r#"
346
381
//- /lib.rs
347
382
fn caller1() {
@@ -365,6 +400,7 @@ fn caller3() {
365
400
#[ test]
366
401
fn test_call_hierarchy_issue_5103 ( ) {
367
402
check_hierarchy (
403
+ false ,
368
404
r#"
369
405
fn a() {
370
406
b()
@@ -382,6 +418,7 @@ fn main() {
382
418
) ;
383
419
384
420
check_hierarchy (
421
+ false ,
385
422
r#"
386
423
fn a() {
387
424
b$0()
@@ -402,6 +439,7 @@ fn main() {
402
439
#[ test]
403
440
fn test_call_hierarchy_in_macros_incoming ( ) {
404
441
check_hierarchy (
442
+ false ,
405
443
r#"
406
444
macro_rules! define {
407
445
($ident:ident) => {
@@ -423,6 +461,7 @@ fn caller() {
423
461
expect ! [ [ ] ] ,
424
462
) ;
425
463
check_hierarchy (
464
+ false ,
426
465
r#"
427
466
macro_rules! define {
428
467
($ident:ident) => {
@@ -448,6 +487,7 @@ fn caller() {
448
487
#[ test]
449
488
fn test_call_hierarchy_in_macros_outgoing ( ) {
450
489
check_hierarchy (
490
+ false ,
451
491
r#"
452
492
macro_rules! define {
453
493
($ident:ident) => {
@@ -473,6 +513,7 @@ fn caller$0() {
473
513
#[ test]
474
514
fn test_call_hierarchy_in_macros_incoming_different_files ( ) {
475
515
check_hierarchy (
516
+ false ,
476
517
r#"
477
518
//- /lib.rs
478
519
#[macro_use]
@@ -498,6 +539,7 @@ macro_rules! call {
498
539
expect ! [ [ ] ] ,
499
540
) ;
500
541
check_hierarchy (
542
+ false ,
501
543
r#"
502
544
//- /lib.rs
503
545
#[macro_use]
@@ -523,6 +565,7 @@ macro_rules! call {
523
565
expect ! [ [ ] ] ,
524
566
) ;
525
567
check_hierarchy (
568
+ false ,
526
569
r#"
527
570
//- /lib.rs
528
571
#[macro_use]
@@ -558,6 +601,7 @@ macro_rules! call {
558
601
#[ test]
559
602
fn test_call_hierarchy_in_macros_outgoing_different_files ( ) {
560
603
check_hierarchy (
604
+ false ,
561
605
r#"
562
606
//- /lib.rs
563
607
#[macro_use]
@@ -585,6 +629,7 @@ macro_rules! call {
585
629
expect ! [ [ ] ] ,
586
630
) ;
587
631
check_hierarchy (
632
+ false ,
588
633
r#"
589
634
//- /lib.rs
590
635
#[macro_use]
@@ -616,6 +661,7 @@ macro_rules! call {
616
661
#[ test]
617
662
fn test_trait_method_call_hierarchy ( ) {
618
663
check_hierarchy (
664
+ false ,
619
665
r#"
620
666
trait T1 {
621
667
fn call$0ee();
@@ -636,4 +682,64 @@ fn caller() {
636
682
expect ! [ [ ] ] ,
637
683
) ;
638
684
}
685
+
686
+ #[ test]
687
+ fn test_call_hierarchy_excluding_tests ( ) {
688
+ check_hierarchy (
689
+ false ,
690
+ r#"
691
+ fn main() {
692
+ f1();
693
+ }
694
+
695
+ fn f1$0() {
696
+ f2(); f3();
697
+ }
698
+
699
+ fn f2() {
700
+ f1(); f3();
701
+ }
702
+
703
+ #[test]
704
+ fn f3() {
705
+ f1(); f2();
706
+ }
707
+ "# ,
708
+ expect ! [ "f1 Function FileId(0) 25..52 28..30" ] ,
709
+ expect ! [ [ r#"
710
+ main Function FileId(0) 0..23 3..7 : FileId(0):16..18
711
+ f2 Function FileId(0) 54..81 57..59 : FileId(0):68..70
712
+ f3 Function FileId(0) 83..118 94..96 : FileId(0):105..107"# ] ] ,
713
+ expect ! [ [ r#"
714
+ f2 Function FileId(0) 54..81 57..59 : FileId(0):39..41
715
+ f3 Function FileId(0) 83..118 94..96 : FileId(0):45..47"# ] ] ,
716
+ ) ;
717
+
718
+ check_hierarchy (
719
+ true ,
720
+ r#"
721
+ fn main() {
722
+ f1();
723
+ }
724
+
725
+ fn f1$0() {
726
+ f2(); f3();
727
+ }
728
+
729
+ fn f2() {
730
+ f1(); f3();
731
+ }
732
+
733
+ #[test]
734
+ fn f3() {
735
+ f1(); f2();
736
+ }
737
+ "# ,
738
+ expect ! [ "f1 Function FileId(0) 25..52 28..30" ] ,
739
+ expect ! [ [ r#"
740
+ main Function FileId(0) 0..23 3..7 : FileId(0):16..18
741
+ f2 Function FileId(0) 54..81 57..59 : FileId(0):68..70"# ] ] ,
742
+ expect ! [ "f2 Function FileId(0) 54..81 57..59 : FileId(0):39..41" ] ,
743
+ ) ;
744
+ }
639
745
}
0 commit comments