@@ -21,9 +21,10 @@ pub fn find_path(
2121 item : ItemInNs ,
2222 from : ModuleId ,
2323 prefer_no_std : bool ,
24+ prefer_prelude : bool ,
2425) -> Option < ModPath > {
2526 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 )
2728}
2829
2930pub fn find_path_prefixed (
@@ -32,9 +33,10 @@ pub fn find_path_prefixed(
3233 from : ModuleId ,
3334 prefix_kind : PrefixKind ,
3435 prefer_no_std : bool ,
36+ prefer_prelude : bool ,
3537) -> Option < ModPath > {
3638 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 )
3840}
3941
4042#[ derive( Copy , Clone , Debug ) ]
@@ -88,6 +90,7 @@ fn find_path_inner(
8890 from : ModuleId ,
8991 prefixed : Option < PrefixKind > ,
9092 prefer_no_std : bool ,
93+ prefer_prelude : bool ,
9194) -> Option < ModPath > {
9295 // - if the item is a builtin, it's in scope
9396 if let ItemInNs :: Types ( ModuleDefId :: BuiltinType ( builtin) ) = item {
@@ -109,6 +112,7 @@ fn find_path_inner(
109112 MAX_PATH_LEN ,
110113 prefixed,
111114 prefer_no_std || db. crate_supports_no_std ( crate_root. krate ) ,
115+ prefer_prelude,
112116 )
113117 . map ( |( item, _) | item) ;
114118 }
@@ -134,6 +138,7 @@ fn find_path_inner(
134138 from,
135139 prefixed,
136140 prefer_no_std,
141+ prefer_prelude,
137142 ) {
138143 let data = db. enum_data ( variant. parent ) ;
139144 path. push_segment ( data. variants [ variant. local_id ] . name . clone ( ) ) ;
@@ -156,6 +161,7 @@ fn find_path_inner(
156161 from,
157162 prefixed,
158163 prefer_no_std || db. crate_supports_no_std ( crate_root. krate ) ,
164+ prefer_prelude,
159165 scope_name,
160166 )
161167 . map ( |( item, _) | item)
@@ -171,6 +177,7 @@ fn find_path_for_module(
171177 max_len : usize ,
172178 prefixed : Option < PrefixKind > ,
173179 prefer_no_std : bool ,
180+ prefer_prelude : bool ,
174181) -> Option < ( ModPath , Stability ) > {
175182 if max_len == 0 {
176183 return None ;
@@ -236,6 +243,7 @@ fn find_path_for_module(
236243 from,
237244 prefixed,
238245 prefer_no_std,
246+ prefer_prelude,
239247 scope_name,
240248 )
241249}
@@ -316,6 +324,7 @@ fn calculate_best_path(
316324 from : ModuleId ,
317325 mut prefixed : Option < PrefixKind > ,
318326 prefer_no_std : bool ,
327+ prefer_prelude : bool ,
319328 scope_name : Option < Name > ,
320329) -> Option < ( ModPath , Stability ) > {
321330 if max_len <= 1 {
@@ -351,11 +360,14 @@ fn calculate_best_path(
351360 best_path_len - 1 ,
352361 prefixed,
353362 prefer_no_std,
363+ prefer_prelude,
354364 ) {
355365 path. 0 . push_segment ( name) ;
356366
357367 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+ }
359371 None => path,
360372 } ;
361373 best_path_len = new_path. 0 . len ( ) ;
@@ -388,6 +400,7 @@ fn calculate_best_path(
388400 max_len - 1 ,
389401 prefixed,
390402 prefer_no_std,
403+ prefer_prelude,
391404 ) else {
392405 continue ;
393406 } ;
@@ -400,7 +413,9 @@ fn calculate_best_path(
400413 ) ;
401414
402415 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+ }
404419 None => path_with_stab,
405420 } ;
406421 update_best_path ( & mut best_path, new_path_with_stab) ;
@@ -421,17 +436,39 @@ fn calculate_best_path(
421436 }
422437}
423438
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.
424442fn 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 ) ,
427445 prefer_no_std : bool ,
446+ prefer_prelude : bool ,
428447) -> ( ModPath , Stability ) {
429- match ( old_path . 1 , new_path . 1 ) {
448+ match ( old_stability , new_stability ) {
430449 ( Stable , Unstable ) => return old_path,
431450 ( Unstable , Stable ) => return new_path,
432451 _ => { }
433452 }
434453 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+
435472 match ( old_path. 0 . segments ( ) . first ( ) , new_path. 0 . segments ( ) . first ( ) ) {
436473 ( Some ( old) , Some ( new) ) if STD_CRATES . contains ( old) && STD_CRATES . contains ( new) => {
437474 let rank = match prefer_no_std {
@@ -452,23 +489,11 @@ fn select_best_path(
452489 let orank = rank ( old) ;
453490 match nrank. cmp ( & orank) {
454491 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) ,
462493 Ordering :: Greater => new_path,
463494 }
464495 }
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) ,
472497 }
473498}
474499
@@ -571,7 +596,13 @@ mod tests {
571596 /// `code` needs to contain a cursor marker; checks that `find_path` for the
572597 /// item the `path` refers to returns that same path when called from the
573598 /// 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+ ) {
575606 let ( db, pos) = TestDB :: with_position ( ra_fixture) ;
576607 let module = db. module_at_position ( pos) ;
577608 let parsed_path_file = syntax:: SourceFile :: parse ( & format ! ( "use {path};" ) ) ;
@@ -590,10 +621,16 @@ mod tests {
590621 )
591622 . 0
592623 . 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+ ) ;
597634 assert_eq ! ( found_path, Some ( mod_path) , "on kind: {prefix_kind:?}" ) ;
598635 }
599636
@@ -604,10 +641,23 @@ mod tests {
604641 absolute : & str ,
605642 self_prefixed : & str ,
606643 ) {
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 ) ;
611661 }
612662
613663 #[ test]
@@ -1422,4 +1472,34 @@ pub mod error {
14221472 "std::error::Error" ,
14231473 ) ;
14241474 }
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+ }
14251505}
0 commit comments