diff options
Diffstat (limited to 'crates/ra_batch/src')
-rw-r--r-- | crates/ra_batch/src/lib.rs | 164 |
1 files changed, 70 insertions, 94 deletions
diff --git a/crates/ra_batch/src/lib.rs b/crates/ra_batch/src/lib.rs index 96b32d9fe..fa244e86c 100644 --- a/crates/ra_batch/src/lib.rs +++ b/crates/ra_batch/src/lib.rs | |||
@@ -1,36 +1,19 @@ | |||
1 | mod vfs_filter; | 1 | mod vfs_filter; |
2 | 2 | ||
3 | use std::{sync::Arc, path::Path, collections::HashSet, error::Error}; | 3 | use std::{path::Path, collections::HashSet, error::Error}; |
4 | 4 | ||
5 | use rustc_hash::FxHashMap; | 5 | use rustc_hash::FxHashMap; |
6 | 6 | ||
7 | use ra_db::{ | 7 | use ra_db::{ |
8 | CrateGraph, FileId, SourceRoot, SourceRootId, SourceDatabase, salsa::{self, Database}, | 8 | CrateGraph, FileId, SourceRootId, |
9 | }; | 9 | }; |
10 | use ra_hir::db; | 10 | use ra_ide_api::{AnalysisHost, AnalysisChange}; |
11 | use ra_project_model::ProjectWorkspace; | 11 | use ra_project_model::ProjectWorkspace; |
12 | use ra_vfs::{Vfs, VfsChange}; | 12 | use ra_vfs::{Vfs, VfsChange}; |
13 | use vfs_filter::IncludeRustFiles; | 13 | use vfs_filter::IncludeRustFiles; |
14 | 14 | ||
15 | type Result<T> = std::result::Result<T, Box<dyn Error + Send + Sync>>; | 15 | type Result<T> = std::result::Result<T, Box<dyn Error + Send + Sync>>; |
16 | 16 | ||
17 | #[salsa::database( | ||
18 | ra_db::SourceDatabaseStorage, | ||
19 | db::AstDatabaseStorage, | ||
20 | db::DefDatabaseStorage, | ||
21 | db::HirDatabaseStorage | ||
22 | )] | ||
23 | #[derive(Debug)] | ||
24 | pub struct BatchDatabase { | ||
25 | runtime: salsa::Runtime<BatchDatabase>, | ||
26 | } | ||
27 | |||
28 | impl salsa::Database for BatchDatabase { | ||
29 | fn salsa_runtime(&self) -> &salsa::Runtime<BatchDatabase> { | ||
30 | &self.runtime | ||
31 | } | ||
32 | } | ||
33 | |||
34 | fn vfs_file_to_id(f: ra_vfs::VfsFile) -> FileId { | 17 | fn vfs_file_to_id(f: ra_vfs::VfsFile) -> FileId { |
35 | FileId(f.0) | 18 | FileId(f.0) |
36 | } | 19 | } |
@@ -38,86 +21,79 @@ fn vfs_root_to_id(r: ra_vfs::VfsRoot) -> SourceRootId { | |||
38 | SourceRootId(r.0) | 21 | SourceRootId(r.0) |
39 | } | 22 | } |
40 | 23 | ||
41 | impl BatchDatabase { | 24 | pub fn load_cargo(root: &Path) -> Result<(AnalysisHost, Vec<SourceRootId>)> { |
42 | pub fn load(crate_graph: CrateGraph, vfs: &mut Vfs) -> BatchDatabase { | 25 | let root = std::env::current_dir()?.join(root); |
43 | let mut db = BatchDatabase { runtime: salsa::Runtime::default() }; | 26 | let ws = ProjectWorkspace::discover(root.as_ref())?; |
44 | let lru_cap = std::env::var("RA_LRU_CAP") | 27 | let mut roots = Vec::new(); |
45 | .ok() | 28 | roots.push(IncludeRustFiles::member(root.clone())); |
46 | .and_then(|it| it.parse::<usize>().ok()) | 29 | roots.extend(IncludeRustFiles::from_roots(ws.to_roots())); |
47 | .unwrap_or(ra_db::DEFAULT_LRU_CAP); | 30 | let (mut vfs, roots) = Vfs::new(roots); |
48 | db.query_mut(ra_db::ParseQuery).set_lru_capacity(lru_cap); | 31 | let crate_graph = ws.to_crate_graph(&mut |path: &Path| { |
49 | db.query_mut(ra_hir::db::ParseMacroQuery).set_lru_capacity(lru_cap); | 32 | let vfs_file = vfs.load(path); |
50 | db.set_crate_graph(Arc::new(crate_graph)); | 33 | log::debug!("vfs file {:?} -> {:?}", path, vfs_file); |
34 | vfs_file.map(vfs_file_to_id) | ||
35 | }); | ||
36 | log::debug!("crate graph: {:?}", crate_graph); | ||
37 | |||
38 | let local_roots = roots | ||
39 | .into_iter() | ||
40 | .filter(|r| vfs.root2path(*r).starts_with(&root)) | ||
41 | .map(vfs_root_to_id) | ||
42 | .collect(); | ||
43 | |||
44 | let host = load(root.as_path(), crate_graph, &mut vfs); | ||
45 | Ok((host, local_roots)) | ||
46 | } | ||
51 | 47 | ||
52 | // wait until Vfs has loaded all roots | 48 | pub fn load(project_root: &Path, crate_graph: CrateGraph, vfs: &mut Vfs) -> AnalysisHost { |
53 | let receiver = vfs.task_receiver().clone(); | 49 | let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok()); |
54 | let mut roots_loaded = HashSet::new(); | 50 | let mut host = AnalysisHost::new(lru_cap); |
55 | for task in receiver { | 51 | let mut analysis_change = AnalysisChange::new(); |
56 | vfs.handle_task(task); | 52 | analysis_change.set_crate_graph(crate_graph); |
57 | let mut done = false; | 53 | |
58 | for change in vfs.commit_changes() { | 54 | // wait until Vfs has loaded all roots |
59 | match change { | 55 | let receiver = vfs.task_receiver().clone(); |
60 | VfsChange::AddRoot { root, files } => { | 56 | let mut roots_loaded = HashSet::new(); |
61 | let source_root_id = vfs_root_to_id(root); | 57 | for task in receiver { |
62 | log::debug!( | 58 | vfs.handle_task(task); |
63 | "loaded source root {:?} with path {:?}", | 59 | let mut done = false; |
64 | source_root_id, | 60 | for change in vfs.commit_changes() { |
65 | vfs.root2path(root) | 61 | match change { |
66 | ); | 62 | VfsChange::AddRoot { root, files } => { |
67 | let mut file_map = FxHashMap::default(); | 63 | let is_local = vfs.root2path(root).starts_with(&project_root); |
68 | for (vfs_file, path, text) in files { | 64 | let source_root_id = vfs_root_to_id(root); |
69 | let file_id = vfs_file_to_id(vfs_file); | 65 | log::debug!( |
70 | db.set_file_text(file_id, text); | 66 | "loaded source root {:?} with path {:?}", |
71 | db.set_file_relative_path(file_id, path.clone()); | 67 | source_root_id, |
72 | db.set_file_source_root(file_id, source_root_id); | 68 | vfs.root2path(root) |
73 | file_map.insert(path, file_id); | 69 | ); |
74 | } | 70 | analysis_change.add_root(source_root_id, is_local); |
75 | let source_root = SourceRoot { files: file_map }; | 71 | |
76 | db.set_source_root(source_root_id, Arc::new(source_root)); | 72 | let mut file_map = FxHashMap::default(); |
77 | roots_loaded.insert(source_root_id); | 73 | for (vfs_file, path, text) in files { |
78 | if roots_loaded.len() == vfs.n_roots() { | 74 | let file_id = vfs_file_to_id(vfs_file); |
79 | done = true; | 75 | analysis_change.add_file(source_root_id, file_id, path.clone(), text); |
80 | } | 76 | file_map.insert(path, file_id); |
81 | } | 77 | } |
82 | VfsChange::AddFile { .. } | 78 | roots_loaded.insert(source_root_id); |
83 | | VfsChange::RemoveFile { .. } | 79 | if roots_loaded.len() == vfs.n_roots() { |
84 | | VfsChange::ChangeFile { .. } => { | 80 | done = true; |
85 | // We just need the first scan, so just ignore these | ||
86 | } | 81 | } |
87 | } | 82 | } |
88 | } | 83 | VfsChange::AddFile { .. } |
89 | if done { | 84 | | VfsChange::RemoveFile { .. } |
90 | break; | 85 | | VfsChange::ChangeFile { .. } => { |
86 | // We just need the first scan, so just ignore these | ||
87 | } | ||
91 | } | 88 | } |
92 | } | 89 | } |
93 | 90 | if done { | |
94 | db | 91 | break; |
92 | } | ||
95 | } | 93 | } |
96 | 94 | ||
97 | pub fn load_cargo(root: impl AsRef<Path>) -> Result<(BatchDatabase, Vec<SourceRootId>)> { | 95 | host.apply_change(analysis_change); |
98 | let root = std::env::current_dir()?.join(root); | 96 | host |
99 | let ws = ProjectWorkspace::discover(root.as_ref())?; | ||
100 | let mut roots = Vec::new(); | ||
101 | roots.push(IncludeRustFiles::member(root.clone())); | ||
102 | roots.extend(IncludeRustFiles::from_roots(ws.to_roots())); | ||
103 | let (mut vfs, roots) = Vfs::new(roots); | ||
104 | let mut load = |path: &Path| { | ||
105 | let vfs_file = vfs.load(path); | ||
106 | log::debug!("vfs file {:?} -> {:?}", path, vfs_file); | ||
107 | vfs_file.map(vfs_file_to_id) | ||
108 | }; | ||
109 | let crate_graph = ws.to_crate_graph(&mut load); | ||
110 | log::debug!("crate graph: {:?}", crate_graph); | ||
111 | |||
112 | let local_roots = roots | ||
113 | .into_iter() | ||
114 | .filter(|r| vfs.root2path(*r).starts_with(&root)) | ||
115 | .map(vfs_root_to_id) | ||
116 | .collect(); | ||
117 | |||
118 | let db = BatchDatabase::load(crate_graph, &mut vfs); | ||
119 | Ok((db, local_roots)) | ||
120 | } | ||
121 | } | 97 | } |
122 | 98 | ||
123 | #[cfg(test)] | 99 | #[cfg(test)] |
@@ -128,10 +104,10 @@ mod tests { | |||
128 | #[test] | 104 | #[test] |
129 | fn test_loading_rust_analyzer() { | 105 | fn test_loading_rust_analyzer() { |
130 | let path = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap().parent().unwrap(); | 106 | let path = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap().parent().unwrap(); |
131 | let (db, roots) = BatchDatabase::load_cargo(path).unwrap(); | 107 | let (host, roots) = load_cargo(path).unwrap(); |
132 | let mut n_crates = 0; | 108 | let mut n_crates = 0; |
133 | for root in roots { | 109 | for root in roots { |
134 | for _krate in Crate::source_root_crates(&db, root) { | 110 | for _krate in Crate::source_root_crates(host.raw_database(), root) { |
135 | n_crates += 1; | 111 | n_crates += 1; |
136 | } | 112 | } |
137 | } | 113 | } |