diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-04-14 18:26:07 +0100 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-04-14 18:26:07 +0100 |
commit | 88be6f32172813f53dae60d73c9f5deb0c3fb29f (patch) | |
tree | 0b5f8f793929f651dfe332e0f5545b938ff5189f /crates/ra_lsp_server/src/server_world.rs | |
parent | 5d35f284f5ac70cde5d758e7c63a38eae0fb0b55 (diff) | |
parent | c2dfc8a229c0a18dff08d5ce7e6836c91648eee5 (diff) |
Merge #1137
1137: Adds support for multiple editor workspaces on initialization r=matklad a=jrvidal
OK, so this "simple hack" turned out to be way more contrived than I expected :joy:
### What works
This patch only handles multi-folder editor workspaces _on initialization_.
* I've found that modifying the layout of a workspace in VSCode just reloads the extension, so this hack should be enough for now.
* Not sure about how emacs-lsp behaves, but we fallback gracefully to the mono-folder workspace, so it should be fine.
### What doesn't work
* [x] `cargo watch` can only watch a single root folder with a `Cargo.toml`. I've left this part untouched but we could either warn that it's not supported or launch _multiple_ `cargo-watch` processes.
* [x] The `rust-analyzer/runnables` command is not functional, since we don't send the correct `cwd`.
* [x] Should we add some happy path test to `heavy_tests`?
* [ ] Going from a single `root` to multiple `roots` leaves us with a couple of `n * m` loops that smell a bit. The number of folders in the editor workspace is probably low though.
Co-authored-by: Roberto Vidal <[email protected]>
Diffstat (limited to 'crates/ra_lsp_server/src/server_world.rs')
-rw-r--r-- | crates/ra_lsp_server/src/server_world.rs | 27 |
1 files changed, 17 insertions, 10 deletions
diff --git a/crates/ra_lsp_server/src/server_world.rs b/crates/ra_lsp_server/src/server_world.rs index 4b1d592bb..b2808b817 100644 --- a/crates/ra_lsp_server/src/server_world.rs +++ b/crates/ra_lsp_server/src/server_world.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use std::{ | 1 | use std::{ |
2 | path::PathBuf, | 2 | path::{Path, PathBuf}, |
3 | sync::Arc, | 3 | sync::Arc, |
4 | }; | 4 | }; |
5 | 5 | ||
@@ -24,7 +24,7 @@ use crate::{ | |||
24 | #[derive(Debug)] | 24 | #[derive(Debug)] |
25 | pub struct ServerWorldState { | 25 | pub struct ServerWorldState { |
26 | pub roots_to_scan: usize, | 26 | pub roots_to_scan: usize, |
27 | pub root: PathBuf, | 27 | pub roots: Vec<PathBuf>, |
28 | pub workspaces: Arc<Vec<ProjectWorkspace>>, | 28 | pub workspaces: Arc<Vec<ProjectWorkspace>>, |
29 | pub analysis_host: AnalysisHost, | 29 | pub analysis_host: AnalysisHost, |
30 | pub vfs: Arc<RwLock<Vfs>>, | 30 | pub vfs: Arc<RwLock<Vfs>>, |
@@ -37,19 +37,20 @@ pub struct ServerWorld { | |||
37 | } | 37 | } |
38 | 38 | ||
39 | impl ServerWorldState { | 39 | impl ServerWorldState { |
40 | pub fn new(root: PathBuf, workspaces: Vec<ProjectWorkspace>) -> ServerWorldState { | 40 | pub fn new(folder_roots: Vec<PathBuf>, workspaces: Vec<ProjectWorkspace>) -> ServerWorldState { |
41 | let mut change = AnalysisChange::new(); | 41 | let mut change = AnalysisChange::new(); |
42 | 42 | ||
43 | let mut roots = Vec::new(); | 43 | let mut roots = Vec::new(); |
44 | roots.push(IncludeRustFiles::member(root.clone())); | 44 | roots.extend(folder_roots.iter().cloned().map(IncludeRustFiles::member)); |
45 | for ws in workspaces.iter() { | 45 | for ws in workspaces.iter() { |
46 | roots.extend(IncludeRustFiles::from_roots(ws.to_roots())); | 46 | roots.extend(IncludeRustFiles::from_roots(ws.to_roots())); |
47 | } | 47 | } |
48 | 48 | ||
49 | let (mut vfs, roots) = Vfs::new(roots); | 49 | let (mut vfs, vfs_roots) = Vfs::new(roots); |
50 | let roots_to_scan = roots.len(); | 50 | let roots_to_scan = vfs_roots.len(); |
51 | for r in roots { | 51 | for r in vfs_roots { |
52 | let is_local = vfs.root2path(r).starts_with(&root); | 52 | let vfs_root_path = vfs.root2path(r); |
53 | let is_local = folder_roots.iter().any(|it| vfs_root_path.starts_with(it)); | ||
53 | change.add_root(SourceRootId(r.0.into()), is_local); | 54 | change.add_root(SourceRootId(r.0.into()), is_local); |
54 | } | 55 | } |
55 | 56 | ||
@@ -68,7 +69,7 @@ impl ServerWorldState { | |||
68 | analysis_host.apply_change(change); | 69 | analysis_host.apply_change(change); |
69 | ServerWorldState { | 70 | ServerWorldState { |
70 | roots_to_scan, | 71 | roots_to_scan, |
71 | root, | 72 | roots: folder_roots, |
72 | workspaces: Arc::new(workspaces), | 73 | workspaces: Arc::new(workspaces), |
73 | analysis_host, | 74 | analysis_host, |
74 | vfs: Arc::new(RwLock::new(vfs)), | 75 | vfs: Arc::new(RwLock::new(vfs)), |
@@ -90,7 +91,8 @@ impl ServerWorldState { | |||
90 | match c { | 91 | match c { |
91 | VfsChange::AddRoot { root, files } => { | 92 | VfsChange::AddRoot { root, files } => { |
92 | let root_path = self.vfs.read().root2path(root); | 93 | let root_path = self.vfs.read().root2path(root); |
93 | if root_path.starts_with(&self.root) { | 94 | let is_local = self.roots.iter().any(|r| root_path.starts_with(r)); |
95 | if is_local { | ||
94 | self.roots_to_scan -= 1; | 96 | self.roots_to_scan -= 1; |
95 | for (file, path, text) in files { | 97 | for (file, path, text) in files { |
96 | change.add_file( | 98 | change.add_file( |
@@ -193,4 +195,9 @@ impl ServerWorld { | |||
193 | res.push_str(&self.analysis.status()); | 195 | res.push_str(&self.analysis.status()); |
194 | res | 196 | res |
195 | } | 197 | } |
198 | |||
199 | pub fn workspace_root_for(&self, file_id: FileId) -> Option<&Path> { | ||
200 | let path = self.vfs.read().file2path(VfsFile(file_id.0.into())); | ||
201 | self.workspaces.iter().find_map(|ws| ws.workspace_root_for(&path)) | ||
202 | } | ||
196 | } | 203 | } |