rust/crates/rust-analyzer/src/cli/load_cargo.rs

115 lines
3.7 KiB
Rust
Raw Normal View History

2020-02-18 11:11:32 +00:00
//! Loads a Cargo project into a static instance of analysis, without support
//! for incorporating changes.
2020-06-24 13:52:07 +00:00
use std::{path::Path, sync::Arc};
2019-02-05 21:54:17 +00:00
2020-02-18 11:11:32 +00:00
use anyhow::Result;
2019-08-25 10:04:56 +00:00
use crossbeam_channel::{unbounded, Receiver};
2020-06-11 09:04:09 +00:00
use ra_db::{AbsPathBuf, CrateGraph};
2020-03-10 17:56:15 +00:00
use ra_ide::{AnalysisChange, AnalysisHost};
2020-06-11 09:04:09 +00:00
use ra_project_model::{CargoConfig, ProcMacroClient, ProjectManifest, ProjectWorkspace};
2020-06-24 13:52:07 +00:00
use vfs::{loader::Handle, AbsPath};
2020-02-17 18:07:30 +00:00
2020-06-11 09:04:09 +00:00
use crate::global_state::{ProjectFolders, SourceRootConfig};
2019-02-09 12:06:12 +00:00
pub fn load_cargo(
2020-02-18 11:11:32 +00:00
root: &Path,
2020-03-16 13:51:44 +00:00
load_out_dirs_from_check: bool,
with_proc_macro: bool,
2020-06-11 09:04:09 +00:00
) -> Result<(AnalysisHost, vfs::Vfs)> {
let root = AbsPathBuf::assert(std::env::current_dir()?.join(root));
2020-06-03 10:05:50 +00:00
let root = ProjectManifest::discover_single(&root)?;
let ws = ProjectWorkspace::load(
root,
2020-04-01 16:51:16 +00:00
&CargoConfig { load_out_dirs_from_check, ..Default::default() },
true,
2020-03-16 13:51:44 +00:00
)?;
2019-08-25 10:04:56 +00:00
let (sender, receiver) = unbounded();
2020-06-11 09:04:09 +00:00
let mut vfs = vfs::Vfs::default();
let mut loader = {
let loader =
2020-06-25 06:59:55 +00:00
vfs_notify::NotifyHandle::spawn(Box::new(move |msg| sender.send(msg).unwrap()));
2020-06-11 09:04:09 +00:00
Box::new(loader)
};
2020-03-18 12:56:46 +00:00
2020-06-11 09:04:09 +00:00
let proc_macro_client = if with_proc_macro {
let path = std::env::current_exe()?;
2020-04-20 18:26:10 +00:00
ProcMacroClient::extern_process(path, &["proc-macro"]).unwrap()
2020-06-11 09:04:09 +00:00
} else {
ProcMacroClient::dummy()
};
2020-06-11 09:04:09 +00:00
2020-06-24 13:52:07 +00:00
let crate_graph = ws.to_crate_graph(None, &proc_macro_client, &mut |path: &AbsPath| {
let contents = loader.load_sync(path);
let path = vfs::VfsPath::from(path.to_path_buf());
2020-06-11 09:04:09 +00:00
vfs.set_file_contents(path.clone(), contents);
vfs.file_id(&path)
});
let project_folders = ProjectFolders::new(&[ws]);
loader.set_config(vfs::loader::Config { load: project_folders.load, watch: vec![] });
log::debug!("crate graph: {:?}", crate_graph);
let host = load(crate_graph, project_folders.source_root_config, &mut vfs, &receiver);
Ok((host, vfs))
2019-06-15 13:29:23 +00:00
}
2019-02-09 12:06:12 +00:00
2020-02-18 11:11:32 +00:00
pub(crate) fn load(
2020-06-11 09:04:09 +00:00
crate_graph: CrateGraph,
source_root_config: SourceRootConfig,
vfs: &mut vfs::Vfs,
receiver: &Receiver<vfs::loader::Message>,
) -> AnalysisHost {
2019-06-15 13:29:23 +00:00
let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok());
2020-03-10 17:56:15 +00:00
let mut host = AnalysisHost::new(lru_cap);
2019-06-15 13:29:23 +00:00
let mut analysis_change = AnalysisChange::new();
// wait until Vfs has loaded all roots
for task in receiver {
2020-06-11 09:04:09 +00:00
match task {
2020-06-24 14:58:49 +00:00
vfs::loader::Message::Progress { n_done, n_total } => {
if n_done == n_total {
2020-06-11 09:04:09 +00:00
break;
}
2020-06-11 09:04:09 +00:00
}
vfs::loader::Message::Loaded { files } => {
for (path, contents) in files {
vfs.set_file_contents(path.into(), contents)
2019-06-15 13:29:23 +00:00
}
2019-02-09 12:06:12 +00:00
}
}
2020-06-11 09:04:09 +00:00
}
let changes = vfs.take_changes();
for file in changes {
if file.exists() {
let contents = vfs.file_contents(file.file_id).to_vec();
if let Ok(text) = String::from_utf8(contents) {
analysis_change.change_file(file.file_id, Some(Arc::new(text)))
}
2019-06-15 13:29:23 +00:00
}
2019-02-09 12:06:12 +00:00
}
2020-06-11 09:04:09 +00:00
let source_roots = source_root_config.partition(&vfs);
analysis_change.set_roots(source_roots);
2019-02-09 12:06:12 +00:00
2020-03-16 13:51:44 +00:00
analysis_change.set_crate_graph(crate_graph);
2019-06-15 13:29:23 +00:00
host.apply_change(analysis_change);
host
2019-02-09 12:06:12 +00:00
}
2019-02-10 10:44:53 +00:00
#[cfg(test)]
mod tests {
use super::*;
2020-02-17 16:31:09 +00:00
use hir::Crate;
2019-02-10 10:44:53 +00:00
#[test]
fn test_loading_rust_analyzer() {
2019-04-04 09:57:10 +00:00
let path = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap().parent().unwrap();
2020-06-11 09:04:09 +00:00
let (host, _vfs) = load_cargo(path, false, false).unwrap();
let n_crates = Crate::all(host.raw_database()).len();
2019-02-10 10:44:53 +00:00
// RA has quite a few crates, but the exact count doesn't matter
2019-02-17 18:05:33 +00:00
assert!(n_crates > 20);
2019-02-10 10:44:53 +00:00
}
}