on master help sign in
Filter out language servers which fail to spawn (#8374)
commit080a085fa796fe2b71b5932b704d465695fba824 authorwoojiq <122799969+woojiq@users.noreply.github.com> dateTue 26 Sep 2023, 23:12 (3 years ago) parent2776233
2 files changed+74−61
helix-lsp/src/lib.rs+22−18 helix-view/src/editor.rs+52−43
helix-lsp/src/lib.rs+22−18
@@ -749,36 +749,40 @@ impl Registry {
749749 }
750750 }
751751
752− pub fn get(
753− &mut self,
754− language_config: &LanguageConfiguration,
755− doc_path: Option<&std::path::PathBuf>,
756− root_dirs: &[PathBuf],
752+ pub fn get<'a>(
753+ &'a mut self,
754+ language_config: &'a LanguageConfiguration,
755+ doc_path: Option<&'a std::path::PathBuf>,
756+ root_dirs: &'a [PathBuf],
757757 enable_snippets: bool,
758− ) -> Result<HashMap<LanguageServerName, Arc<Client>>> {
759− language_config
760− .language_servers
761− .iter()
762− .map(|LanguageServerFeatures { name, .. }| {
758+ ) -> impl Iterator<Item = (LanguageServerName, Result<Arc<Client>>)> + 'a {
759+ language_config.language_servers.iter().map(
760+ move |LanguageServerFeatures { name, .. }| {
763761 if let Some(clients) = self.inner.get(name) {
764762 if let Some((_, client)) = clients.iter().enumerate().find(|(i, client)| {
765763 client.try_add_doc(&language_config.roots, root_dirs, doc_path, *i == 0)
766764 }) {
767− return Ok((name.to_owned(), client.clone()));
765+ return (name.to_owned(), Ok(client.clone()));
768766 }
769767 }
770− let client = self.start_client(
768+ match self.start_client(
771769 name.clone(),
772770 language_config,
773771 doc_path,
774772 root_dirs,
775773 enable_snippets,
776− )?;
777− let clients = self.inner.entry(name.clone()).or_default();
778− clients.push(client.clone());
779− Ok((name.clone(), client))
780− })
781− .collect()
774+ ) {
775+ Ok(client) => {
776+ self.inner
777+ .entry(name.to_owned())
778+ .or_default()
779+ .push(client.clone());
780+ (name.clone(), Ok(client))
781+ }
782+ Err(err) => (name.to_owned(), Err(err)),
783+ }
784+ },
785+ )
782786 }
783787
784788 pub fn iter_clients(&self) -> impl Iterator<Item = &Arc<Client>> {
helix-view/src/editor.rs+52−43
@@ -1188,71 +1188,80 @@ impl Editor {
11881188 }
11891189
11901190 /// Refreshes the language server for a given document
1191− pub fn refresh_language_servers(&mut self, doc_id: DocumentId) -> Option<()> {
1191+ pub fn refresh_language_servers(&mut self, doc_id: DocumentId) {
11921192 self.launch_language_servers(doc_id)
11931193 }
11941194
11951195 /// Launch a language server for a given document
1196− fn launch_language_servers(&mut self, doc_id: DocumentId) -> Option<()> {
1196+ fn launch_language_servers(&mut self, doc_id: DocumentId) {
11971197 if !self.config().lsp.enable {
1198− return None;
1198+ return;
11991199 }
12001200 // if doc doesn't have a URL it's a scratch buffer, ignore it
1201− let doc = self.documents.get_mut(&doc_id)?;
1202− let doc_url = doc.url()?;
1201+ let Some(doc) = self.documents.get_mut(&doc_id) else {
1202+ return;
1203+ };
1204+ let Some(doc_url) = doc.url() else {
1205+ return;
1206+ };
12031207 let (lang, path) = (doc.language.clone(), doc.path().cloned());
12041208 let config = doc.config.load();
12051209 let root_dirs = &config.workspace_lsp_roots;
12061210
1207− // try to find language servers based on the language name
1208− let language_servers = lang.as_ref().and_then(|language| {
1211+ // store only successfully started language servers
1212+ let language_servers = lang.as_ref().map_or_else(HashMap::default, |language| {
12091213 self.language_servers
12101214 .get(language, path.as_ref(), root_dirs, config.lsp.snippets)
1211− .map_err(|e| {
1212− log::error!(
1213− "Failed to initialize the language servers for `{}` {{ {} }}",
1214− language.scope(),
1215− e
1216− )
1215+ .filter_map(|(lang, client)| match client {
1216+ Ok(client) => Some((lang, client)),
1217+ Err(err) => {
1218+ log::error!(
1219+ "Failed to initialize the language servers for `{}` - `{}` {{ {} }}",
1220+ language.scope(),
1221+ lang,
1222+ err
1223+ );
1224+ None
1225+ }
12171226 })
1218− .ok()
1227+ .collect::<HashMap<_, _>>()
12191228 });
12201229
1221− if let Some(language_servers) = language_servers {
1222− let language_id = doc.language_id().map(ToOwned::to_owned).unwrap_or_default();
1223−
1224− // only spawn new language servers if the servers aren't the same
1225−
1226− let doc_language_servers_not_in_registry =
1227− doc.language_servers.iter().filter(|(name, doc_ls)| {
1228− language_servers
1229− .get(*name)
1230− .map_or(true, |ls| ls.id() != doc_ls.id())
1231− });
1230+ if language_servers.is_empty() {
1231+ return;
1232+ }
12321233
1233− for (_, language_server) in doc_language_servers_not_in_registry {
1234− tokio::spawn(language_server.text_document_did_close(doc.identifier()));
1235− }
1234+ let language_id = doc.language_id().map(ToOwned::to_owned).unwrap_or_default();
12361235
1237− let language_servers_not_in_doc = language_servers.iter().filter(|(name, ls)| {
1238− doc.language_servers
1236+ // only spawn new language servers if the servers aren't the same
1237+ let doc_language_servers_not_in_registry =
1238+ doc.language_servers.iter().filter(|(name, doc_ls)| {
1239+ language_servers
12391240 .get(*name)
1240− .map_or(true, |doc_ls| ls.id() != doc_ls.id())
1241+ .map_or(true, |ls| ls.id() != doc_ls.id())
12411242 });
12421243
1243− for (_, language_server) in language_servers_not_in_doc {
1244− // TODO: this now races with on_init code if the init happens too quickly
1245− tokio::spawn(language_server.text_document_did_open(
1246− doc_url.clone(),
1247− doc.version(),
1248− doc.text(),
1249− language_id.clone(),
1250− ));
1251− }
1244+ for (_, language_server) in doc_language_servers_not_in_registry {
1245+ tokio::spawn(language_server.text_document_did_close(doc.identifier()));
1246+ }
1247+
1248+ let language_servers_not_in_doc = language_servers.iter().filter(|(name, ls)| {
1249+ doc.language_servers
1250+ .get(*name)
1251+ .map_or(true, |doc_ls| ls.id() != doc_ls.id())
1252+ });
12521253
1253− doc.language_servers = language_servers;
1254+ for (_, language_server) in language_servers_not_in_doc {
1255+ // TODO: this now races with on_init code if the init happens too quickly
1256+ tokio::spawn(language_server.text_document_did_open(
1257+ doc_url.clone(),
1258+ doc.version(),
1259+ doc.text(),
1260+ language_id.clone(),
1261+ ));
12541262 }
1255− Some(())
1263+
1264+ doc.language_servers = language_servers;
12561265 }
12571266
12581267 fn _refresh(&mut self) {
@@ -1454,7 +1463,7 @@ impl Editor {
14541463 doc.set_version_control_head(self.diff_providers.get_current_head_name(&path));
14551464
14561465 let id = self.new_document(doc);
1457− let _ = self.launch_language_servers(id);
1466+ self.launch_language_servers(id);
14581467
14591468 id
14601469 };