1- use indexmap:: IndexMap ;
1+ use crate_feature_graph:: WorkspaceGraph ;
2+ use indexmap:: { IndexMap , IndexSet } ;
23use log:: trace;
34use rustc_hir:: {
45 def:: DefKind ,
5- def_id:: { CrateNum , DefId } ,
6+ def_id:: { CrateNum , DefId , LOCAL_CRATE } ,
67} ;
78use rustc_middle:: ty:: TyCtxt ;
89
@@ -42,6 +43,7 @@ impl std::fmt::Debug for ImportPathElement {
4243pub ( crate ) struct ImportPathFinder < ' tcx > {
4344 pub ( crate ) tcx : TyCtxt < ' tcx > ,
4445 pub ( crate ) cache : IndexMap < DefId , Vec < Vec < ImportPathElement > > > ,
46+ pub ( crate ) crawled_crates : IndexSet < CrateNum > ,
4547 pub ( crate ) include_private_paths : bool ,
4648 pub ( crate ) import_path_processor : Option < Box < dyn Fn ( & str ) -> String > > ,
4749}
@@ -58,18 +60,59 @@ impl<'tcx> ImportPathFinder<'tcx> {
5860 cache : Default :: default ( ) ,
5961 include_private_paths,
6062 import_path_processor,
63+ crawled_crates : Default :: default ( ) ,
6164 }
6265 }
6366
64- pub ( crate ) fn crawl_crate ( & mut self , crate_num : CrateNum ) {
65- self . crawl_module (
66- crate_num. as_def_id ( ) ,
67- & [ ImportPathElement :: Crate ( crate_num) ] ,
68- ) ;
69- // sort by length of path, shortest wins
70- self . cache . iter_mut ( ) . for_each ( |( _, paths) | {
71- paths. sort_by_key ( |a| a. len ( ) ) ;
72- } ) ;
67+ /// Sort the import paths according to some heuristics, so best ones are first
68+ pub ( crate ) fn stable_sort ( & mut self , graph : & WorkspaceGraph ) {
69+ for ( _, values) in & mut self . cache {
70+ values. sort_by_cached_key ( |k| Self :: path_score ( k, graph, self . tcx ) ) ;
71+ }
72+ }
73+
74+ pub ( crate ) fn crawled_items_in_crate ( & self , krate : CrateNum ) -> impl Iterator < Item = DefId > {
75+ self . cache
76+ . keys ( )
77+ . filter_map ( move |i| ( i. krate == krate) . then_some ( * i) )
78+ }
79+
80+ /// Higher is worse
81+ fn path_score ( path : & [ ImportPathElement ] , graph : & WorkspaceGraph , tcx : TyCtxt ) -> usize {
82+ let length_score = path. len ( ) ;
83+ // crate proximity score
84+ let mut crate_proximity_score = 0 ;
85+ if let Some ( ImportPathElement :: Crate ( crate_num) ) = path. first ( ) {
86+ let crate_name = tcx. crate_name ( * crate_num) ;
87+ let is_std_or_core = crate_name. as_str ( ) == "std" || crate_name. as_str ( ) == "core" ;
88+ let not_in_workspace = !graph
89+ . all_enabled_workspace_crates ( )
90+ . iter ( )
91+ . any ( |c| c. as_ref ( ) == crate_name. as_str ( ) ) ;
92+
93+ let is_not_local_crate = if & LOCAL_CRATE != crate_num && !is_std_or_core {
94+ 10
95+ } else {
96+ 0
97+ } ;
98+ let is_not_in_workspace = if not_in_workspace && !is_std_or_core {
99+ 10
100+ } else {
101+ 0
102+ } ;
103+ crate_proximity_score = is_not_local_crate + is_not_in_workspace;
104+ }
105+ length_score + crate_proximity_score
106+ }
107+
108+ pub ( crate ) fn ensure_crate_crawled ( & mut self , crate_num : CrateNum ) {
109+ if !self . crawled_crates . contains ( & crate_num) {
110+ self . crawl_module (
111+ crate_num. as_def_id ( ) ,
112+ & [ ImportPathElement :: Crate ( crate_num) ] ,
113+ ) ;
114+ self . crawled_crates . insert ( crate_num) ;
115+ }
73116 }
74117
75118 fn crawl_module ( & mut self , did : DefId , frontier : & [ ImportPathElement ] ) {
0 commit comments