Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'src/edi/lsp_mn.rs')
| -rw-r--r-- | src/edi/lsp_mn.rs | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/src/edi/lsp_mn.rs b/src/edi/lsp_mn.rs new file mode 100644 index 0000000..45cfd24 --- /dev/null +++ b/src/edi/lsp_mn.rs @@ -0,0 +1,119 @@ +use std::collections::HashMap; +use std::io::BufReader; +use std::path::PathBuf; +use std::process::Stdio; +use std::sync::Arc; + +use lsp_server::Connection; +use lsp_types::*; +use tokio::sync::oneshot::Sender; +use tree_house::Language; +use url::Url; +use winit::window::Window; + +pub struct LSPM { + pub four: HashMap<(Language, PathBuf), LoadedLSP>, +} + +pub struct LoadedLSP { + pub c: Arc<Client>, + pub iot: Option<IoThreads>, + pub comms: std::thread::JoinHandle<()>, +} +impl LoadedLSP { + pub fn status(&self) { + assert!(!self.comms.is_finished()); + } +} +mod stdio; +impl LSPM { + pub fn load( + &mut self, + workspace: &PathBuf, + l: Language, + vsc: Option<serde_json::Value>, + ) -> Option<(Arc<Client>, Option<Sender<Arc<dyn Window + 'static>>>)> + { + let ra_conn_used = self + .four + .values() + .any(|x| x.c.lsp_data.1.name == "rust-analyzer"); + let e = match self.four.entry((l, workspace.to_owned())) { + std::collections::hash_map::Entry::Occupied(x) => { + let x = x.get(); + return Some((x.c.clone(), None)); + } + std::collections::hash_map::Entry::Vacant(e) => e, + }; + let (l, w) = load(workspace, l, vsc, ra_conn_used)?; + let v = e.insert(l); + Some((v.c.clone(), Some(w))) + } +} +use crate::edi::lsp_mn::stdio::IoThreads; +use crate::lsp::Client; +pub fn load( + workspace: &PathBuf, + l: Language, + vsc: Option<serde_json::Value>, + ra_conn_used: bool, +) -> Option<(LoadedLSP, Sender<Arc<dyn Window>>)> { + let l = super::LOADER.language(l).config(); + let use_builtin_ra = l.language_id == "rust" && !ra_conn_used; + let (Connection { sender, receiver }, conf, iot) = if use_builtin_ra { + let (_jh, a) = super::ra::ra(workspace.clone()); + ( + a, + ( + &super::LOADER.language_server_configs()["rust-analyzer"], + &l.language_servers[0], + ), + None, + ) + } else { + let (mut c, conf) = l + .language_servers + .iter() + .find_map(|l| { + let lc = super::LOADER + .language_server_configs() + .get(&l.name)?; + std::process::Command::new(&lc.command) + .args(&lc.args) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::inherit()) + .spawn() + .ok() + .zip(Some((lc, l))) + }) + .ok_or_else(|| { + log::error!( + "no lsp for this language; install one of {:?}", + l.language_servers + ) + }) + .ok()?; + + let (x, iot) = stdio::transport( + BufReader::new(c.stdout.take().unwrap()), + c.stdin.take().unwrap(), + ); + (x, conf, Some(iot)) + }; + let (c, t2, changed) = crate::lsp::run( + (sender, receiver), + WorkspaceFolder { + uri: Url::from_file_path(&workspace).unwrap(), + name: workspace + .file_name() + .unwrap() + .to_string_lossy() + .into_owned(), + }, + vsc.and_then(|x| x.as_object()?.get(&conf.1.name).cloned()), + conf, + ) + .unwrap(); + Some((LoadedLSP { iot, c: Arc::new(c), comms: t2 }, changed)) +} |