Add function Editor::language_server_by_id and refactor/simplify related code, also don't 'crash' in completion menu if language_server somehow disappeared

This commit is contained in:
Philipp Mildenberger 2023-04-05 18:50:05 +02:00
parent 521cdec5a1
commit 39b9a4bba2
4 changed files with 33 additions and 30 deletions

View File

@ -665,7 +665,7 @@ pub async fn handle_language_server_message(
macro_rules! language_server {
() => {
match self.editor.language_servers.get_by_id(server_id) {
match self.editor.language_server_by_id(server_id) {
Some(language_server) => language_server,
None => {
warn!("can't find language server with id `{}`", server_id);

View File

@ -301,7 +301,7 @@ fn diag_picker(
flat_diag.reserve(diags.len());
for (diag, ls) in diags {
if let Some(ls) = cx.editor.language_servers.get_by_id(ls) {
if let Some(ls) = cx.editor.language_server_by_id(ls) {
flat_diag.push(PickerDiagnostic {
url: url.clone(),
diag,
@ -725,7 +725,7 @@ pub fn code_action(cx: &mut Context) {
// always present here
let action = action.unwrap();
let Some(language_server) = editor.language_servers.get_by_id(action.language_server_id) else {
let Some(language_server) = editor.language_server_by_id(action.language_server_id) else {
editor.set_error("Language Server disappeared");
return;
};
@ -772,8 +772,7 @@ pub fn execute_lsp_command(editor: &mut Editor, language_server_id: usize, cmd:
// the command is executed on the server and communicated back
// to the client asynchronously using workspace edits
let future = match editor
.language_servers
.get_by_id(language_server_id)
.language_server_by_id(language_server_id)
.and_then(|language_server| language_server.command(cmd))
{
Some(future) => future,

View File

@ -212,6 +212,23 @@ fn completion_changes(transaction: &Transaction, trigger_offset: usize) -> Vec<C
let (view, doc) = current!(editor);
macro_rules! language_server {
($item:expr) => {
match editor
.language_servers
.get_by_id($item.language_server_id)
{
Some(ls) => ls,
None => {
editor.set_error("language server disappeared between completion request and application");
// TODO close the completion menu somehow,
// currently there is no trivial way to access the EditorView to close the completion menu
return;
}
}
};
}
match event {
PromptEvent::Abort => {}
PromptEvent::Update => {
@ -236,17 +253,11 @@ fn completion_changes(transaction: &Transaction, trigger_offset: usize) -> Vec<C
// always present here
let item = item.unwrap();
let offset_encoding = editor
.language_servers
.get_by_id(item.language_server_id)
.expect("language server disappeared between completion request and application")
.offset_encoding();
let transaction = item_to_transaction(
doc,
view.id,
item,
offset_encoding,
language_server!(item).offset_encoding(),
trigger_offset,
true,
replace_mode,
@ -262,11 +273,8 @@ fn completion_changes(transaction: &Transaction, trigger_offset: usize) -> Vec<C
// always present here
let mut item = item.unwrap().clone();
let offset_encoding = editor
.language_servers
.get_by_id(item.language_server_id)
.expect("language server disappeared between completion request and application")
.offset_encoding();
let language_server = language_server!(item);
let offset_encoding = language_server.offset_encoding();
let language_server = editor
.language_servers
@ -401,20 +409,11 @@ pub fn ensure_item_resolved(&mut self, cx: &mut commands::Context) -> bool {
Some(item) if !item.resolved => item.clone(),
_ => return false,
};
let language_server = match cx
.editor
.language_servers
.get_by_id(current_item.language_server_id)
{
Some(language_server) => language_server,
None => return false,
};
let Some(language_server) = cx.editor.language_server_by_id(current_item.language_server_id) else { return false; };
// This method should not block the compositor so we handle the response asynchronously.
let future = match language_server.resolve_completion_item(current_item.item.clone()) {
Some(future) => future,
None => return false,
};
let Some(future) = language_server.resolve_completion_item(current_item.item.clone()) else { return false; };
cx.callback(
future,

View File

@ -874,7 +874,7 @@ pub struct Editor {
/// times during rendering and should not be set by other functions.
pub cursor_cache: Cell<Option<Option<Position>>>,
/// When a new completion request is sent to the server old
/// unifinished request must be dropped. Each completion
/// unfinished request must be dropped. Each completion
/// request is associated with a channel that cancels
/// when the channel is dropped. That channel is stored
/// here. When a new completion request is sent this
@ -1093,6 +1093,11 @@ fn set_theme_impl(&mut self, theme: Theme, preview: ThemeAction) {
self._refresh();
}
#[inline]
pub fn language_server_by_id(&self, language_server_id: usize) -> Option<&helix_lsp::Client> {
self.language_servers.get_by_id(language_server_id)
}
/// Refreshes the language server for a given document
pub fn refresh_language_servers(&mut self, doc_id: DocumentId) -> Option<()> {
self.launch_language_servers(doc_id)