mirror of
https://github.com/helix-editor/helix.git
synced 2024-11-22 17:36:19 +04:00
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:
parent
521cdec5a1
commit
39b9a4bba2
@ -665,7 +665,7 @@ pub async fn handle_language_server_message(
|
|||||||
|
|
||||||
macro_rules! language_server {
|
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,
|
Some(language_server) => language_server,
|
||||||
None => {
|
None => {
|
||||||
warn!("can't find language server with id `{}`", server_id);
|
warn!("can't find language server with id `{}`", server_id);
|
||||||
|
@ -301,7 +301,7 @@ fn diag_picker(
|
|||||||
flat_diag.reserve(diags.len());
|
flat_diag.reserve(diags.len());
|
||||||
|
|
||||||
for (diag, ls) in diags {
|
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 {
|
flat_diag.push(PickerDiagnostic {
|
||||||
url: url.clone(),
|
url: url.clone(),
|
||||||
diag,
|
diag,
|
||||||
@ -725,7 +725,7 @@ pub fn code_action(cx: &mut Context) {
|
|||||||
|
|
||||||
// always present here
|
// always present here
|
||||||
let action = action.unwrap();
|
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");
|
editor.set_error("Language Server disappeared");
|
||||||
return;
|
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
|
// the command is executed on the server and communicated back
|
||||||
// to the client asynchronously using workspace edits
|
// to the client asynchronously using workspace edits
|
||||||
let future = match editor
|
let future = match editor
|
||||||
.language_servers
|
.language_server_by_id(language_server_id)
|
||||||
.get_by_id(language_server_id)
|
|
||||||
.and_then(|language_server| language_server.command(cmd))
|
.and_then(|language_server| language_server.command(cmd))
|
||||||
{
|
{
|
||||||
Some(future) => future,
|
Some(future) => future,
|
||||||
|
@ -212,6 +212,23 @@ fn completion_changes(transaction: &Transaction, trigger_offset: usize) -> Vec<C
|
|||||||
|
|
||||||
let (view, doc) = current!(editor);
|
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 {
|
match event {
|
||||||
PromptEvent::Abort => {}
|
PromptEvent::Abort => {}
|
||||||
PromptEvent::Update => {
|
PromptEvent::Update => {
|
||||||
@ -236,17 +253,11 @@ fn completion_changes(transaction: &Transaction, trigger_offset: usize) -> Vec<C
|
|||||||
// always present here
|
// always present here
|
||||||
let item = item.unwrap();
|
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(
|
let transaction = item_to_transaction(
|
||||||
doc,
|
doc,
|
||||||
view.id,
|
view.id,
|
||||||
item,
|
item,
|
||||||
offset_encoding,
|
language_server!(item).offset_encoding(),
|
||||||
trigger_offset,
|
trigger_offset,
|
||||||
true,
|
true,
|
||||||
replace_mode,
|
replace_mode,
|
||||||
@ -262,11 +273,8 @@ fn completion_changes(transaction: &Transaction, trigger_offset: usize) -> Vec<C
|
|||||||
// always present here
|
// always present here
|
||||||
let mut item = item.unwrap().clone();
|
let mut item = item.unwrap().clone();
|
||||||
|
|
||||||
let offset_encoding = editor
|
let language_server = language_server!(item);
|
||||||
.language_servers
|
let offset_encoding = language_server.offset_encoding();
|
||||||
.get_by_id(item.language_server_id)
|
|
||||||
.expect("language server disappeared between completion request and application")
|
|
||||||
.offset_encoding();
|
|
||||||
|
|
||||||
let language_server = editor
|
let language_server = editor
|
||||||
.language_servers
|
.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(),
|
Some(item) if !item.resolved => item.clone(),
|
||||||
_ => return false,
|
_ => return false,
|
||||||
};
|
};
|
||||||
let language_server = match cx
|
|
||||||
.editor
|
let Some(language_server) = cx.editor.language_server_by_id(current_item.language_server_id) else { return false; };
|
||||||
.language_servers
|
|
||||||
.get_by_id(current_item.language_server_id)
|
|
||||||
{
|
|
||||||
Some(language_server) => language_server,
|
|
||||||
None => return false,
|
|
||||||
};
|
|
||||||
|
|
||||||
// This method should not block the compositor so we handle the response asynchronously.
|
// 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()) {
|
let Some(future) = language_server.resolve_completion_item(current_item.item.clone()) else { return false; };
|
||||||
Some(future) => future,
|
|
||||||
None => return false,
|
|
||||||
};
|
|
||||||
|
|
||||||
cx.callback(
|
cx.callback(
|
||||||
future,
|
future,
|
||||||
|
@ -874,7 +874,7 @@ pub struct Editor {
|
|||||||
/// times during rendering and should not be set by other functions.
|
/// times during rendering and should not be set by other functions.
|
||||||
pub cursor_cache: Cell<Option<Option<Position>>>,
|
pub cursor_cache: Cell<Option<Option<Position>>>,
|
||||||
/// When a new completion request is sent to the server old
|
/// 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
|
/// request is associated with a channel that cancels
|
||||||
/// when the channel is dropped. That channel is stored
|
/// when the channel is dropped. That channel is stored
|
||||||
/// here. When a new completion request is sent this
|
/// 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();
|
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
|
/// Refreshes the language server for a given document
|
||||||
pub fn refresh_language_servers(&mut self, doc_id: DocumentId) -> Option<()> {
|
pub fn refresh_language_servers(&mut self, doc_id: DocumentId) -> Option<()> {
|
||||||
self.launch_language_servers(doc_id)
|
self.launch_language_servers(doc_id)
|
||||||
|
Loading…
Reference in New Issue
Block a user