diff options
author | Florian Diebold <[email protected]> | 2019-02-09 12:06:12 +0000 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2019-02-10 09:56:58 +0000 |
commit | 43e52ac9e2b26ec287b1778823bad10851cfd44e (patch) | |
tree | 9e32634c498e0b8ae6d5132b8b0d3e8c17d37788 /crates | |
parent | 15224dfcd5fc5338844aec5993abf98f7f283e1e (diff) |
Implement BatchDatabase construction
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_batch/Cargo.toml | 12 | ||||
-rw-r--r-- | crates/ra_batch/src/lib.rs | 99 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/server_world.rs | 4 | ||||
-rw-r--r-- | crates/ra_vfs/src/lib.rs | 12 |
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" | |||
5 | authors = ["Aleksey Kladov <[email protected]>"] | 5 | authors = ["Aleksey Kladov <[email protected]>"] |
6 | 6 | ||
7 | [dependencies] | 7 | [dependencies] |
8 | itertools = "0.8.0" | ||
9 | join_to_string = "0.1.3" | ||
10 | log = "0.4.5" | 8 | log = "0.4.5" |
11 | relative-path = "0.4.0" | ||
12 | rayon = "1.0.2" | ||
13 | fst = "0.3.1" | ||
14 | rustc-hash = "1.0" | 9 | rustc-hash = "1.0" |
15 | parking_lot = "0.7.0" | 10 | |
16 | unicase = "2.2.0" | 11 | failure = "0.1.4" |
17 | 12 | ||
18 | ra_syntax = { path = "../ra_syntax" } | 13 | ra_syntax = { path = "../ra_syntax" } |
19 | ra_db = { path = "../ra_db" } | 14 | ra_db = { path = "../ra_db" } |
20 | ra_hir = { path = "../ra_hir" } | 15 | ra_hir = { path = "../ra_hir" } |
16 | ra_vfs = { path = "../ra_vfs" } | ||
17 | ra_project_model = { path = "../ra_project_model" } | ||
21 | 18 | ||
22 | [dev-dependencies] | 19 | [dev-dependencies] |
23 | test_utils = { path = "../test_utils" } | 20 | test_utils = { path = "../test_utils" } |
24 | insta = "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 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | use std::path::Path; | ||
3 | use std::collections::HashSet; | ||
4 | |||
5 | use rustc_hash::FxHashMap; | ||
2 | 6 | ||
3 | use ra_db::{ | 7 | use ra_db::{ |
4 | FilePosition, FileId, CrateGraph, SourceRoot, SourceRootId, SourceDatabase, salsa, | 8 | CrateGraph, FileId, SourceRoot, SourceRootId, SourceDatabase, salsa, |
5 | }; | 9 | }; |
6 | use ra_hir::{db, HirInterner}; | 10 | use ra_hir::{db, HirInterner}; |
11 | use ra_project_model::ProjectWorkspace; | ||
12 | use ra_vfs::{Vfs, VfsChange}; | ||
13 | |||
14 | type 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)] |
14 | pub(crate) struct BatchDatabase { | 22 | pub 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 | ||
20 | impl salsa::Database for BatchDatabase { | 28 | impl salsa::Database for BatchDatabase { |
@@ -28,3 +36,88 @@ impl AsRef<HirInterner> for BatchDatabase { | |||
28 | &self.interner | 36 | &self.interner |
29 | } | 37 | } |
30 | } | 38 | } |
39 | |||
40 | fn vfs_file_to_id(f: ra_vfs::VfsFile) -> FileId { | ||
41 | FileId(f.0.into()) | ||
42 | } | ||
43 | fn vfs_root_to_id(r: ra_vfs::VfsRoot) -> SourceRootId { | ||
44 | SourceRootId(r.0.into()) | ||
45 | } | ||
46 | |||
47 | impl 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 { |