editor: Refactor the LSP config.

This commit is contained in:
Jason Lee 2025-09-18 14:17:18 +08:00
parent 3fe9bc8de0
commit a942c57627
4 changed files with 41 additions and 94 deletions

View file

@ -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
});

View file

@ -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<Rc<dyn CompletionProvider>>,
/// The code action providers.
pub code_action_providers: Vec<Rc<dyn CodeActionProvider>>,
/// The hover provider.
pub hover_provider: Option<Rc<dyn HoverProvider>>,
}
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<Result<()>>;
}
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<Result<Option<lsp_types::Hover>>> {
Task::ready(Ok(None))
}
}
impl InputState {
pub(crate) fn hide_context_menu(&mut self, cx: &mut Context<Self>) {
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<Self>,
) {
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<Self>,
) {
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)

View file

@ -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<RefCell<Option<SyntaxHighlighter>>>,
diagnostics: DiagnosticSet,
completion_provider: Option<Rc<dyn CompletionProvider>>,
code_action_providers: Vec<Rc<dyn CodeActionProvider>>,
},
}
@ -241,26 +237,6 @@ impl InputMode {
_ => None,
}
}
pub(super) fn completion_provider(&self) -> Option<&Rc<dyn CompletionProvider>> {
match self {
InputMode::CodeEditor {
completion_provider,
..
} => completion_provider.as_ref(),
_ => None,
}
}
pub(super) fn code_action_providers(&self) -> Vec<Rc<dyn CodeActionProvider>> {
match self {
InputMode::CodeEditor {
code_action_providers,
..
} => code_action_providers.clone(),
_ => vec![],
}
}
}
#[cfg(test)]

View file

@ -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<dyn super::CodeActionProvider>,
cx: &mut Context<Self>,
) {
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<Self>) {
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<Self>) {
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<Rc<dyn super::CompletionProvider>>,
cx: &mut Context<Self>,
) {
if let InputMode::CodeEditor {
completion_provider,
..
} = &mut self.mode
{
*completion_provider = provider;
cx.notify();
}
}
/// Set placeholder
pub fn placeholder(mut self, placeholder: impl Into<SharedString>) -> Self {
self.placeholder = placeholder.into();