aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-02-09 12:06:12 +0000
committerFlorian Diebold <[email protected]>2019-02-10 09:56:58 +0000
commit43e52ac9e2b26ec287b1778823bad10851cfd44e (patch)
tree9e32634c498e0b8ae6d5132b8b0d3e8c17d37788 /crates
parent15224dfcd5fc5338844aec5993abf98f7f283e1e (diff)
Implement BatchDatabase construction
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_batch/Cargo.toml12
-rw-r--r--crates/ra_batch/src/lib.rs99
-rw-r--r--crates/ra_lsp_server/src/server_world.rs4
-rw-r--r--crates/ra_vfs/src/lib.rs12
4 files changed, 113 insertions, 14 deletions
diff --git a/crates/ra_batch/Cargo.toml b/crates/ra_batch/Cargo.toml
index 3e83f8388..30a0749c7 100644
--- a/crates/ra_batch/Cargo.toml
+++ b/crates/ra_batch/Cargo.toml
@@ -5,20 +5,16 @@ version = "0.1.0"
5authors = ["Aleksey Kladov <[email protected]>"] 5authors = ["Aleksey Kladov <[email protected]>"]
6 6
7[dependencies] 7[dependencies]
8itertools = "0.8.0"
9join_to_string = "0.1.3"
10log = "0.4.5" 8log = "0.4.5"
11relative-path = "0.4.0"
12rayon = "1.0.2"
13fst = "0.3.1"
14rustc-hash = "1.0" 9rustc-hash = "1.0"
15parking_lot = "0.7.0" 10
16unicase = "2.2.0" 11failure = "0.1.4"
17 12
18ra_syntax = { path = "../ra_syntax" } 13ra_syntax = { path = "../ra_syntax" }
19ra_db = { path = "../ra_db" } 14ra_db = { path = "../ra_db" }
20ra_hir = { path = "../ra_hir" } 15ra_hir = { path = "../ra_hir" }
16ra_vfs = { path = "../ra_vfs" }
17ra_project_model = { path = "../ra_project_model" }
21 18
22[dev-dependencies] 19[dev-dependencies]
23test_utils = { path = "../test_utils" } 20test_utils = { path = "../test_utils" }
24insta = "0.6.1"
diff --git a/crates/ra_batch/src/lib.rs b/crates/ra_batch/src/lib.rs
index 25f1f7357..ea91d88b7 100644
--- a/crates/ra_batch/src/lib.rs
+++ b/crates/ra_batch/src/lib.rs
@@ -1,9 +1,17 @@
1use std::sync::Arc; 1use std::sync::Arc;
2use std::path::Path;
3use std::collections::HashSet;
4
5use rustc_hash::FxHashMap;
2 6
3use ra_db::{ 7use ra_db::{
4 FilePosition, FileId, CrateGraph, SourceRoot, SourceRootId, SourceDatabase, salsa, 8 CrateGraph, FileId, SourceRoot, SourceRootId, SourceDatabase, salsa,
5}; 9};
6use ra_hir::{db, HirInterner}; 10use ra_hir::{db, HirInterner};
11use ra_project_model::ProjectWorkspace;
12use ra_vfs::{Vfs, VfsChange};
13
14type Result<T> = std::result::Result<T, failure::Error>;
7 15
8#[salsa::database( 16#[salsa::database(
9 ra_db::SourceDatabaseStorage, 17 ra_db::SourceDatabaseStorage,
@@ -11,10 +19,10 @@ use ra_hir::{db, HirInterner};
11 db::PersistentHirDatabaseStorage 19 db::PersistentHirDatabaseStorage
12)] 20)]
13#[derive(Debug)] 21#[derive(Debug)]
14pub(crate) struct BatchDatabase { 22pub struct BatchDatabase {
15 runtime: salsa::Runtime<BatchDatabase>, 23 runtime: salsa::Runtime<BatchDatabase>,
16 interner: Arc<HirInterner>, 24 interner: Arc<HirInterner>,
17 file_counter: u32, 25 // file_counter: u32,
18} 26}
19 27
20impl salsa::Database for BatchDatabase { 28impl salsa::Database for BatchDatabase {
@@ -28,3 +36,88 @@ impl AsRef<HirInterner> for BatchDatabase {
28 &self.interner 36 &self.interner
29 } 37 }
30} 38}
39
40fn vfs_file_to_id(f: ra_vfs::VfsFile) -> FileId {
41 FileId(f.0.into())
42}
43fn vfs_root_to_id(r: ra_vfs::VfsRoot) -> SourceRootId {
44 SourceRootId(r.0.into())
45}
46
47impl BatchDatabase {
48 pub fn load(crate_graph: CrateGraph, vfs: &mut Vfs) -> BatchDatabase {
49 let mut db =
50 BatchDatabase { runtime: salsa::Runtime::default(), interner: Default::default() };
51 db.set_crate_graph(Arc::new(crate_graph));
52
53 // wait until Vfs has loaded all roots
54 let receiver = vfs.task_receiver().clone();
55 let mut roots_loaded = HashSet::new();
56 for task in receiver {
57 vfs.handle_task(task);
58 let mut done = false;
59 for change in vfs.commit_changes() {
60 match change {
61 VfsChange::AddRoot { root, files } => {
62 let source_root_id = vfs_root_to_id(root);
63 log::debug!("loaded source root {:?} with path {:?}", source_root_id, vfs.root2path(root));
64 let mut file_map = FxHashMap::default();
65 for (vfs_file, path, text) in files {
66 let file_id = vfs_file_to_id(vfs_file);
67 db.set_file_text(file_id, text);
68 db.set_file_relative_path(file_id, path.clone());
69 db.set_file_source_root(file_id, source_root_id);
70 file_map.insert(path, file_id);
71 }
72 let source_root = SourceRoot { files: file_map };
73 db.set_source_root(source_root_id, Arc::new(source_root));
74 roots_loaded.insert(source_root_id);
75 if roots_loaded.len() == vfs.num_roots() {
76 done = true;
77 }
78 }
79 VfsChange::AddFile { .. }
80 | VfsChange::RemoveFile { .. }
81 | VfsChange::ChangeFile { .. } => {
82 // log::warn!("VFS changed while loading");
83 }
84 }
85 }
86 if done {
87 break;
88 }
89 }
90
91 db
92 }
93
94 pub fn load_cargo(root: impl AsRef<Path>) -> Result<(BatchDatabase, Vec<SourceRootId>)> {
95 let root = root.as_ref().canonicalize()?;
96 let ws = ProjectWorkspace::discover(root.as_ref())?;
97 let mut roots = Vec::new();
98 roots.push(root.clone());
99 for pkg in ws.cargo.packages() {
100 roots.push(pkg.root(&ws.cargo).to_path_buf());
101 }
102 for krate in ws.sysroot.crates() {
103 roots.push(krate.root_dir(&ws.sysroot).to_path_buf())
104 }
105 let (mut vfs, roots) = Vfs::new(roots);
106 let mut load = |path: &Path| {
107 let vfs_file = vfs.load(path);
108 log::debug!("vfs file {:?} -> {:?}", path, vfs_file);
109 vfs_file.map(vfs_file_to_id)
110 };
111 let crate_graph = ws.to_crate_graph(&mut load);
112 log::debug!("crate graph: {:?}", crate_graph);
113
114 let local_roots = roots.into_iter()
115 .filter(|r| vfs.root2path(*r).starts_with(&root))
116 .map(vfs_root_to_id)
117 .collect();
118
119 let db = BatchDatabase::load(crate_graph, &mut vfs);
120 let _ = vfs.shutdown();
121 Ok((db, local_roots))
122 }
123}
diff --git a/crates/ra_lsp_server/src/server_world.rs b/crates/ra_lsp_server/src/server_world.rs
index f97d240fa..4a68c019f 100644
--- a/crates/ra_lsp_server/src/server_world.rs
+++ b/crates/ra_lsp_server/src/server_world.rs
@@ -47,10 +47,8 @@ impl ServerWorldState {
47 roots.push(krate.root_dir(&ws.sysroot).to_path_buf()) 47 roots.push(krate.root_dir(&ws.sysroot).to_path_buf())
48 } 48 }
49 } 49 }
50 roots.sort();
51 roots.dedup();
52 let roots_to_scan = roots.len();
53 let (mut vfs, roots) = Vfs::new(roots); 50 let (mut vfs, roots) = Vfs::new(roots);
51 let roots_to_scan = roots.len();
54 for r in roots { 52 for r in roots {
55 let is_local = vfs.root2path(r).starts_with(&root); 53 let is_local = vfs.root2path(r).starts_with(&root);
56 change.add_root(SourceRootId(r.0.into()), is_local); 54 change.add_root(SourceRootId(r.0.into()), is_local);
diff --git a/crates/ra_vfs/src/lib.rs b/crates/ra_vfs/src/lib.rs
index 6b4eb6842..2d861f832 100644
--- a/crates/ra_vfs/src/lib.rs
+++ b/crates/ra_vfs/src/lib.rs
@@ -94,6 +94,7 @@ impl Roots {
94 let mut roots = Arena::default(); 94 let mut roots = Arena::default();
95 // A hack to make nesting work. 95 // A hack to make nesting work.
96 paths.sort_by_key(|it| Reverse(it.as_os_str().len())); 96 paths.sort_by_key(|it| Reverse(it.as_os_str().len()));
97 paths.dedup();
97 for (i, path) in paths.iter().enumerate() { 98 for (i, path) in paths.iter().enumerate() {
98 let nested_roots = paths[..i] 99 let nested_roots = paths[..i]
99 .iter() 100 .iter()
@@ -161,6 +162,13 @@ impl Vfs {
161 self.roots[root].root.clone() 162 self.roots[root].root.clone()
162 } 163 }
163 164
165 pub fn path2root(&self, path: &Path) -> Option<VfsRoot> {
166 match self.find_root(path) {
167 Some((root, _path, _file)) => Some(root),
168 _ => None,
169 }
170 }
171
164 pub fn path2file(&self, path: &Path) -> Option<VfsFile> { 172 pub fn path2file(&self, path: &Path) -> Option<VfsFile> {
165 if let Some((_root, _path, Some(file))) = self.find_root(path) { 173 if let Some((_root, _path, Some(file))) = self.find_root(path) {
166 return Some(file); 174 return Some(file);
@@ -181,6 +189,10 @@ impl Vfs {
181 None 189 None
182 } 190 }
183 191
192 pub fn num_roots(&self) -> usize {
193 self.roots.len()
194 }
195
184 pub fn load(&mut self, path: &Path) -> Option<VfsFile> { 196 pub fn load(&mut self, path: &Path) -> Option<VfsFile> {
185 if let Some((root, rel_path, file)) = self.find_root(path) { 197 if let Some((root, rel_path, file)) = self.find_root(path) {
186 return if let Some(file) = file { 198 return if let Some(file) = file {