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.rs119
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))
+}