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
39b9a4bPhilipp Mildenberger
helix-term/src/application.rs+1−1
@@ -665,7 +665,7 @@ impl Application {
665
665
666 macro_rules! language_server {
666 macro_rules! language_server {
667 () => {
667 () => {
668− match self.editor.language_servers.get_by_id(server_id) {
668+ match self.editor.language_server_by_id(server_id) {
669 Some(language_server) => language_server,
669 Some(language_server) => language_server,
670 None => {
670 None => {
671 warn!("can't find language server with id `{}`", server_id);
671 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(
301 flat_diag.reserve(diags.len());
301 flat_diag.reserve(diags.len());
302
302
303 for (diag, ls) in diags {
303 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) {
305 flat_diag.push(PickerDiagnostic {
305 flat_diag.push(PickerDiagnostic {
306 url: url.clone(),
306 url: url.clone(),
307 diag,
307 diag,
@@ -725,7 +725,7 @@ pub fn code_action(cx: &mut Context) {
725
725
726 // always present here
726 // always present here
727 let action = action.unwrap();
727 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 {
729 editor.set_error("Language Server disappeared");
729 editor.set_error("Language Server disappeared");
730 return;
730 return;
731 };
731 };
@@ -772,8 +772,7 @@ pub fn execute_lsp_command(editor: &mut Editor, language_server_id: usize, cmd:
772 // the command is executed on the server and communicated back
772 // the command is executed on the server and communicated back
773 // to the client asynchronously using workspace edits
773 // to the client asynchronously using workspace edits
774 let future = match editor
774 let future = match editor
775− .language_servers
776− .get_by_id(language_server_id)
775+ .language_server_by_id(language_server_id)
777 .and_then(|language_server| language_server.command(cmd))
776 .and_then(|language_server| language_server.command(cmd))
778 {
777 {
779 Some(future) => future,
778 Some(future) => future,
helix-term/src/ui/completion.rs+23−24
@@ -212,6 +212,23 @@ impl Completion {
212
212
213 let (view, doc) = current!(editor);
213 let (view, doc) = current!(editor);
214
214
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+
215 match event {
232 match event {
216 PromptEvent::Abort => {}
233 PromptEvent::Abort => {}
217 PromptEvent::Update => {
234 PromptEvent::Update => {
@@ -236,17 +253,11 @@ impl Completion {
236 // always present here
253 // always present here
237 let item = item.unwrap();
254 let item = item.unwrap();
238
255
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−
245 let transaction = item_to_transaction(
256 let transaction = item_to_transaction(
246 doc,
257 doc,
247 view.id,
258 view.id,
248 item,
259 item,
249− offset_encoding,
260+ language_server!(item).offset_encoding(),
250 trigger_offset,
261 trigger_offset,
251 true,
262 true,
252 replace_mode,
263 replace_mode,
@@ -262,11 +273,8 @@ impl Completion {
262 // always present here
273 // always present here
263 let mut item = item.unwrap().clone();
274 let mut item = item.unwrap().clone();
264
275
265− let offset_encoding = editor
276+ let language_server = language_server!(item);
266− .language_servers
267− .get_by_id(item.language_server_id)
268− .expect("language server disappeared between completion request and application")
269− .offset_encoding();
277+ let offset_encoding = language_server.offset_encoding();
270
278
271 let language_server = editor
279 let language_server = editor
272 .language_servers
280 .language_servers
@@ -401,20 +409,11 @@ impl Completion {
401 Some(item) if !item.resolved => item.clone(),
409 Some(item) if !item.resolved => item.clone(),
402 _ => return false,
410 _ => return false,
403 };
411 };
404− let language_server = match cx
412+
405− .editor
406− .language_servers
407− .get_by_id(current_item.language_server_id)
413+ let Some(language_server) = cx.editor.language_server_by_id(current_item.language_server_id) else { return false; };
408− {
409− Some(language_server) => language_server,
410− None => return false,
411− };
412
414
413 // This method should not block the compositor so we handle the response asynchronously.
415 // 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()) {
416+ let Some(future) = language_server.resolve_completion_item(current_item.item.clone()) else { return false; };
415− Some(future) => future,
416− None => return false,
417− };
418
417
419 cx.callback(
418 cx.callback(
420 future,
419 future,
helix-view/src/editor.rs+6−1
@@ -874,7 +874,7 @@ pub struct Editor {
874 /// times during rendering and should not be set by other functions.
874 /// times during rendering and should not be set by other functions.
875 pub cursor_cache: Cell<Option<Option<Position>>>,
875 pub cursor_cache: Cell<Option<Option<Position>>>,
876 /// When a new completion request is sent to the server old
876 /// 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
878 /// request is associated with a channel that cancels
878 /// request is associated with a channel that cancels
879 /// when the channel is dropped. That channel is stored
879 /// when the channel is dropped. That channel is stored
880 /// here. When a new completion request is sent this
880 /// here. When a new completion request is sent this
@@ -1093,6 +1093,11 @@ impl Editor {
1093 self._refresh();
1093 self._refresh();
1094 }
1094 }
1095
1095
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+
1096 /// Refreshes the language server for a given document
1101 /// Refreshes the language server for a given document
1097 pub fn refresh_language_servers(&mut self, doc_id: DocumentId) -> Option<()> {
1102 pub fn refresh_language_servers(&mut self, doc_id: DocumentId) -> Option<()> {
1098 self.launch_language_servers(doc_id)
1103 self.launch_language_servers(doc_id)