From 83d4fe8e3a03c1ce6cacd73e27bfbfc0b5689258 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 4 Feb 2022 17:45:00 -0800 Subject: [PATCH] Start work on code actions Just print out the returned code actions for now Co-Authored-By: Nathan Sobo --- crates/editor/src/editor.rs | 19 +++++++++ crates/editor/src/multi_buffer.rs | 15 +++++++ crates/language/src/buffer.rs | 65 ++++++++++++++++++++++++++++++- crates/lsp/src/lsp.rs | 11 ++++++ 4 files changed, 109 insertions(+), 1 deletion(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index b0f7bbe478..9f13c9fb41 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -124,6 +124,7 @@ action!(FoldSelectedRanges); action!(Scroll, Vector2F); action!(Select, SelectPhase); action!(ShowCompletions); +action!(ShowCodeActions); action!(ConfirmCompletion, Option); pub fn init(cx: &mut MutableAppContext, path_openers: &mut Vec>) { @@ -239,6 +240,7 @@ pub fn init(cx: &mut MutableAppContext, path_openers: &mut Vec) { + let position = if let Some(selection) = self.newest_anchor_selection() { + selection.head() + } else { + return; + }; + + let actions = self + .buffer + .update(cx, |buffer, cx| buffer.code_actions(position.clone(), cx)); + cx.spawn(|this, cx| async move { + dbg!(actions.await.unwrap()); + }) + .detach(); + } + fn hide_completions(&mut self, cx: &mut ViewContext) -> Option { cx.notify(); self.completion_tasks.clear(); diff --git a/crates/editor/src/multi_buffer.rs b/crates/editor/src/multi_buffer.rs index 592323fb0d..bbcc4a47a7 100644 --- a/crates/editor/src/multi_buffer.rs +++ b/crates/editor/src/multi_buffer.rs @@ -860,6 +860,21 @@ impl MultiBuffer { }) } + pub fn code_actions( + &self, + position: T, + cx: &mut ModelContext, + ) -> Task>> + where + T: ToOffset, + { + let anchor = self.read(cx).anchor_before(position); + let buffer = self.buffers.borrow()[&anchor.buffer_id].buffer.clone(); + let code_actions = + buffer.update(cx, |buffer, cx| buffer.code_actions(anchor.text_anchor, cx)); + cx.spawn(|this, cx| async move { code_actions.await }) + } + pub fn completions( &self, position: T, diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index 18e620fcd2..fb5958fcd4 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -14,7 +14,7 @@ use clock::ReplicaId; use futures::FutureExt as _; use gpui::{AppContext, Entity, ModelContext, MutableAppContext, Task}; use lazy_static::lazy_static; -use lsp::LanguageServer; +use lsp::{CodeActionKind, LanguageServer}; use parking_lot::Mutex; use postage::{prelude::Stream, sink::Sink, watch}; use similar::{ChangeTag, TextDiff}; @@ -1848,6 +1848,69 @@ impl Buffer { } } + pub fn code_actions( + &self, + position: T, + cx: &mut ModelContext, + ) -> Task>> + where + T: ToPointUtf16, + { + let file = if let Some(file) = self.file.as_ref() { + file + } else { + return Task::ready(Ok(Default::default())); + }; + + if let Some(file) = file.as_local() { + let server = if let Some(language_server) = self.language_server.as_ref() { + language_server.server.clone() + } else { + return Task::ready(Ok(Default::default())); + }; + let abs_path = file.abs_path(cx); + let position = position.to_point_utf16(self); + + cx.spawn(|this, mut cx| async move { + let actions = server + .request::(lsp::CodeActionParams { + text_document: lsp::TextDocumentIdentifier::new( + lsp::Url::from_file_path(abs_path).unwrap(), + ), + range: lsp::Range::new( + position.to_lsp_position(), + position.to_lsp_position(), + ), + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + context: lsp::CodeActionContext { + diagnostics: Default::default(), + only: Some(vec![ + lsp::CodeActionKind::QUICKFIX, + lsp::CodeActionKind::REFACTOR, + lsp::CodeActionKind::REFACTOR_EXTRACT, + ]), + }, + }) + .await? + .unwrap_or_default() + .into_iter() + .filter_map(|entry| { + if let lsp::CodeActionOrCommand::CodeAction(action) = entry { + Some(action) + } else { + None + } + }) + .collect(); + Ok(actions) + }) + } else { + log::info!("code actions are not implemented for guests"); + Task::ready(Ok(Default::default())) + } + } + pub fn apply_additional_edits_for_completion( &mut self, completion: Completion, diff --git a/crates/lsp/src/lsp.rs b/crates/lsp/src/lsp.rs index 5cc1fee8aa..287d825c8f 100644 --- a/crates/lsp/src/lsp.rs +++ b/crates/lsp/src/lsp.rs @@ -238,6 +238,17 @@ impl LanguageServer { link_support: Some(true), ..Default::default() }), + code_action: Some(CodeActionClientCapabilities { + code_action_literal_support: Some(CodeActionLiteralSupport { + code_action_kind: CodeActionKindLiteralSupport { + value_set: vec![ + CodeActionKind::REFACTOR.as_str().into(), + CodeActionKind::QUICKFIX.as_str().into(), + ], + }, + }), + ..Default::default() + }), completion: Some(CompletionClientCapabilities { completion_item: Some(CompletionItemCapability { snippet_support: Some(true),