From 451fe528bbc71e2712c02c1ee0d7ac6fcc1a058b Mon Sep 17 00:00:00 2001
From: Philipp Mildenberger <philipp@mildenberger.me>
Date: Mon, 20 Mar 2023 01:18:08 +0100
Subject: [PATCH] Filter out already seen language servers in requests that can
 be sent to multiple language servers (code-action, completion, symbol
 pickers)

---
 helix-term/src/commands.rs     |  3 +++
 helix-term/src/commands/lsp.rs | 15 ++++++++++++++-
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index e2a5975b..d602eaa2 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -4243,9 +4243,12 @@ pub fn completion(cx: &mut Context) {
     let text = savepoint.text.clone();
     let cursor = savepoint.cursor();
 
+    let mut seen_language_servers = HashSet::new();
+
     let mut futures: FuturesUnordered<_> = doc
         .language_servers_with_feature(LanguageServerFeature::Completion)
         // TODO this should probably already been filtered in something like "language_servers_with_feature"
+        .filter(|ls| seen_language_servers.insert(ls.id()))
         .filter_map(|language_server| {
             let language_server_id = language_server.id();
             let offset_encoding = language_server.offset_encoding();
diff --git a/helix-term/src/commands/lsp.rs b/helix-term/src/commands/lsp.rs
index a1bd291c..6a024bed 100644
--- a/helix-term/src/commands/lsp.rs
+++ b/helix-term/src/commands/lsp.rs
@@ -37,7 +37,12 @@ use crate::{
 };
 
 use std::{
-    cmp::Ordering, collections::BTreeMap, fmt::Write, future::Future, path::PathBuf, sync::Arc,
+    cmp::Ordering,
+    collections::{BTreeMap, HashSet},
+    fmt::Write,
+    future::Future,
+    path::PathBuf,
+    sync::Arc,
 };
 
 impl ui::menu::Item for lsp::Location {
@@ -351,8 +356,11 @@ pub fn symbol_picker(cx: &mut Context) {
     }
     let doc = doc!(cx.editor);
 
+    let mut seen_language_servers = HashSet::new();
+
     let mut futures: FuturesUnordered<_> = doc
         .language_servers_with_feature(LanguageServerFeature::DocumentSymbols)
+        .filter(|ls| seen_language_servers.insert(ls.id()))
         .filter_map(|ls| {
             let request = ls.document_symbols(doc.identifier())?;
             Some((request, ls.offset_encoding(), doc.identifier()))
@@ -413,8 +421,10 @@ pub fn workspace_symbol_picker(cx: &mut Context) {
 
     let get_symbols = move |pattern: String, editor: &mut Editor| {
         let doc = doc!(editor);
+        let mut seen_language_servers = HashSet::new();
         let mut futures: FuturesUnordered<_> = doc
             .language_servers_with_feature(LanguageServerFeature::WorkspaceSymbols)
+            .filter(|ls| seen_language_servers.insert(ls.id()))
             .filter_map(|ls| Some((ls.workspace_symbols(pattern.clone())?, ls.offset_encoding())))
             .map(|(request, offset_encoding)| async move {
                 let json = request.await?;
@@ -573,8 +583,11 @@ pub fn code_action(cx: &mut Context) {
 
     let selection_range = doc.selection(view.id).primary();
 
+    let mut seen_language_servers = HashSet::new();
+
     let mut futures: FuturesUnordered<_> = doc
         .language_servers_with_feature(LanguageServerFeature::CodeAction)
+        .filter(|ls| seen_language_servers.insert(ls.id()))
         // TODO this should probably already been filtered in something like "language_servers_with_feature"
         .filter_map(|language_server| {
             let offset_encoding = language_server.offset_encoding();