Skip to content

Commit e6fbff3

Browse files
bors[bot]matklad
andcommitted
Merge #1406
1406: reuse AnalysisHost in batch analysis r=matklad a=matklad We do some custom setup in `AnalysisHost`, like setting up LRU size. I figure it's a good idea to not duplicate this work in batch analysis, *if* we want to keep batch and non-batch close. Long-term, I see a value in keeping batch a separate, lighter weight thing. However, because now we use batch to measure performance, keeping them closer makes more sense. I'd also like to add ability to get completions by using batch analysis, and that will require ra_ide_api as well. @flodiebold were there some reason why we haven't started with this approach from the start? Co-authored-by: Aleksey Kladov <[email protected]>
2 parents ce9ea09 + b0be420 commit e6fbff3

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)