11//! Loads a Cargo project into a static instance of analysis, without support
22//! for incorporating changes.
33
4- use std:: path:: Path ;
4+ use std:: path:: { Path , PathBuf } ;
55
66use anyhow:: Result ;
77use crossbeam_channel:: { unbounded, Receiver } ;
8- use ra_db:: { CrateGraph , FileId , SourceRootId } ;
8+ use ra_db:: { ExternSourceId , FileId , SourceRootId } ;
99use ra_ide:: { AnalysisChange , AnalysisHost } ;
10- use ra_project_model:: { get_rustc_cfg_options, PackageRoot , ProjectWorkspace } ;
10+ use ra_project_model:: { get_rustc_cfg_options, CargoFeatures , PackageRoot , ProjectWorkspace } ;
1111use ra_vfs:: { RootEntry , Vfs , VfsChange , VfsTask , Watch } ;
1212use rustc_hash:: { FxHashMap , FxHashSet } ;
1313
@@ -22,10 +22,21 @@ fn vfs_root_to_id(r: ra_vfs::VfsRoot) -> SourceRootId {
2222
2323pub ( crate ) fn load_cargo (
2424 root : & Path ,
25+ load_out_dirs_from_check : bool ,
2526) -> Result < ( AnalysisHost , FxHashMap < SourceRootId , PackageRoot > ) > {
2627 let root = std:: env:: current_dir ( ) ?. join ( root) ;
27- let ws = ProjectWorkspace :: discover ( root. as_ref ( ) , & Default :: default ( ) ) ?;
28- let project_roots = ws. to_roots ( ) ;
28+ let ws = ProjectWorkspace :: discover (
29+ root. as_ref ( ) ,
30+ & CargoFeatures { load_out_dirs_from_check, ..Default :: default ( ) } ,
31+ ) ?;
32+
33+ let mut extern_dirs = FxHashSet :: default ( ) ;
34+ extern_dirs. extend ( ws. out_dirs ( ) ) ;
35+
36+ let mut project_roots = ws. to_roots ( ) ;
37+ project_roots
38+ . extend ( extern_dirs. iter ( ) . map ( |path| PackageRoot :: new ( path. to_path_buf ( ) , false ) ) ) ;
39+
2940 let ( sender, receiver) = unbounded ( ) ;
3041 let sender = Box :: new ( move |t| sender. send ( t) . unwrap ( ) ) ;
3142 let ( mut vfs, roots) = Vfs :: new (
@@ -44,25 +55,6 @@ pub(crate) fn load_cargo(
4455 Watch ( false ) ,
4556 ) ;
4657
47- // FIXME: cfg options?
48- let default_cfg_options = {
49- let mut opts = get_rustc_cfg_options ( ) ;
50- opts. insert_atom ( "test" . into ( ) ) ;
51- opts. insert_atom ( "debug_assertion" . into ( ) ) ;
52- opts
53- } ;
54-
55- // FIXME: outdirs?
56- let extern_source_roots = FxHashMap :: default ( ) ;
57-
58- let crate_graph =
59- ws. to_crate_graph ( & default_cfg_options, & extern_source_roots, & mut |path : & Path | {
60- let vfs_file = vfs. load ( path) ;
61- log:: debug!( "vfs file {:?} -> {:?}" , path, vfs_file) ;
62- vfs_file. map ( vfs_file_to_id)
63- } ) ;
64- log:: debug!( "crate graph: {:?}" , crate_graph) ;
65-
6658 let source_roots = roots
6759 . iter ( )
6860 . map ( |& vfs_root| {
@@ -75,23 +67,24 @@ pub(crate) fn load_cargo(
7567 ( source_root_id, project_root)
7668 } )
7769 . collect :: < FxHashMap < _ , _ > > ( ) ;
78- let host = load ( & source_roots, crate_graph , & mut vfs, receiver) ;
70+ let host = load ( & source_roots, ws , & mut vfs, receiver, extern_dirs ) ;
7971 Ok ( ( host, source_roots) )
8072}
8173
8274pub ( crate ) fn load (
8375 source_roots : & FxHashMap < SourceRootId , PackageRoot > ,
84- crate_graph : CrateGraph ,
76+ ws : ProjectWorkspace ,
8577 vfs : & mut Vfs ,
8678 receiver : Receiver < VfsTask > ,
79+ extern_dirs : FxHashSet < PathBuf > ,
8780) -> AnalysisHost {
8881 let lru_cap = std:: env:: var ( "RA_LRU_CAP" ) . ok ( ) . and_then ( |it| it. parse :: < usize > ( ) . ok ( ) ) ;
8982 let mut host = AnalysisHost :: new ( lru_cap) ;
9083 let mut analysis_change = AnalysisChange :: new ( ) ;
91- analysis_change. set_crate_graph ( crate_graph) ;
9284
9385 // wait until Vfs has loaded all roots
9486 let mut roots_loaded = FxHashSet :: default ( ) ;
87+ let mut extern_source_roots = FxHashMap :: default ( ) ;
9588 for task in receiver {
9689 vfs. handle_task ( task) ;
9790 let mut done = false ;
@@ -111,6 +104,11 @@ pub(crate) fn load(
111104 source_roots[ & source_root_id] . path ( ) . display ( ) . to_string ( ) ,
112105 ) ;
113106
107+ let vfs_root_path = vfs. root2path ( root) ;
108+ if extern_dirs. contains ( & vfs_root_path) {
109+ extern_source_roots. insert ( vfs_root_path, ExternSourceId ( root. 0 ) ) ;
110+ }
111+
114112 let mut file_map = FxHashMap :: default ( ) ;
115113 for ( vfs_file, path, text) in files {
116114 let file_id = vfs_file_to_id ( vfs_file) ;
@@ -137,6 +135,23 @@ pub(crate) fn load(
137135 }
138136 }
139137
138+ // FIXME: cfg options?
139+ let default_cfg_options = {
140+ let mut opts = get_rustc_cfg_options ( ) ;
141+ opts. insert_atom ( "test" . into ( ) ) ;
142+ opts. insert_atom ( "debug_assertion" . into ( ) ) ;
143+ opts
144+ } ;
145+
146+ let crate_graph =
147+ ws. to_crate_graph ( & default_cfg_options, & extern_source_roots, & mut |path : & Path | {
148+ let vfs_file = vfs. load ( path) ;
149+ log:: debug!( "vfs file {:?} -> {:?}" , path, vfs_file) ;
150+ vfs_file. map ( vfs_file_to_id)
151+ } ) ;
152+ log:: debug!( "crate graph: {:?}" , crate_graph) ;
153+ analysis_change. set_crate_graph ( crate_graph) ;
154+
140155 host. apply_change ( analysis_change) ;
141156 host
142157}
@@ -150,7 +165,7 @@ mod tests {
150165 #[ test]
151166 fn test_loading_rust_analyzer ( ) {
152167 let path = Path :: new ( env ! ( "CARGO_MANIFEST_DIR" ) ) . parent ( ) . unwrap ( ) . parent ( ) . unwrap ( ) ;
153- let ( host, _roots) = load_cargo ( path) . unwrap ( ) ;
168+ let ( host, _roots) = load_cargo ( path, false ) . unwrap ( ) ;
154169 let n_crates = Crate :: all ( host. raw_database ( ) ) . len ( ) ;
155170 // RA has quite a few crates, but the exact count doesn't matter
156171 assert ! ( n_crates > 20 ) ;
0 commit comments