@@ -21,9 +21,10 @@ pub fn find_path(
21
21
item : ItemInNs ,
22
22
from : ModuleId ,
23
23
prefer_no_std : bool ,
24
+ prefer_prelude : bool ,
24
25
) -> Option < ModPath > {
25
26
let _p = profile:: span ( "find_path" ) ;
26
- find_path_inner ( db, item, from, None , prefer_no_std)
27
+ find_path_inner ( db, item, from, None , prefer_no_std, prefer_prelude )
27
28
}
28
29
29
30
pub fn find_path_prefixed (
@@ -32,9 +33,10 @@ pub fn find_path_prefixed(
32
33
from : ModuleId ,
33
34
prefix_kind : PrefixKind ,
34
35
prefer_no_std : bool ,
36
+ prefer_prelude : bool ,
35
37
) -> Option < ModPath > {
36
38
let _p = profile:: span ( "find_path_prefixed" ) ;
37
- find_path_inner ( db, item, from, Some ( prefix_kind) , prefer_no_std)
39
+ find_path_inner ( db, item, from, Some ( prefix_kind) , prefer_no_std, prefer_prelude )
38
40
}
39
41
40
42
#[ derive( Copy , Clone , Debug ) ]
@@ -88,6 +90,7 @@ fn find_path_inner(
88
90
from : ModuleId ,
89
91
prefixed : Option < PrefixKind > ,
90
92
prefer_no_std : bool ,
93
+ prefer_prelude : bool ,
91
94
) -> Option < ModPath > {
92
95
// - if the item is a builtin, it's in scope
93
96
if let ItemInNs :: Types ( ModuleDefId :: BuiltinType ( builtin) ) = item {
@@ -109,6 +112,7 @@ fn find_path_inner(
109
112
MAX_PATH_LEN ,
110
113
prefixed,
111
114
prefer_no_std || db. crate_supports_no_std ( crate_root. krate ) ,
115
+ prefer_prelude,
112
116
)
113
117
. map ( |( item, _) | item) ;
114
118
}
@@ -134,6 +138,7 @@ fn find_path_inner(
134
138
from,
135
139
prefixed,
136
140
prefer_no_std,
141
+ prefer_prelude,
137
142
) {
138
143
let data = db. enum_data ( variant. parent ) ;
139
144
path. push_segment ( data. variants [ variant. local_id ] . name . clone ( ) ) ;
@@ -156,6 +161,7 @@ fn find_path_inner(
156
161
from,
157
162
prefixed,
158
163
prefer_no_std || db. crate_supports_no_std ( crate_root. krate ) ,
164
+ prefer_prelude,
159
165
scope_name,
160
166
)
161
167
. map ( |( item, _) | item)
@@ -171,6 +177,7 @@ fn find_path_for_module(
171
177
max_len : usize ,
172
178
prefixed : Option < PrefixKind > ,
173
179
prefer_no_std : bool ,
180
+ prefer_prelude : bool ,
174
181
) -> Option < ( ModPath , Stability ) > {
175
182
if max_len == 0 {
176
183
return None ;
@@ -236,6 +243,7 @@ fn find_path_for_module(
236
243
from,
237
244
prefixed,
238
245
prefer_no_std,
246
+ prefer_prelude,
239
247
scope_name,
240
248
)
241
249
}
@@ -316,6 +324,7 @@ fn calculate_best_path(
316
324
from : ModuleId ,
317
325
mut prefixed : Option < PrefixKind > ,
318
326
prefer_no_std : bool ,
327
+ prefer_prelude : bool ,
319
328
scope_name : Option < Name > ,
320
329
) -> Option < ( ModPath , Stability ) > {
321
330
if max_len <= 1 {
@@ -351,11 +360,14 @@ fn calculate_best_path(
351
360
best_path_len - 1 ,
352
361
prefixed,
353
362
prefer_no_std,
363
+ prefer_prelude,
354
364
) {
355
365
path. 0 . push_segment ( name) ;
356
366
357
367
let new_path = match best_path. take ( ) {
358
- Some ( best_path) => select_best_path ( best_path, path, prefer_no_std) ,
368
+ Some ( best_path) => {
369
+ select_best_path ( best_path, path, prefer_no_std, prefer_prelude)
370
+ }
359
371
None => path,
360
372
} ;
361
373
best_path_len = new_path. 0 . len ( ) ;
@@ -388,6 +400,7 @@ fn calculate_best_path(
388
400
max_len - 1 ,
389
401
prefixed,
390
402
prefer_no_std,
403
+ prefer_prelude,
391
404
) else {
392
405
continue ;
393
406
} ;
@@ -400,7 +413,9 @@ fn calculate_best_path(
400
413
) ;
401
414
402
415
let new_path_with_stab = match best_path. take ( ) {
403
- Some ( best_path) => select_best_path ( best_path, path_with_stab, prefer_no_std) ,
416
+ Some ( best_path) => {
417
+ select_best_path ( best_path, path_with_stab, prefer_no_std, prefer_prelude)
418
+ }
404
419
None => path_with_stab,
405
420
} ;
406
421
update_best_path ( & mut best_path, new_path_with_stab) ;
@@ -421,17 +436,39 @@ fn calculate_best_path(
421
436
}
422
437
}
423
438
439
+ /// Select the best (most relevant) path between two paths.
440
+ /// This accounts for stability, path length whether std should be chosen over alloc/core paths as
441
+ /// well as ignoring prelude like paths or not.
424
442
fn select_best_path (
425
- old_path : ( ModPath , Stability ) ,
426
- new_path : ( ModPath , Stability ) ,
443
+ old_path @ ( _ , old_stability ) : ( ModPath , Stability ) ,
444
+ new_path @ ( _ , new_stability ) : ( ModPath , Stability ) ,
427
445
prefer_no_std : bool ,
446
+ prefer_prelude : bool ,
428
447
) -> ( ModPath , Stability ) {
429
- match ( old_path . 1 , new_path . 1 ) {
448
+ match ( old_stability , new_stability ) {
430
449
( Stable , Unstable ) => return old_path,
431
450
( Unstable , Stable ) => return new_path,
432
451
_ => { }
433
452
}
434
453
const STD_CRATES : [ Name ; 3 ] = [ known:: std, known:: core, known:: alloc] ;
454
+
455
+ let choose = |new_path : ( ModPath , _ ) , old_path : ( ModPath , _ ) | {
456
+ let new_has_prelude = new_path. 0 . segments ( ) . iter ( ) . any ( |seg| seg == & known:: prelude) ;
457
+ let old_has_prelude = old_path. 0 . segments ( ) . iter ( ) . any ( |seg| seg == & known:: prelude) ;
458
+ match ( new_has_prelude, old_has_prelude, prefer_prelude) {
459
+ ( true , false , true ) | ( false , true , false ) => new_path,
460
+ ( true , false , false ) | ( false , true , true ) => old_path,
461
+ // no prelude difference in the paths, so pick the smaller one
462
+ ( true , true , _) | ( false , false , _) => {
463
+ if new_path. 0 . len ( ) < old_path. 0 . len ( ) {
464
+ new_path
465
+ } else {
466
+ old_path
467
+ }
468
+ }
469
+ }
470
+ } ;
471
+
435
472
match ( old_path. 0 . segments ( ) . first ( ) , new_path. 0 . segments ( ) . first ( ) ) {
436
473
( Some ( old) , Some ( new) ) if STD_CRATES . contains ( old) && STD_CRATES . contains ( new) => {
437
474
let rank = match prefer_no_std {
@@ -452,23 +489,11 @@ fn select_best_path(
452
489
let orank = rank ( old) ;
453
490
match nrank. cmp ( & orank) {
454
491
Ordering :: Less => old_path,
455
- Ordering :: Equal => {
456
- if new_path. 0 . len ( ) < old_path. 0 . len ( ) {
457
- new_path
458
- } else {
459
- old_path
460
- }
461
- }
492
+ Ordering :: Equal => choose ( new_path, old_path) ,
462
493
Ordering :: Greater => new_path,
463
494
}
464
495
}
465
- _ => {
466
- if new_path. 0 . len ( ) < old_path. 0 . len ( ) {
467
- new_path
468
- } else {
469
- old_path
470
- }
471
- }
496
+ _ => choose ( new_path, old_path) ,
472
497
}
473
498
}
474
499
@@ -571,7 +596,13 @@ mod tests {
571
596
/// `code` needs to contain a cursor marker; checks that `find_path` for the
572
597
/// item the `path` refers to returns that same path when called from the
573
598
/// module the cursor is in.
574
- fn check_found_path_ ( ra_fixture : & str , path : & str , prefix_kind : Option < PrefixKind > ) {
599
+ #[ track_caller]
600
+ fn check_found_path_ (
601
+ ra_fixture : & str ,
602
+ path : & str ,
603
+ prefix_kind : Option < PrefixKind > ,
604
+ prefer_prelude : bool ,
605
+ ) {
575
606
let ( db, pos) = TestDB :: with_position ( ra_fixture) ;
576
607
let module = db. module_at_position ( pos) ;
577
608
let parsed_path_file = syntax:: SourceFile :: parse ( & format ! ( "use {path};" ) ) ;
@@ -590,10 +621,16 @@ mod tests {
590
621
)
591
622
. 0
592
623
. take_types ( )
593
- . unwrap ( ) ;
594
-
595
- let found_path =
596
- find_path_inner ( & db, ItemInNs :: Types ( resolved) , module, prefix_kind, false ) ;
624
+ . expect ( "path does not resolve to a type" ) ;
625
+
626
+ let found_path = find_path_inner (
627
+ & db,
628
+ ItemInNs :: Types ( resolved) ,
629
+ module,
630
+ prefix_kind,
631
+ false ,
632
+ prefer_prelude,
633
+ ) ;
597
634
assert_eq ! ( found_path, Some ( mod_path) , "on kind: {prefix_kind:?}" ) ;
598
635
}
599
636
@@ -604,10 +641,23 @@ mod tests {
604
641
absolute : & str ,
605
642
self_prefixed : & str ,
606
643
) {
607
- check_found_path_ ( ra_fixture, unprefixed, None ) ;
608
- check_found_path_ ( ra_fixture, prefixed, Some ( PrefixKind :: Plain ) ) ;
609
- check_found_path_ ( ra_fixture, absolute, Some ( PrefixKind :: ByCrate ) ) ;
610
- check_found_path_ ( ra_fixture, self_prefixed, Some ( PrefixKind :: BySelf ) ) ;
644
+ check_found_path_ ( ra_fixture, unprefixed, None , false ) ;
645
+ check_found_path_ ( ra_fixture, prefixed, Some ( PrefixKind :: Plain ) , false ) ;
646
+ check_found_path_ ( ra_fixture, absolute, Some ( PrefixKind :: ByCrate ) , false ) ;
647
+ check_found_path_ ( ra_fixture, self_prefixed, Some ( PrefixKind :: BySelf ) , false ) ;
648
+ }
649
+
650
+ fn check_found_path_prelude (
651
+ ra_fixture : & str ,
652
+ unprefixed : & str ,
653
+ prefixed : & str ,
654
+ absolute : & str ,
655
+ self_prefixed : & str ,
656
+ ) {
657
+ check_found_path_ ( ra_fixture, unprefixed, None , true ) ;
658
+ check_found_path_ ( ra_fixture, prefixed, Some ( PrefixKind :: Plain ) , true ) ;
659
+ check_found_path_ ( ra_fixture, absolute, Some ( PrefixKind :: ByCrate ) , true ) ;
660
+ check_found_path_ ( ra_fixture, self_prefixed, Some ( PrefixKind :: BySelf ) , true ) ;
611
661
}
612
662
613
663
#[ test]
@@ -1422,4 +1472,34 @@ pub mod error {
1422
1472
"std::error::Error" ,
1423
1473
) ;
1424
1474
}
1475
+
1476
+ #[ test]
1477
+ fn respects_prelude_setting ( ) {
1478
+ let ra_fixture = r#"
1479
+ //- /main.rs crate:main deps:krate
1480
+ $0
1481
+ //- /krate.rs crate:krate
1482
+ pub mod prelude {
1483
+ pub use crate::foo::*;
1484
+ }
1485
+
1486
+ pub mod foo {
1487
+ pub struct Foo;
1488
+ }
1489
+ "# ;
1490
+ check_found_path (
1491
+ ra_fixture,
1492
+ "krate::foo::Foo" ,
1493
+ "krate::foo::Foo" ,
1494
+ "krate::foo::Foo" ,
1495
+ "krate::foo::Foo" ,
1496
+ ) ;
1497
+ check_found_path_prelude (
1498
+ ra_fixture,
1499
+ "krate::prelude::Foo" ,
1500
+ "krate::prelude::Foo" ,
1501
+ "krate::prelude::Foo" ,
1502
+ "krate::prelude::Foo" ,
1503
+ ) ;
1504
+ }
1425
1505
}
0 commit comments