gpui_base/input/editor/lsp/
mod.rs1use 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
24pub type ShowDocumentHandler =
34 Rc<dyn Fn(&lsp_types::ShowDocumentParams, &mut Window, &mut App) -> bool>;
35
36pub struct Lsp {
40 pub completion_provider: Option<Rc<dyn CompletionProvider>>,
42 pub code_action_providers: Vec<Rc<dyn CodeActionProvider>>,
44 pub hover_provider: Option<Rc<dyn HoverProvider>>,
46 pub definition_provider: Option<Rc<dyn DefinitionProvider>>,
48 pub document_color_provider: Option<Rc<dyn DocumentColorProvider>>,
50 pub semantic_tokens_provider: Option<Rc<dyn DocumentRangeSemanticTokensProvider>>,
52 pub show_document: Option<ShowDocumentHandler>,
57
58 pub completion_menu: CompletionMenuOptions,
60
61 completion_highlighter: Rc<CompletionHighlighter>,
66
67 pub(crate) document_colors: Vec<(lsp_types::Range, Hsla)>,
68 pub(crate) semantic_tokens: Vec<(lsp_types::Range, SharedString)>,
72 pub(crate) _hover_task: Task<Result<()>>,
73 pub(crate) _definition_task: Task<Result<()>>,
74 pub(crate) _document_color_task: Task<()>,
75 pub(crate) _semantic_tokens_task: Task<()>,
76}
77
78impl Default for Lsp {
79 fn default() -> Self {
80 Self {
81 completion_provider: None,
82 code_action_providers: vec![],
83 hover_provider: None,
84 definition_provider: None,
85 document_color_provider: None,
86 completion_menu: CompletionMenuOptions::default(),
87 completion_highlighter: Rc::new(highlight_prefix),
88 semantic_tokens_provider: None,
89 show_document: None,
90 document_colors: vec![],
91 semantic_tokens: vec![],
92 _hover_task: Task::ready(Ok(())),
93 _definition_task: Task::ready(Ok(())),
94 _document_color_task: Task::ready(()),
95 _semantic_tokens_task: Task::ready(()),
96 }
97 }
98}
99
100impl Lsp {
101 pub fn with_completion_highlighter(mut self, highlighter: Rc<CompletionHighlighter>) -> Self {
103 self.set_completion_highlighter(highlighter);
104 self
105 }
106
107 pub fn completion_highlighter(&self) -> &Rc<CompletionHighlighter> {
109 &self.completion_highlighter
110 }
111
112 pub fn set_completion_highlighter(&mut self, highlighter: Rc<CompletionHighlighter>) {
116 self.completion_highlighter = highlighter;
117 }
118
119 pub(crate) fn update(
121 &mut self,
122 text: &Rope,
123 window: &mut Window,
124 cx: &mut Context<InputBaseState<EditorMode>>,
125 ) {
126 self.update_document_colors(text, window, cx);
127 self.update_semantic_tokens(text, window, cx);
128 }
129
130 pub(crate) fn reset(&mut self) {
132 self.document_colors.clear();
133 self.semantic_tokens.clear();
134 self._hover_task = Task::ready(Ok(()));
135 self._definition_task = Task::ready(Ok(()));
136 self._document_color_task = Task::ready(());
137 self._semantic_tokens_task = Task::ready(());
138 }
139}
140
141impl InputBaseState<EditorMode> {
142 pub fn apply_lsp_edits(
144 &mut self,
145 text_edits: &Vec<lsp_types::TextEdit>,
146 window: &mut Window,
147 cx: &mut Context<Self>,
148 ) {
149 for edit in text_edits {
150 let start = self.text.position_to_offset(&edit.range.start);
151 let end = self.text.position_to_offset(&edit.range.end);
152
153 let range_utf16 = self.range_to_utf16(&(start..end));
154 self.replace_text_in_range_silent(Some(range_utf16), &edit.new_text, window, cx);
155 }
156 }
157}
158
159#[cfg(test)]
160mod tests {
161 use super::*;
162
163 #[test]
164 fn test_lsp_builder() {
165 let highlighter: Rc<CompletionHighlighter> = Rc::new(highlight_contains);
166 let mut lsp = Lsp::default().with_completion_highlighter(highlighter.clone());
167 assert!(Rc::ptr_eq(lsp.completion_highlighter(), &highlighter));
168
169 let replacement: Rc<CompletionHighlighter> = Rc::new(highlight_characters);
170 lsp.set_completion_highlighter(replacement.clone());
171 assert!(Rc::ptr_eq(lsp.completion_highlighter(), &replacement));
172 }
173}