on master help sign in
Add function `Editor::language_server_by_id` and refactor/simplify related code, also don't 'crash' in completion menu if language_server somehow disappeared
commit39b9a4bba2a026844348886c9d9f2026a3d6f658 authorPhilipp Mildenberger <philipp@mildenberger.me> dateWed 5 Apr 2023, 18:50 (4 years ago) parent521cdec
4 files changed+33−30
helix-term/src/application.rs+1−1 helix-term/src/commands/lsp.rs+3−4 helix-term/src/ui/completion.rs+23−24 helix-view/src/editor.rs+6−1
helix-term/src/application.rs+1−1
@@ -665,7 +665,7 @@ impl Application {
665665
666666 macro_rules! language_server {
667667 () => {
668− match self.editor.language_servers.get_by_id(server_id) {
668+ match self.editor.language_server_by_id(server_id) {
669669 Some(language_server) => language_server,
670670 None => {
671671 warn!("can't find language server with id `{}`", server_id);
helix-term/src/commands/lsp.rs+3−4
@@ -301,7 +301,7 @@ fn diag_picker(
301301 flat_diag.reserve(diags.len());
302302
303303 for (diag, ls) in diags {
304− if let Some(ls) = cx.editor.language_servers.get_by_id(ls) {
304+ if let Some(ls) = cx.editor.language_server_by_id(ls) {
305305 flat_diag.push(PickerDiagnostic {
306306 url: url.clone(),
307307 diag,
@@ -725,7 +725,7 @@ pub fn code_action(cx: &mut Context) {
725725
726726 // always present here
727727 let action = action.unwrap();
728− let Some(language_server) = editor.language_servers.get_by_id(action.language_server_id) else {
728+ let Some(language_server) = editor.language_server_by_id(action.language_server_id) else {
729729 editor.set_error("Language Server disappeared");
730730 return;
731731 };
@@ -772,8 +772,7 @@ pub fn execute_lsp_command(editor: &mut Editor, language_server_id: usize, cmd:
772772 // the command is executed on the server and communicated back
773773 // to the client asynchronously using workspace edits
774774 let future = match editor
775− .language_servers
776− .get_by_id(language_server_id)
775+ .language_server_by_id(language_server_id)
777776 .and_then(|language_server| language_server.command(cmd))
778777 {
779778 Some(future) => future,
helix-term/src/ui/completion.rs+23−24
@@ -212,6 +212,23 @@ impl Completion {
212212
213213 let (view, doc) = current!(editor);
214214
215+ macro_rules! language_server {
216+ ($item:expr) => {
217+ match editor
218+ .language_servers
219+ .get_by_id($item.language_server_id)
220+ {
221+ Some(ls) => ls,
222+ None => {
223+ editor.set_error("language server disappeared between completion request and application");
224+ // TODO close the completion menu somehow,
225+ // currently there is no trivial way to access the EditorView to close the completion menu
226+ return;
227+ }
228+ }
229+ };
230+ }
231+
215232 match event {
216233 PromptEvent::Abort => {}
217234 PromptEvent::Update => {
@@ -236,17 +253,11 @@ impl Completion {
236253 // always present here
237254 let item = item.unwrap();
238255
239− let offset_encoding = editor
240− .language_servers
241− .get_by_id(item.language_server_id)
242− .expect("language server disappeared between completion request and application")
243− .offset_encoding();
244−
245256 let transaction = item_to_transaction(
246257 doc,
247258 view.id,
248259 item,
249− offset_encoding,
260+ language_server!(item).offset_encoding(),
250261 trigger_offset,
251262 true,
252263 replace_mode,
@@ -262,11 +273,8 @@ impl Completion {
262273 // always present here
263274 let mut item = item.unwrap().clone();
264275
265− let offset_encoding = editor
266− .language_servers
267− .get_by_id(item.language_server_id)
268− .expect("language server disappeared between completion request and application")
269− .offset_encoding();
276+ let language_server = language_server!(item);
277+ let offset_encoding = language_server.offset_encoding();
270278
271279 let language_server = editor
272280 .language_servers
@@ -401,20 +409,11 @@ impl Completion {
401409 Some(item) if !item.resolved => item.clone(),
402410 _ => return false,
403411 };
404− let language_server = match cx
405− .editor
406− .language_servers
407− .get_by_id(current_item.language_server_id)
408− {
409− Some(language_server) => language_server,
410− None => return false,
411− };
412+
413+ let Some(language_server) = cx.editor.language_server_by_id(current_item.language_server_id) else { return false; };
412414
413415 // This method should not block the compositor so we handle the response asynchronously.
414− let future = match language_server.resolve_completion_item(current_item.item.clone()) {
415− Some(future) => future,
416− None => return false,
417− };
416+ let Some(future) = language_server.resolve_completion_item(current_item.item.clone()) else { return false; };
418417
419418 cx.callback(
420419 future,
helix-view/src/editor.rs+6−1
@@ -874,7 +874,7 @@ pub struct Editor {
874874 /// times during rendering and should not be set by other functions.
875875 pub cursor_cache: Cell<Option<Option<Position>>>,
876876 /// When a new completion request is sent to the server old
877− /// unifinished request must be dropped. Each completion
877+ /// unfinished request must be dropped. Each completion
878878 /// request is associated with a channel that cancels
879879 /// when the channel is dropped. That channel is stored
880880 /// here. When a new completion request is sent this
@@ -1093,6 +1093,11 @@ impl Editor {
10931093 self._refresh();
10941094 }
10951095
1096+ #[inline]
1097+ pub fn language_server_by_id(&self, language_server_id: usize) -> Option<&helix_lsp::Client> {
1098+ self.language_servers.get_by_id(language_server_id)
1099+ }
1100+
10961101 /// Refreshes the language server for a given document
10971102 pub fn refresh_language_servers(&mut self, doc_id: DocumentId) -> Option<()> {
10981103 self.launch_language_servers(doc_id)