Merge pull request #2332 from zed-industries/per-server-code-action-kinds

Julia created

Allow each language adapter to provide their own code action kinds array

Change summary

crates/language/src/language.rs        | 16 ++++++++++++++++
crates/lsp/src/lsp.rs                  | 11 +++++++++++
crates/project/src/project.rs          | 14 ++++----------
crates/zed/src/languages/typescript.rs | 10 ++++++++++
4 files changed, 41 insertions(+), 10 deletions(-)

Detailed changes

crates/language/src/language.rs 🔗

@@ -20,6 +20,7 @@ use futures::{
 use gpui::{executor::Background, MutableAppContext, Task};
 use highlight_map::HighlightMap;
 use lazy_static::lazy_static;
+use lsp::CodeActionKind;
 use parking_lot::{Mutex, RwLock};
 use postage::watch;
 use regex::Regex;
@@ -140,6 +141,10 @@ impl CachedLspAdapter {
         self.adapter.cached_server_binary(container_dir).await
     }
 
+    pub fn code_action_kinds(&self) -> Option<Vec<CodeActionKind>> {
+        self.adapter.code_action_kinds()
+    }
+
     pub fn workspace_configuration(
         &self,
         cx: &mut MutableAppContext,
@@ -225,6 +230,16 @@ pub trait LspAdapter: 'static + Send + Sync {
         None
     }
 
+    fn code_action_kinds(&self) -> Option<Vec<CodeActionKind>> {
+        Some(vec![
+            CodeActionKind::EMPTY,
+            CodeActionKind::QUICKFIX,
+            CodeActionKind::REFACTOR,
+            CodeActionKind::REFACTOR_EXTRACT,
+            CodeActionKind::SOURCE,
+        ])
+    }
+
     async fn disk_based_diagnostic_sources(&self) -> Vec<String> {
         Default::default()
     }
@@ -825,6 +840,7 @@ impl LanguageRegistry {
                 &binary.path,
                 &binary.arguments,
                 &root_path,
+                adapter.code_action_kinds(),
                 cx,
             )?;
 

crates/lsp/src/lsp.rs 🔗

@@ -40,6 +40,7 @@ pub struct LanguageServer {
     outbound_tx: channel::Sender<Vec<u8>>,
     name: String,
     capabilities: ServerCapabilities,
+    code_action_kinds: Option<Vec<CodeActionKind>>,
     notification_handlers: Arc<Mutex<HashMap<&'static str, NotificationHandler>>>,
     response_handlers: Arc<Mutex<Option<HashMap<usize, ResponseHandler>>>>,
     executor: Arc<executor::Background>,
@@ -110,6 +111,7 @@ impl LanguageServer {
         binary_path: &Path,
         arguments: &[T],
         root_path: &Path,
+        code_action_kinds: Option<Vec<CodeActionKind>>,
         cx: AsyncAppContext,
     ) -> Result<Self> {
         let working_dir = if root_path.is_dir() {
@@ -135,6 +137,7 @@ impl LanguageServer {
             stout,
             Some(server),
             root_path,
+            code_action_kinds,
             cx,
             |notification| {
                 log::info!(
@@ -160,6 +163,7 @@ impl LanguageServer {
         stdout: Stdout,
         server: Option<Child>,
         root_path: &Path,
+        code_action_kinds: Option<Vec<CodeActionKind>>,
         cx: AsyncAppContext,
         on_unhandled_notification: F,
     ) -> Self
@@ -197,6 +201,7 @@ impl LanguageServer {
             response_handlers,
             name: Default::default(),
             capabilities: Default::default(),
+            code_action_kinds,
             next_id: Default::default(),
             outbound_tx,
             executor: cx.background(),
@@ -207,6 +212,10 @@ impl LanguageServer {
         }
     }
 
+    pub fn code_action_kinds(&self) -> Option<Vec<CodeActionKind>> {
+        self.code_action_kinds.clone()
+    }
+
     async fn handle_input<Stdout, F>(
         stdout: Stdout,
         mut on_unhandled_notification: F,
@@ -715,6 +724,7 @@ impl LanguageServer {
             stdout_reader,
             None,
             Path::new("/"),
+            None,
             cx.clone(),
             |_| {},
         );
@@ -725,6 +735,7 @@ impl LanguageServer {
                 stdin_reader,
                 None,
                 Path::new("/"),
+                None,
                 cx,
                 move |msg| {
                     notifications_tx

crates/project/src/project.rs 🔗

@@ -3773,7 +3773,7 @@ impl Project {
             worktree = file.worktree.clone();
             buffer_abs_path = file.as_local().map(|f| f.abs_path(cx));
         } else {
-            return Task::ready(Ok(Default::default()));
+            return Task::ready(Ok(Vec::new()));
         };
         let range = buffer.anchor_before(range.start)..buffer.anchor_before(range.end);
 
@@ -3783,13 +3783,13 @@ impl Project {
             {
                 server.clone()
             } else {
-                return Task::ready(Ok(Default::default()));
+                return Task::ready(Ok(Vec::new()));
             };
 
             let lsp_range = range_to_lsp(range.to_point_utf16(buffer));
             cx.foreground().spawn(async move {
                 if lang_server.capabilities().code_action_provider.is_none() {
-                    return Ok(Default::default());
+                    return Ok(Vec::new());
                 }
 
                 Ok(lang_server
@@ -3802,13 +3802,7 @@ impl Project {
                         partial_result_params: Default::default(),
                         context: lsp::CodeActionContext {
                             diagnostics: relevant_diagnostics,
-                            only: Some(vec![
-                                lsp::CodeActionKind::EMPTY,
-                                lsp::CodeActionKind::QUICKFIX,
-                                lsp::CodeActionKind::REFACTOR,
-                                lsp::CodeActionKind::REFACTOR_EXTRACT,
-                                lsp::CodeActionKind::SOURCE,
-                            ]),
+                            only: lang_server.code_action_kinds(),
                         },
                     })
                     .await?

crates/zed/src/languages/typescript.rs 🔗

@@ -4,6 +4,7 @@ use async_trait::async_trait;
 use client::http::HttpClient;
 use futures::StreamExt;
 use language::{LanguageServerBinary, LanguageServerName, LspAdapter};
+use lsp::CodeActionKind;
 use serde_json::json;
 use smol::fs;
 use std::{
@@ -142,6 +143,15 @@ impl LspAdapter for TypeScriptLspAdapter {
         .log_err()
     }
 
+    fn code_action_kinds(&self) -> Option<Vec<CodeActionKind>> {
+        Some(vec![
+            CodeActionKind::QUICKFIX,
+            CodeActionKind::REFACTOR,
+            CodeActionKind::REFACTOR_EXTRACT,
+            CodeActionKind::SOURCE,
+        ])
+    }
+
     async fn label_for_completion(
         &self,
         item: &lsp::CompletionItem,