Skip to content

Commit b0be420

Browse files
committed
reuse AnalysisHost in batch analysis
1 parent 41c56c8 commit b0be420

File tree

6 files changed

+89
-108
lines changed

6 files changed

+89
-108
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/ra_batch/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ rustc-hash = "1.0"
1111
ra_vfs = "0.2.0"
1212
ra_syntax = { path = "../ra_syntax" }
1313
ra_db = { path = "../ra_db" }
14+
ra_ide_api = { path = "../ra_ide_api" }
1415
ra_hir = { path = "../ra_hir" }
1516
ra_project_model = { path = "../ra_project_model" }
1617

crates/ra_batch/src/lib.rs

Lines changed: 70 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,123 +1,99 @@
11
mod vfs_filter;
22

3-
use std::{sync::Arc, path::Path, collections::HashSet, error::Error};
3+
use std::{path::Path, collections::HashSet, error::Error};
44

55
use rustc_hash::FxHashMap;
66

77
use ra_db::{
8-
CrateGraph, FileId, SourceRoot, SourceRootId, SourceDatabase, salsa::{self, Database},
8+
CrateGraph, FileId, SourceRootId,
99
};
10-
use ra_hir::db;
10+
use ra_ide_api::{AnalysisHost, AnalysisChange};
1111
use ra_project_model::ProjectWorkspace;
1212
use ra_vfs::{Vfs, VfsChange};
1313
use vfs_filter::IncludeRustFiles;
1414

1515
type Result<T> = std::result::Result<T, Box<dyn Error + Send + Sync>>;
1616

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-
3417
fn vfs_file_to_id(f: ra_vfs::VfsFile) -> FileId {
3518
FileId(f.0)
3619
}
3720
fn vfs_root_to_id(r: ra_vfs::VfsRoot) -> SourceRootId {
3821
SourceRootId(r.0)
3922
}
4023

