From 3507bcb97aaaafba10d55c101bd295f3ab4fed4f Mon Sep 17 00:00:00 2001 From: Roberto Vidal Date: Thu, 11 Apr 2019 08:08:19 +0200 Subject: Adds support for multiple editor workspaces on initialization This is a quick, partial fix for #1104 --- crates/ra_lsp_server/src/main.rs | 13 +++++++++- crates/ra_lsp_server/src/main_loop.rs | 31 +++++++++++++---------- crates/ra_lsp_server/src/server_world.rs | 20 ++++++++------- crates/ra_lsp_server/tests/heavy_tests/support.rs | 2 +- 4 files changed, 41 insertions(+), 25 deletions(-) (limited to 'crates/ra_lsp_server') diff --git a/crates/ra_lsp_server/src/main.rs b/crates/ra_lsp_server/src/main.rs index eb4091a3d..82f52a6e8 100644 --- a/crates/ra_lsp_server/src/main.rs +++ b/crates/ra_lsp_server/src/main.rs @@ -40,12 +40,23 @@ fn main_inner() -> Result<()> { run_server(ra_lsp_server::server_capabilities(), receiver, sender, |params, r, s| { let root = params.root_uri.and_then(|it| it.to_file_path().ok()).unwrap_or(cwd); + let workspace_roots = params + .workspace_folders + .map(|workspaces| { + workspaces + .into_iter() + .filter_map(|it| it.uri.to_file_path().ok()) + .collect::>() + }) + .filter(|workspaces| !workspaces.is_empty()) + .unwrap_or_else(|| vec![root]); + let opts = params .initialization_options .and_then(|v| InitializationOptions::deserialize(v).ok()) .unwrap_or(InitializationOptions::default()); - ra_lsp_server::main_loop(root, opts, r, s) + ra_lsp_server::main_loop(workspace_roots, opts, r, s) })?; log::info!("shutting down IO..."); threads.join()?; diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index 82410bee3..07ac4917a 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs @@ -48,7 +48,7 @@ enum Task { const THREADPOOL_SIZE: usize = 8; pub fn main_loop( - ws_root: PathBuf, + ws_roots: Vec, options: InitializationOptions, msg_receiver: &Receiver, msg_sender: &Sender, @@ -59,23 +59,26 @@ pub fn main_loop( // FIXME: support dynamic workspace loading. let workspaces = { let ws_worker = workspace_loader(); - ws_worker.sender().send(ws_root.clone()).unwrap(); - match ws_worker.receiver().recv().unwrap() { - Ok(ws) => vec![ws], - Err(e) => { - log::error!("loading workspace failed: {}", e); - - show_message( - req::MessageType::Error, - format!("rust-analyzer failed to load workspace: {}", e), - msg_sender, - ); - Vec::new() + let mut loaded_workspaces = Vec::new(); + for ws_root in &ws_roots { + ws_worker.sender().send(ws_root.clone()).unwrap(); + match ws_worker.receiver().recv().unwrap() { + Ok(ws) => loaded_workspaces.push(ws), + Err(e) => { + log::error!("loading workspace failed: {}", e); + + show_message( + req::MessageType::Error, + format!("rust-analyzer failed to load workspace: {}", e), + msg_sender, + ); + } } } + loaded_workspaces }; - let mut state = ServerWorldState::new(ws_root.clone(), workspaces); + let mut state = ServerWorldState::new(ws_roots, workspaces); log::info!("server initialized, serving requests"); diff --git a/crates/ra_lsp_server/src/server_world.rs b/crates/ra_lsp_server/src/server_world.rs index 4b1d592bb..45ad8e24e 100644 --- a/crates/ra_lsp_server/src/server_world.rs +++ b/crates/ra_lsp_server/src/server_world.rs @@ -24,7 +24,7 @@ use crate::{ #[derive(Debug)] pub struct ServerWorldState { pub roots_to_scan: usize, - pub root: PathBuf, + pub roots: Vec, pub workspaces: Arc>, pub analysis_host: AnalysisHost, pub vfs: Arc>, @@ -37,19 +37,20 @@ pub struct ServerWorld { } impl ServerWorldState { - pub fn new(root: PathBuf, workspaces: Vec) -> ServerWorldState { + pub fn new(folder_roots: Vec, workspaces: Vec) -> ServerWorldState { let mut change = AnalysisChange::new(); let mut roots = Vec::new(); - roots.push(IncludeRustFiles::member(root.clone())); + roots.extend(folder_roots.iter().cloned().map(IncludeRustFiles::member)); for ws in workspaces.iter() { roots.extend(IncludeRustFiles::from_roots(ws.to_roots())); } - let (mut vfs, roots) = Vfs::new(roots); - let roots_to_scan = roots.len(); - for r in roots { - let is_local = vfs.root2path(r).starts_with(&root); + let (mut vfs, vfs_roots) = Vfs::new(roots); + let roots_to_scan = vfs_roots.len(); + for r in vfs_roots { + let vfs_root_path = vfs.root2path(r); + let is_local = folder_roots.iter().any(|it| vfs_root_path.starts_with(it)); change.add_root(SourceRootId(r.0.into()), is_local); } @@ -68,7 +69,7 @@ impl ServerWorldState { analysis_host.apply_change(change); ServerWorldState { roots_to_scan, - root, + roots: folder_roots, workspaces: Arc::new(workspaces), analysis_host, vfs: Arc::new(RwLock::new(vfs)), @@ -90,7 +91,8 @@ impl ServerWorldState { match c { VfsChange::AddRoot { root, files } => { let root_path = self.vfs.read().root2path(root); - if root_path.starts_with(&self.root) { + let is_local = self.roots.iter().any(|r| root_path.starts_with(r)); + if is_local { self.roots_to_scan -= 1; for (file, path, text) in files { change.add_file( diff --git a/crates/ra_lsp_server/tests/heavy_tests/support.rs b/crates/ra_lsp_server/tests/heavy_tests/support.rs index ab9db3dd4..4ea6760a1 100644 --- a/crates/ra_lsp_server/tests/heavy_tests/support.rs +++ b/crates/ra_lsp_server/tests/heavy_tests/support.rs @@ -63,7 +63,7 @@ impl Server { 128, move |mut msg_receiver, mut msg_sender| { main_loop( - path, + vec![path], InitializationOptions::default(), &mut msg_receiver, &mut msg_sender, -- cgit v1.2.3