]> git.lizzy.rs Git - rust.git/blobdiff - crates/rust-analyzer/src/cli/load_cargo.rs
clippy::redudant_borrow
[rust.git] / crates / rust-analyzer / src / cli / load_cargo.rs
index 16ccab7817f14d577378ec1caecddd5dc38926d9..b5f5519b43ef2b856fec20c3f5548cec07c04b64 100644 (file)
@@ -4,26 +4,41 @@
 
 use anyhow::Result;
 use crossbeam_channel::{unbounded, Receiver};
+use hir::db::DefDatabase;
 use ide::{AnalysisHost, Change};
 use ide_db::base_db::CrateGraph;
-use project_model::{CargoConfig, ProcMacroClient, ProjectManifest, ProjectWorkspace};
+use project_model::{
+    BuildDataCollector, CargoConfig, ProcMacroClient, ProjectManifest, ProjectWorkspace,
+};
 use vfs::{loader::Handle, AbsPath, AbsPathBuf};
 
 use crate::reload::{ProjectFolders, SourceRootConfig};
 
-pub fn load_cargo(
+pub(crate) struct LoadCargoConfig {
+    pub(crate) load_out_dirs_from_check: bool,
+    pub(crate) wrap_rustc: bool,
+    pub(crate) with_proc_macro: bool,
+    pub(crate) prefill_caches: bool,
+}
+
+pub(crate) fn load_workspace_at(
     root: &Path,
-    load_out_dirs_from_check: bool,
-    with_proc_macro: bool,
-) -> Result<(AnalysisHost, vfs::Vfs)> {
+    cargo_config: &CargoConfig,
+    load_config: &LoadCargoConfig,
+    progress: &dyn Fn(String),
+) -> Result<(AnalysisHost, vfs::Vfs, Option<ProcMacroClient>)> {
     let root = AbsPathBuf::assert(std::env::current_dir()?.join(root));
     let root = ProjectManifest::discover_single(&root)?;
-    let ws = ProjectWorkspace::load(
-        root,
-        &CargoConfig { load_out_dirs_from_check, ..Default::default() },
-        &|_| {},
-    )?;
+    let workspace = ProjectWorkspace::load(root, cargo_config, progress)?;
+
+    load_workspace(workspace, load_config, progress)
+}
 
+fn load_workspace(
+    ws: ProjectWorkspace,
+    config: &LoadCargoConfig,
+    progress: &dyn Fn(String),
+) -> Result<(AnalysisHost, vfs::Vfs, Option<ProcMacroClient>)> {
     let (sender, receiver) = unbounded();
     let mut vfs = vfs::Vfs::default();
     let mut loader = {
@@ -32,29 +47,50 @@ pub fn load_cargo(
         Box::new(loader)
     };
 
-    let proc_macro_client = if with_proc_macro {
+    let proc_macro_client = if config.with_proc_macro {
         let path = std::env::current_exe()?;
         Some(ProcMacroClient::extern_process(path, &["proc-macro"]).unwrap())
     } else {
         None
     };
 
-    let crate_graph = ws.to_crate_graph(proc_macro_client.as_ref(), &mut |path: &AbsPath| {
-        let contents = loader.load_sync(path);
-        let path = vfs::VfsPath::from(path.to_path_buf());
-        vfs.set_file_contents(path.clone(), contents);
-        vfs.file_id(&path)
-    });
+    let build_data = if config.load_out_dirs_from_check {
+        let mut collector = BuildDataCollector::new(config.wrap_rustc);
+        ws.collect_build_data_configs(&mut collector);
+        Some(collector.collect(progress)?)
+    } else {
+        None
+    };
 
-    let project_folders = ProjectFolders::new(&[ws]);
-    loader.set_config(vfs::loader::Config { load: project_folders.load, watch: vec![] });
+    let crate_graph = ws.to_crate_graph(
+        build_data.as_ref(),
+        proc_macro_client.as_ref(),
+        &mut |path: &AbsPath| {
+            let contents = loader.load_sync(path);
+            let path = vfs::VfsPath::from(path.to_path_buf());
+            vfs.set_file_contents(path.clone(), contents);
+            vfs.file_id(&path)
+        },
+    );
+
+    let project_folders = ProjectFolders::new(&[ws], &[], build_data.as_ref());
+    loader.set_config(vfs::loader::Config {
+        load: project_folders.load,
+        watch: vec![],
+        version: 0,
+    });
 
     log::debug!("crate graph: {:?}", crate_graph);
-    let host = load(crate_graph, project_folders.source_root_config, &mut vfs, &receiver);
-    Ok((host, vfs))
+    let host =
+        load_crate_graph(crate_graph, project_folders.source_root_config, &mut vfs, &receiver);
+
+    if config.prefill_caches {
+        host.analysis().prime_caches(|_| {})?;
+    }
+    Ok((host, vfs, proc_macro_client))
 }
 
-fn load(
+fn load_crate_graph(
     crate_graph: CrateGraph,
     source_root_config: SourceRootConfig,
     vfs: &mut vfs::Vfs,
@@ -64,10 +100,12 @@ fn load(
     let mut host = AnalysisHost::new(lru_cap);
     let mut analysis_change = Change::new();
 
+    host.raw_database_mut().set_enable_proc_attr_macros(true);
+
     // wait until Vfs has loaded all roots
     for task in receiver {
         match task {
-            vfs::loader::Message::Progress { n_done, n_total } => {
+            vfs::loader::Message::Progress { n_done, n_total, config_version: _ } => {
                 if n_done == n_total {
                     break;
                 }
@@ -88,7 +126,7 @@ fn load(
             }
         }
     }
-    let source_roots = source_root_config.partition(&vfs);
+    let source_roots = source_root_config.partition(vfs);
     analysis_change.set_roots(source_roots);
 
     analysis_change.set_crate_graph(crate_graph);
@@ -104,11 +142,22 @@ mod tests {
     use hir::Crate;
 
     #[test]
-    fn test_loading_rust_analyzer() {
+    fn test_loading_rust_analyzer() -> Result<()> {
         let path = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap().parent().unwrap();
-        let (host, _vfs) = load_cargo(path, false, false).unwrap();
+        let cargo_config = Default::default();
+        let load_cargo_config = LoadCargoConfig {
+            load_out_dirs_from_check: false,
+            wrap_rustc: false,
+            with_proc_macro: false,
+            prefill_caches: false,
+        };
+        let (host, _vfs, _proc_macro) =
+            load_workspace_at(path, &cargo_config, &load_cargo_config, &|_| {})?;
+
         let n_crates = Crate::all(host.raw_database()).len();
         // RA has quite a few crates, but the exact count doesn't matter
         assert!(n_crates > 20);
+
+        Ok(())
     }
 }