From a942c576277da0af1a3c899322f77ea20830eeeb Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Thu, 18 Sep 2025 14:17:18 +0800 Subject: [PATCH] editor: Refactor the LSP config. --- crates/story/examples/code-editor.rs | 6 +-- crates/ui/src/input/lsp.rs | 36 +++++++++++++-- crates/ui/src/input/mode.rs | 26 +---------- crates/ui/src/input/state.rs | 67 ++-------------------------- 4 files changed, 41 insertions(+), 94 deletions(-) diff --git a/crates/story/examples/code-editor.rs b/crates/story/examples/code-editor.rs index 0651f7ec..57606fd1 100644 --- a/crates/story/examples/code-editor.rs +++ b/crates/story/examples/code-editor.rs @@ -489,9 +489,9 @@ impl Example { .default_value(default_language.1) .placeholder("Enter your code here..."); - editor.set_completion_provider(Some(Rc::new(lsp_store.clone())), cx); - editor.add_code_action_provider(Rc::new(lsp_store.clone()), cx); - editor.add_code_action_provider(Rc::new(TextConvertor), cx); + editor.lsp.completion_provider = Some(Rc::new(lsp_store.clone())); + editor.lsp.code_action_providers = + vec![Rc::new(lsp_store.clone()), Rc::new(TextConvertor)]; editor }); diff --git a/crates/ui/src/input/lsp.rs b/crates/ui/src/input/lsp.rs index 44dfaa67..51e00e48 100644 --- a/crates/ui/src/input/lsp.rs +++ b/crates/ui/src/input/lsp.rs @@ -12,6 +12,21 @@ use crate::input::{ InputState, RopeExt, }; +/// LSP ServerCapabilities +/// +/// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#serverCapabilities +#[derive(Clone, Default)] +pub struct Lsp { + /// The completion provider. + pub completion_provider: Option>, + /// The code action providers. + pub code_action_providers: Vec>, + /// The hover provider. + pub hover_provider: Option>, +} + +impl Lsp {} + /// A trait for providing code completions based on the current input state and context. pub trait CompletionProvider { /// Fetches completions based on the given byte offset. @@ -68,6 +83,21 @@ pub trait CodeActionProvider { ) -> Task>; } +pub trait HoverProvider { + /// Hover provider + /// + /// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_hover + fn hover( + &self, + _text: &Rope, + _offset: usize, + _window: &mut Window, + _cx: &mut App, + ) -> Task>> { + Task::ready(Ok(None)) + } +} + impl InputState { pub(crate) fn hide_context_menu(&mut self, cx: &mut Context) { self.context_menu = None; @@ -125,7 +155,7 @@ impl InputState { return; } - let Some(provider) = self.mode.completion_provider().cloned() else { + let Some(provider) = self.lsp.completion_provider.clone() else { return; }; @@ -220,7 +250,7 @@ impl InputState { window: &mut Window, cx: &mut Context, ) { - let providers = self.mode.code_action_providers(); + let providers = self.lsp.code_action_providers.clone(); let menu = match self.context_menu.as_ref() { Some(ContextMenu::CodeAction(menu)) => Some(menu), _ => None, @@ -289,7 +319,7 @@ impl InputState { window: &mut Window, cx: &mut Context, ) { - let providers = self.mode.code_action_providers(); + let providers = self.lsp.code_action_providers.clone(); let Some(provider) = providers .iter() .find(|provider| provider.id() == item.provider_id) diff --git a/crates/ui/src/input/mode.rs b/crates/ui/src/input/mode.rs index f942d5be..948b1242 100644 --- a/crates/ui/src/input/mode.rs +++ b/crates/ui/src/input/mode.rs @@ -5,11 +5,9 @@ use gpui::{App, SharedString}; use rope::Rope; use tree_sitter::{InputEdit, Point}; +use super::text_wrapper::TextWrapper; use crate::highlighter::DiagnosticSet; use crate::highlighter::SyntaxHighlighter; -use crate::input::{CodeActionProvider, CompletionProvider}; - -use super::text_wrapper::TextWrapper; #[derive(Debug, Copy, Clone)] pub struct TabSize { @@ -59,8 +57,6 @@ pub enum InputMode { language: SharedString, highlighter: Rc>>, diagnostics: DiagnosticSet, - completion_provider: Option>, - code_action_providers: Vec>, }, } @@ -241,26 +237,6 @@ impl InputMode { _ => None, } } - - pub(super) fn completion_provider(&self) -> Option<&Rc> { - match self { - InputMode::CodeEditor { - completion_provider, - .. - } => completion_provider.as_ref(), - _ => None, - } - } - - pub(super) fn code_action_providers(&self) -> Vec> { - match self { - InputMode::CodeEditor { - code_action_providers, - .. - } => code_action_providers.clone(), - _ => vec![], - } - } } #[cfg(test)] diff --git a/crates/ui/src/input/state.rs b/crates/ui/src/input/state.rs index 3f908421..a3106945 100644 --- a/crates/ui/src/input/state.rs +++ b/crates/ui/src/input/state.rs @@ -32,7 +32,7 @@ use super::{ use crate::input::{ popovers::{ContextMenu, DiagnosticPopover}, search::{self, SearchPanel}, - Position, + Lsp, Position, }; use crate::input::{RopeExt as _, Selection}; use crate::{highlighter::DiagnosticSet, input::text_wrapper::LineItem}; @@ -299,6 +299,8 @@ pub struct InputState { /// A flag to indicate if we are currently inserting a completion item. pub(super) completion_inserting: bool, + pub lsp: Lsp, + /// To remember the horizontal column (x-coordinate) of the cursor position for keep column for move up/down. /// /// The first element is the x-coordinate (Pixels), preferred to use this. @@ -376,6 +378,7 @@ impl InputState { preferred_column: None, placeholder: SharedString::default(), mask_pattern: MaskPattern::default(), + lsp: Lsp::default(), diagnostic_popover: None, context_menu: None, completion_inserting: false, @@ -433,8 +436,6 @@ impl InputState { highlighter: Rc::new(RefCell::new(None)), line_number: true, diagnostics: DiagnosticSet::default(), - code_action_providers: vec![], - completion_provider: None, }; self.searchable = true; self @@ -446,66 +447,6 @@ impl InputState { self } - /// Add a code action provider for the code editor mode. - /// - /// Only for `InputMode::CodeEditor`. - pub fn add_code_action_provider( - &mut self, - provider: Rc, - cx: &mut Context, - ) { - if let InputMode::CodeEditor { - code_action_providers, - .. - } = &mut self.mode - { - code_action_providers.push(provider); - cx.notify(); - } - } - - /// Remove a code action provider for the code editor mode. - pub fn remove_code_action_provider(&mut self, id: &str, cx: &mut Context) { - if let InputMode::CodeEditor { - code_action_providers, - .. - } = &mut self.mode - { - code_action_providers.retain(|p| p.id().as_str() != id); - cx.notify(); - } - } - - /// Clear all code action providers for the code editor mode. - pub fn clear_code_action_providers(&mut self, cx: &mut Context) { - if let InputMode::CodeEditor { - code_action_providers, - .. - } = &mut self.mode - { - code_action_providers.clear(); - cx.notify(); - } - } - - /// Set the completion provider for the code editor mode. - /// - /// Only for `InputMode::CodeEditor`. - pub fn set_completion_provider( - &mut self, - provider: Option>, - cx: &mut Context, - ) { - if let InputMode::CodeEditor { - completion_provider, - .. - } = &mut self.mode - { - *completion_provider = provider; - cx.notify(); - } - } - /// Set placeholder pub fn placeholder(mut self, placeholder: impl Into) -> Self { self.placeholder = placeholder.into();