41-
impl BatchDatabase {
42-
pub fn load(crate_graph: CrateGraph, vfs: &mut Vfs) -> BatchDatabase {
43-
let mut db = BatchDatabase { runtime: salsa::Runtime::default() };
44-
let lru_cap = std::env::var("RA_LRU_CAP")
45-
.ok()
46-
.and_then(|it| it.parse::<usize>().ok())
47-
.unwrap_or(ra_db::DEFAULT_LRU_CAP);
48-
db.query_mut(ra_db::ParseQuery).set_lru_capacity(lru_cap);
49-
db.query_mut(ra_hir::db::ParseMacroQuery).set_lru_capacity(lru_cap);
50-
db.set_crate_graph(Arc::new(crate_graph));
24+
pub fn load_cargo(root: &Path) -> Result<(AnalysisHost, Vec<SourceRootId>)> {
25+
let root = std::env::current_dir()?.join(root);
26+
let ws = ProjectWorkspace::discover(root.as_ref())?;
27+
let mut roots = Vec::new();
28+
roots.push(IncludeRustFiles::member(root.clone()));
29+
roots.extend(IncludeRustFiles::from_roots(ws.to_roots()));
30+
let (mut vfs, roots) = Vfs::new(roots);
31+
let crate_graph = ws.to_crate_graph(&mut |path: &Path| {
32+
let vfs_file = vfs.load(path);
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+
}
5147

52-
// wait until Vfs has loaded all roots
53-
let receiver = vfs.task_receiver().clone();
54-
let mut roots_loaded = HashSet::new();
55-
for task in receiver {
56-
vfs.handle_task(task);
57-
let mut done = false;
58-
for change in vfs.commit_changes() {
59-
match change {
60-
VfsChange::AddRoot { root, files } => {
61-
let source_root_id = vfs_root_to_id(root);
62-
log::debug!(
63-
"loaded source root {:?} with path {:?}",
64-
source_root_id,
65-
vfs.root2path(root)
66-
);
67-
let mut file_map = FxHashMap::default();
68-
for (vfs_file, path, text) in files {
69-
let file_id = vfs_file_to_id(vfs_file);
70-
db.set_file_text(file_id, text);
71-
db.set_file_relative_path(file_id, path.clone());
72-
db.set_file_source_root(file_id, source_root_id);
73-
file_map.insert(path, file_id);
74-
}
75-
let source_root = SourceRoot { files: file_map };
76-
db.set_source_root(source_root_id, Arc::new(source_root));
77-
roots_loaded.insert(source_root_id);
78-
if roots_loaded.len() == vfs.n_roots() {
79-
done = true;
80-
}
48+
pub fn load(project_root: &Path, crate_graph: CrateGraph, vfs: &mut Vfs) -> AnalysisHost {
49+
let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok());
50+
let mut host = AnalysisHost::new(lru_cap);
51+
let mut analysis_change = AnalysisChange::new();
52+
analysis_change.set_crate_graph(crate_graph);
53+
54+
// wait until Vfs has loaded all roots
55+
let receiver = vfs.task_receiver().clone();
56+
let mut roots_loaded = HashSet::new();
57+
for task in receiver {
58+
vfs.handle_task(task);
59+
let mut done = false;
60+
for change in vfs.commit_changes() {
61+
match change {
62+
VfsChange::AddRoot { root, files } => {
63+
let is_local = vfs.root2path(root).starts_with(&project_root);
64+
let source_root_id = vfs_root_to_id(root);
65+
log::debug!(
66+
"loaded source root {:?} with path {:?}",
67+
source_root_id,
68+
vfs.root2path(root)
69+
);
70+
analysis_change.add_root(source_root_id, is_local);
71+
72+
let mut file_map = FxHashMap::default();
73+
for (vfs_file, path, text) in files {
74+
let file_id = vfs_file_to_id(vfs_file);
75+
analysis_change.add_file(source_root_id, file_id, path.clone(), text);
76+
file_map.insert(path, file_id);
8177
}
82-
VfsChange::AddFile { .. }
83-
| VfsChange::RemoveFile { .. }
84-
| VfsChange::ChangeFile { .. } => {
85-
// We just need the first scan, so just ignore these
78+
roots_loaded.insert(source_root_id);
79+
if roots_loaded.len() == vfs.n_roots() {
80+
done = true;
8681
}
8782
}
88-
}
89-
if done {
90-
break;
83+
VfsChange::AddFile { .. }
84+
| VfsChange::RemoveFile { .. }
85+
| VfsChange::ChangeFile { .. } => {
86+
// We just need the first scan, so just ignore these
87+
}
9188
}
9289
}
93-
94-
db
90+
if done {
91+
break;
92+
}
9593
}
9694

97-
pub fn load_cargo(root: impl AsRef<Path>) -> Result<(BatchDatabase, Vec<SourceRootId>)> {
98-
let root = std::env::current_dir()?.join(root);
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-
}
95+
host.apply_change(analysis_change);
96+
host
12197
}
12298

12399
#[cfg(test)]
@@ -128,10 +104,10 @@ mod tests {
128104
#[test]
129105
fn test_loading_rust_analyzer() {
130106
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();
132108
let mut n_crates = 0;
133109
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) {
135111
n_crates += 1;
136112
}
137113
}

crates/ra_cli/src/analysis_stats.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
use std::{collections::HashSet, time::Instant, fmt::Write};
22

33
use ra_db::SourceDatabase;
4-
use ra_batch::BatchDatabase;
54
use ra_hir::{Crate, ModuleDef, Ty, ImplItem, HasSource};
65
use ra_syntax::AstNode;
76

87
use crate::Result;
98

109
pub fn run(verbose: bool, path: &str, only: Option<&str>) -> Result<()> {
1110
let db_load_time = Instant::now();
12-
let (db, roots) = BatchDatabase::load_cargo(path)?;
11+
let (host, roots) = ra_batch::load_cargo(path.as_ref())?;
12+
let db = host.raw_database();
1313
println!("Database loaded, {} roots, {:?}", roots.len(), db_load_time.elapsed());
1414
let analysis_time = Instant::now();
1515
let mut num_crates = 0;
1616
let mut visited_modules = HashSet::new();
1717
let mut visit_queue = Vec::new();
1818
for root in roots {
19-
for krate in Crate::source_root_crates(&db, root) {
19+
for krate in Crate::source_root_crates(db, root) {
2020
num_crates += 1;
21-
let module = krate.root_module(&db).expect("crate in source root without root module");
21+
let module = krate.root_module(db).expect("crate in source root without root module");
2222
visit_queue.push(module);
2323
}
2424
}
@@ -27,17 +27,17 @@ pub fn run(verbose: bool, path: &str, only: Option<&str>) -> Result<()> {
2727
let mut funcs = Vec::new();
2828
while let Some(module) = visit_queue.pop() {
2929
if visited_modules.insert(module) {
30-
visit_queue.extend(module.children(&db));
30+
visit_queue.extend(module.children(db));
3131

32-
for decl in module.declarations(&db) {
32+
for decl in module.declarations(db) {
3333
num_decls += 1;
3434
if let ModuleDef::Function(f) = decl {
3535
funcs.push(f);
3636
}
3737
}
3838

39-
for impl_block in module.impl_blocks(&db) {
40-
for item in impl_block.items(&db) {
39+
for impl_block in module.impl_blocks(db) {
40+
for item in impl_block.items(db) {
4141
num_decls += 1;
4242
if let ImplItem::Method(f) = item {
4343
funcs.push(f);
@@ -61,11 +61,11 @@ pub fn run(verbose: bool, path: &str, only: Option<&str>) -> Result<()> {
6161
let mut num_exprs_unknown = 0;
6262
let mut num_exprs_partially_unknown = 0;
6363
for f in funcs {
64-
let name = f.name(&db);
64+
let name = f.name(db);
6565
let mut msg = format!("processing: {}", name);
6666
if verbose {
67-
let src = f.source(&db);
68-
let original_file = src.file_id.original_file(&db);
67+
let src = f.source(db);
68+
let original_file = src.file_id.original_file(db);
6969
let path = db.file_relative_path(original_file);
7070
let syntax_range = src.ast.syntax().range();
7171
write!(msg, " ({:?} {})", path, syntax_range).unwrap();
@@ -76,8 +76,8 @@ pub fn run(verbose: bool, path: &str, only: Option<&str>) -> Result<()> {
7676
continue;
7777
}
7878
}
79-
let body = f.body(&db);
80-
let inference_result = f.infer(&db);
79+
let body = f.body(db);
80+
let inference_result = f.infer(db);
8181
for (expr_id, _) in body.exprs() {
8282
let ty = &inference_result[expr_id];
8383
num_exprs += 1;

crates/ra_ide_api/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,9 @@ impl AnalysisHost {
276276
pub fn collect_garbage(&mut self) {
277277
self.db.collect_garbage();
278278
}
279+
pub fn raw_database(&self) -> &impl hir::db::HirDatabase {
280+
&self.db
281+
}
279282
}
280283

281284
/// Analysis is a snapshot of a world state at a moment in time. It is the main

crates/ra_lsp_server/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ fn main() -> Result<()> {
1717
Err(_) => ra_prof::Filter::disabled(),
1818
});
1919
log::info!("lifecycle: server started");
20-
match ::std::panic::catch_unwind(main_inner) {
20+
match std::panic::catch_unwind(main_inner) {
2121
Ok(res) => {
2222
log::info!("lifecycle: terminating process with {:?}", res);
2323
res

0 commit comments

Comments
 (0)