@@ -7,7 +7,7 @@ use crate::{
LanguageServerName, LspAdapter, LspAdapterDelegate, PLAIN_TEXT,
};
use anyhow::{anyhow, Context as _, Result};
-use collections::{hash_map, HashMap};
+use collections::{hash_map, HashMap, HashSet};
use futures::TryFutureExt;
use futures::{
channel::{mpsc, oneshot},
@@ -188,6 +188,22 @@ impl LanguageRegistry {
self.state.write().reload();
}
+ /// Reorders the list of language servers for the given language.
+ ///
+ /// Uses the provided list of ordered [`CachedLspAdapters`] as the desired order.
+ ///
+ /// Any existing language servers not present in `ordered_lsp_adapters` will be
+ /// appended to the end.
+ pub fn reorder_language_servers(
+ &self,
+ language: &Arc<Language>,
+ ordered_lsp_adapters: Vec<Arc<CachedLspAdapter>>,
+ ) {
+ self.state
+ .write()
+ .reorder_language_servers(language, ordered_lsp_adapters);
+ }
+
/// Removes the specified languages and grammars from the registry.
pub fn remove_languages(
&self,
@@ -920,6 +936,36 @@ impl LanguageRegistryState {
*self.subscription.0.borrow_mut() = ();
}
+ /// Reorders the list of language servers for the given language.
+ ///
+ /// Uses the provided list of ordered [`CachedLspAdapters`] as the desired order.
+ ///
+ /// Any existing language servers not present in `ordered_lsp_adapters` will be
+ /// appended to the end.
+ fn reorder_language_servers(
+ &mut self,
+ language: &Arc<Language>,
+ ordered_lsp_adapters: Vec<Arc<CachedLspAdapter>>,
+ ) {
+ let Some(lsp_adapters) = self.lsp_adapters.get_mut(&language.config.name) else {
+ return;
+ };
+
+ let ordered_lsp_adapter_ids = ordered_lsp_adapters
+ .iter()
+ .map(|lsp_adapter| lsp_adapter.name.clone())
+ .collect::<HashSet<_>>();
+
+ let mut new_lsp_adapters = ordered_lsp_adapters;
+ for adapter in lsp_adapters.iter() {
+ if !ordered_lsp_adapter_ids.contains(&adapter.name) {
+ new_lsp_adapters.push(adapter.clone());
+ }
+ }
+
+ *lsp_adapters = new_lsp_adapters;
+ }
+
fn remove_languages(
&mut self,
languages_to_remove: &[Arc<str>],
@@ -2999,9 +2999,18 @@ impl Project {
.join(", ")
);
- for adapter in enabled_lsp_adapters {
- self.start_language_server(worktree, adapter, language.clone(), cx);
+ for adapter in &enabled_lsp_adapters {
+ self.start_language_server(worktree, adapter.clone(), language.clone(), cx);
}
+
+ // After starting all the language servers, reorder them to reflect the desired order
+ // based on the settings.
+ //
+ // This is done, in part, to ensure that language servers loaded at different points
+ // (e.g., native vs extension) still end up in the right order at the end, rather than
+ // it being based on which language server happened to be loaded in first.
+ self.languages()
+ .reorder_language_servers(&language, enabled_lsp_adapters);
}
fn start_language_server(
@@ -10247,8 +10256,10 @@ impl Project {
buffer: &Buffer,
cx: &AppContext,
) -> Option<(&Arc<CachedLspAdapter>, &Arc<LanguageServer>)> {
- self.language_servers_for_buffer(buffer, cx)
- .find(|s| s.0.is_primary)
+ // The list of language servers is ordered based on the `language_servers` setting
+ // for each language, thus we can consider the first one in the list to be the
+ // primary one.
+ self.language_servers_for_buffer(buffer, cx).next()
}
pub fn language_server_for_buffer(