Adds support for multiple editor workspaces on initialization
This is a quick, partial fix for #1104
This commit is contained in:
parent
23b876bc3b
commit
3507bcb97a
5 changed files with 40 additions and 31 deletions
|
@ -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::<Vec<_>>()
|
||||
})
|
||||
.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()?;
|
||||
|
|
|
@ -48,7 +48,7 @@ enum Task {
|
|||
const THREADPOOL_SIZE: usize = 8;
|
||||
|
||||
pub fn main_loop(
|
||||
ws_root: PathBuf,
|
||||
ws_roots: Vec<PathBuf>,
|
||||
options: InitializationOptions,
|
||||
msg_receiver: &Receiver<RawMessage>,
|
||||
msg_sender: &Sender<RawMessage>,
|
||||
|
@ -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);
|
||||
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,
|
||||
);
|
||||
Vec::new()
|
||||
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");
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ use crate::{
|
|||
#[derive(Debug)]
|
||||
pub struct ServerWorldState {
|
||||
pub roots_to_scan: usize,
|
||||
pub root: PathBuf,
|
||||
pub roots: Vec<PathBuf>,
|
||||
pub workspaces: Arc<Vec<ProjectWorkspace>>,
|
||||
pub analysis_host: AnalysisHost,
|
||||
pub vfs: Arc<RwLock<Vfs>>,
|
||||
|
@ -37,19 +37,20 @@ pub struct ServerWorld {
|
|||
}
|
||||
|
||||
impl ServerWorldState {
|
||||
pub fn new(root: PathBuf, workspaces: Vec<ProjectWorkspace>) -> ServerWorldState {
|
||||
pub fn new(folder_roots: Vec<PathBuf>, workspaces: Vec<ProjectWorkspace>) -> 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(
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -17,13 +17,6 @@ export class Server {
|
|||
let folder: string = '.';
|
||||
if (workspace.workspaceFolders !== undefined) {
|
||||
folder = workspace.workspaceFolders[0].uri.fsPath.toString();
|
||||
|
||||
if (workspace.workspaceFolders.length > 1) {
|
||||
// Tell the user that we do not support multi-root workspaces yet
|
||||
window.showWarningMessage(
|
||||
'Multi-root workspaces are not currently supported'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const run: lc.Executable = {
|
||||
|
|
Loading…
Reference in a new issue