Skip to main content

gpui_base/input/editor/lsp/
mod.rs

1use anyhow::Result;
2use gpui::{App, Context, Hsla, SharedString, Task, Window};
3use ropey::Rope;
4use std::rc::Rc;
5
6use crate::input::{EditorMode, InputBaseState, RopeExt};
7
8mod code_actions;
9mod completions;
10mod definitions;
11mod document_colors;
12mod hover;
13mod overlay;
14mod semantic_tokens;
15
16pub use code_actions::*;
17pub use completions::*;
18pub use definitions::*;
19pub use document_colors::*;
20pub use hover::*;
21pub use overlay::*;
22pub use semantic_tokens::*;
23
24/// Host hook to show a document when following an LSP location
25/// (Go to Definition), modeled after the `window/showDocument` request.
26///
27/// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#window_showDocument
28///
29/// Called before the built-in behavior. Return `true` if the host has shown
30/// the document (e.g. opened a docs window for a virtual/external URI);
31/// return `false` to fall through to the default handling (`external` URIs
32/// open in the browser, anything else jumps within the current document).
33pub type ShowDocumentHandler =
34    Rc<dyn Fn(&lsp_types::ShowDocumentParams, &mut Window, &mut App) -> bool>;
35
36/// LSP ServerCapabilities
37///
38/// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#serverCapabilities
39pub struct Lsp {
40    /// The completion provider.
41    pub completion_provider: Option<Rc<dyn CompletionProvider>>,
42    /// The code action providers.
43    pub code_action_providers: Vec<Rc<dyn CodeActionProvider>>,
44    /// The hover provider.
45    pub hover_provider: Option<Rc<dyn HoverProvider>>,
46    /// The definition provider.
47    pub definition_provider: Option<Rc<dyn DefinitionProvider>>,
48    /// The document color provider.
49    pub document_color_provider: Option<Rc<dyn DocumentColorProvider>>,
50    /// The range semantic tokens provider.
51    pub semantic_tokens_provider: Option<Rc<dyn DocumentRangeSemanticTokensProvider>>,
52    /// Optional host hook to show documents for Go to Definition locations,
53    /// following the `window/showDocument` request (see [`ShowDocumentHandler`]).
54    ///
55    /// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#window_showDocument
56    pub show_document: Option<ShowDocumentHandler>,
57
58    /// Display options for the completion popover.
59    pub completion_menu: CompletionMenuOptions,
60
61    pub(crate) document_colors: Vec<(lsp_types::Range, Hsla)>,
62    /// Cached semantic tokens as absolute position ranges + theme token-type
63    /// names. Color is resolved from the name at paint time so theme switches
64    /// take effect without a refetch.
65    pub(crate) semantic_tokens: Vec<(lsp_types::Range, SharedString)>,
66    pub(crate) _hover_task: Task<Result<()>>,
67    pub(crate) _document_color_task: Task<()>,
68    pub(crate) _semantic_tokens_task: Task<()>,
69}
70
71impl Default for Lsp {
72    fn default() -> Self {
73        Self {
74            completion_provider: None,
75            code_action_providers: vec![],
76            hover_provider: None,
77            definition_provider: None,
78            document_color_provider: None,
79            completion_menu: CompletionMenuOptions::default(),
80            semantic_tokens_provider: None,
81            show_document: None,
82            document_colors: vec![],
83            semantic_tokens: vec![],
84            _hover_task: Task::ready(Ok(())),
85            _document_color_task: Task::ready(()),
86            _semantic_tokens_task: Task::ready(()),
87        }
88    }
89}
90
91impl Lsp {
92    /// Update the LSP when the text changes.
93    pub(crate) fn update(
94        &mut self,
95        text: &Rope,
96        window: &mut Window,
97        cx: &mut Context<InputBaseState<EditorMode>>,
98    ) {
99        self.update_document_colors(text, window, cx);
100        self.update_semantic_tokens(text, window, cx);
101    }
102
103    /// Reset all LSP states.
104    pub(crate) fn reset(&mut self) {
105        self.document_colors.clear();
106        self.semantic_tokens.clear();
107        self._hover_task = Task::ready(Ok(()));
108        self._document_color_task = Task::ready(());
109        self._semantic_tokens_task = Task::ready(());
110    }
111}
112
113impl InputBaseState<EditorMode> {
114    /// Apply a list of [`lsp_types::TextEdit`] to mutate the text.
115    pub fn apply_lsp_edits(
116        &mut self,
117        text_edits: &Vec<lsp_types::TextEdit>,
118        window: &mut Window,
119        cx: &mut Context<Self>,
120    ) {
121        for edit in text_edits {
122            let start = self.text.position_to_offset(&edit.range.start);
123            let end = self.text.position_to_offset(&edit.range.end);
124
125            let range_utf16 = self.range_to_utf16(&(start..end));
126            self.replace_text_in_range_silent(Some(range_utf16), &edit.new_text, window, cx);
127        }
128    }
129}