From d7be1da8df45027ce18b8af9da68ed98b9a454cc Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 17 Feb 2020 17:31:09 +0100 Subject: Inline ra_batch --- crates/ra_cli/src/analysis_bench.rs | 4 +- crates/ra_cli/src/analysis_stats.rs | 4 +- crates/ra_cli/src/load_cargo.rs | 153 ++++++++++++++++++++++++++++++++++++ crates/ra_cli/src/main.rs | 3 +- 4 files changed, 158 insertions(+), 6 deletions(-) create mode 100644 crates/ra_cli/src/load_cargo.rs (limited to 'crates/ra_cli/src') diff --git a/crates/ra_cli/src/analysis_bench.rs b/crates/ra_cli/src/analysis_bench.rs index 4835a68ce..3f10ed400 100644 --- a/crates/ra_cli/src/analysis_bench.rs +++ b/crates/ra_cli/src/analysis_bench.rs @@ -13,7 +13,7 @@ use ra_db::{ }; use ra_ide::{Analysis, AnalysisChange, AnalysisHost, FilePosition, LineCol}; -use crate::Result; +use crate::{load_cargo::load_cargo, Result}; pub(crate) struct Position { path: PathBuf, @@ -46,7 +46,7 @@ pub(crate) fn run(verbose: bool, path: &Path, op: Op) -> Result<()> { let start = Instant::now(); eprint!("loading: "); - let (mut host, roots) = ra_batch::load_cargo(path)?; + let (mut host, roots) = load_cargo(path)?; let db = host.raw_database(); eprintln!("{:?}\n", start.elapsed()); diff --git a/crates/ra_cli/src/analysis_stats.rs b/crates/ra_cli/src/analysis_stats.rs index bfa174d51..d40f04391 100644 --- a/crates/ra_cli/src/analysis_stats.rs +++ b/crates/ra_cli/src/analysis_stats.rs @@ -13,7 +13,7 @@ use ra_db::SourceDatabaseExt; use ra_syntax::AstNode; use rand::{seq::SliceRandom, thread_rng}; -use crate::{progress_report::ProgressReport, Result, Verbosity}; +use crate::{load_cargo::load_cargo, progress_report::ProgressReport, Result, Verbosity}; pub fn run( verbosity: Verbosity, @@ -24,7 +24,7 @@ pub fn run( randomize: bool, ) -> Result<()> { let db_load_time = Instant::now(); - let (mut host, roots) = ra_batch::load_cargo(path)?; + let (mut host, roots) = load_cargo(path)?; let db = host.raw_database(); println!("Database loaded, {} roots, {:?}", roots.len(), db_load_time.elapsed()); let analysis_time = Instant::now(); diff --git a/crates/ra_cli/src/load_cargo.rs b/crates/ra_cli/src/load_cargo.rs new file mode 100644 index 000000000..2d6433f18 --- /dev/null +++ b/crates/ra_cli/src/load_cargo.rs @@ -0,0 +1,153 @@ +//! FIXME: write short doc here + +use std::{collections::HashSet, error::Error, path::Path}; + +use rustc_hash::FxHashMap; + +use crossbeam_channel::{unbounded, Receiver}; +use ra_db::{CrateGraph, FileId, SourceRootId}; +use ra_ide::{AnalysisChange, AnalysisHost, FeatureFlags}; +use ra_project_model::{get_rustc_cfg_options, PackageRoot, ProjectWorkspace}; +use ra_vfs::{RootEntry, Vfs, VfsChange, VfsTask, Watch}; +use ra_vfs_glob::RustPackageFilterBuilder; + +type Result = std::result::Result>; + +fn vfs_file_to_id(f: ra_vfs::VfsFile) -> FileId { + FileId(f.0) +} +fn vfs_root_to_id(r: ra_vfs::VfsRoot) -> SourceRootId { + SourceRootId(r.0) +} + +pub fn load_cargo(root: &Path) -> Result<(AnalysisHost, FxHashMap)> { + let root = std::env::current_dir()?.join(root); + let ws = ProjectWorkspace::discover(root.as_ref(), &Default::default())?; + let project_roots = ws.to_roots(); + let (sender, receiver) = unbounded(); + let sender = Box::new(move |t| sender.send(t).unwrap()); + let (mut vfs, roots) = Vfs::new( + project_roots + .iter() + .map(|pkg_root| { + RootEntry::new( + pkg_root.path().clone(), + RustPackageFilterBuilder::default() + .set_member(pkg_root.is_member()) + .into_vfs_filter(), + ) + }) + .collect(), + sender, + Watch(false), + ); + + // FIXME: cfg options? + let default_cfg_options = { + let mut opts = get_rustc_cfg_options(); + opts.insert_atom("test".into()); + opts.insert_atom("debug_assertion".into()); + opts + }; + + let (crate_graph, _crate_names) = + ws.to_crate_graph(&default_cfg_options, &mut |path: &Path| { + let vfs_file = vfs.load(path); + log::debug!("vfs file {:?} -> {:?}", path, vfs_file); + vfs_file.map(vfs_file_to_id) + }); + log::debug!("crate graph: {:?}", crate_graph); + + let source_roots = roots + .iter() + .map(|&vfs_root| { + let source_root_id = vfs_root_to_id(vfs_root); + let project_root = project_roots + .iter() + .find(|it| it.path() == &vfs.root2path(vfs_root)) + .unwrap() + .clone(); + (source_root_id, project_root) + }) + .collect::>(); + let host = load(&source_roots, crate_graph, &mut vfs, receiver); + Ok((host, source_roots)) +} + +pub fn load( + source_roots: &FxHashMap, + crate_graph: CrateGraph, + vfs: &mut Vfs, + receiver: Receiver, +) -> AnalysisHost { + let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::().ok()); + let mut host = AnalysisHost::new(lru_cap, FeatureFlags::default()); + let mut analysis_change = AnalysisChange::new(); + analysis_change.set_crate_graph(crate_graph); + + // wait until Vfs has loaded all roots + let mut roots_loaded = HashSet::new(); + for task in receiver { + vfs.handle_task(task); + let mut done = false; + for change in vfs.commit_changes() { + match change { + VfsChange::AddRoot { root, files } => { + let source_root_id = vfs_root_to_id(root); + let is_local = source_roots[&source_root_id].is_member(); + log::debug!( + "loaded source root {:?} with path {:?}", + source_root_id, + vfs.root2path(root) + ); + analysis_change.add_root(source_root_id, is_local); + analysis_change.set_debug_root_path( + source_root_id, + source_roots[&source_root_id].path().display().to_string(), + ); + + let mut file_map = FxHashMap::default(); + for (vfs_file, path, text) in files { + let file_id = vfs_file_to_id(vfs_file); + analysis_change.add_file(source_root_id, file_id, path.clone(), text); + file_map.insert(path, file_id); + } + roots_loaded.insert(source_root_id); + if roots_loaded.len() == vfs.n_roots() { + done = true; + } + } + VfsChange::AddFile { root, file, path, text } => { + let source_root_id = vfs_root_to_id(root); + let file_id = vfs_file_to_id(file); + analysis_change.add_file(source_root_id, file_id, path, text); + } + VfsChange::RemoveFile { .. } | VfsChange::ChangeFile { .. } => { + // We just need the first scan, so just ignore these + } + } + } + if done { + break; + } + } + + host.apply_change(analysis_change); + host +} + +#[cfg(test)] +mod tests { + use super::*; + + use hir::Crate; + + #[test] + fn test_loading_rust_analyzer() { + let path = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap().parent().unwrap(); + let (host, _roots) = load_cargo(path).unwrap(); + 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); + } +} diff --git a/crates/ra_cli/src/main.rs b/crates/ra_cli/src/main.rs index 9a7f9724e..4a428faff 100644 --- a/crates/ra_cli/src/main.rs +++ b/crates/ra_cli/src/main.rs @@ -1,5 +1,6 @@ //! FIXME: write short doc here +mod load_cargo; mod analysis_stats; mod analysis_bench; mod progress_report; @@ -157,12 +158,10 @@ ARGS: let path = { let mut trailing = matches.free()?; if trailing.len() != 1 { - eprintln!("{}", help::ANALYSIS_STATS_HELP); Err("Invalid flags")?; } trailing.pop().unwrap() }; - matches.finish().or_else(handle_extra_flags)?; analysis_stats::run( verbosity, -- cgit v1.2.3