|
|
|
@ -1,8 +1,8 @@
|
|
|
|
|
use arc_swap::{access::Map, ArcSwap};
|
|
|
|
|
use futures_util::Stream;
|
|
|
|
|
use helix_core::{diagnostic::Severity, pos_at_coords, syntax, Selection};
|
|
|
|
|
use helix_core::{diagnostic::Severity, pos_at_coords, syntax, Rope, Selection};
|
|
|
|
|
use helix_lsp::{
|
|
|
|
|
lsp::{self, notification::Notification},
|
|
|
|
|
lsp::{self, notification::Notification, MessageType},
|
|
|
|
|
util::lsp_range_to_range,
|
|
|
|
|
LanguageServerId, LspProgressMap,
|
|
|
|
|
};
|
|
|
|
@ -26,7 +26,7 @@ use crate::{
|
|
|
|
|
handlers,
|
|
|
|
|
job::Jobs,
|
|
|
|
|
keymap::Keymaps,
|
|
|
|
|
ui::{self, overlay::overlaid},
|
|
|
|
|
ui::{self, overlay::overlaid, FileLocation, Picker, Popup},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
use log::{debug, error, info, warn};
|
|
|
|
@ -960,11 +960,11 @@ impl Application {
|
|
|
|
|
"Language Server: Method {} not found in request {}",
|
|
|
|
|
method, id
|
|
|
|
|
);
|
|
|
|
|
Err(helix_lsp::jsonrpc::Error {
|
|
|
|
|
Some(Err(helix_lsp::jsonrpc::Error {
|
|
|
|
|
code: helix_lsp::jsonrpc::ErrorCode::MethodNotFound,
|
|
|
|
|
message: format!("Method not found: {}", method),
|
|
|
|
|
data: None,
|
|
|
|
|
})
|
|
|
|
|
}))
|
|
|
|
|
}
|
|
|
|
|
Err(err) => {
|
|
|
|
|
log::error!(
|
|
|
|
@ -973,11 +973,11 @@ impl Application {
|
|
|
|
|
id,
|
|
|
|
|
err
|
|
|
|
|
);
|
|
|
|
|
Err(helix_lsp::jsonrpc::Error {
|
|
|
|
|
Some(Err(helix_lsp::jsonrpc::Error {
|
|
|
|
|
code: helix_lsp::jsonrpc::ErrorCode::ParseError,
|
|
|
|
|
message: format!("Malformed method call: {}", method),
|
|
|
|
|
data: None,
|
|
|
|
|
})
|
|
|
|
|
}))
|
|
|
|
|
}
|
|
|
|
|
Ok(MethodCall::WorkDoneProgressCreate(params)) => {
|
|
|
|
|
self.lsp_progress.create(server_id, params.token);
|
|
|
|
@ -991,7 +991,7 @@ impl Application {
|
|
|
|
|
spinner.start();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(serde_json::Value::Null)
|
|
|
|
|
Some(Ok(serde_json::Value::Null))
|
|
|
|
|
}
|
|
|
|
|
Ok(MethodCall::ApplyWorkspaceEdit(params)) => {
|
|
|
|
|
let language_server = language_server!();
|
|
|
|
@ -1001,25 +1001,73 @@ impl Application {
|
|
|
|
|
.editor
|
|
|
|
|
.apply_workspace_edit(offset_encoding, ¶ms.edit);
|
|
|
|
|
|
|
|
|
|
Ok(json!(lsp::ApplyWorkspaceEditResponse {
|
|
|
|
|
Some(Ok(json!(lsp::ApplyWorkspaceEditResponse {
|
|
|
|
|
applied: res.is_ok(),
|
|
|
|
|
failure_reason: res.as_ref().err().map(|err| err.kind.to_string()),
|
|
|
|
|
failed_change: res
|
|
|
|
|
.as_ref()
|
|
|
|
|
.err()
|
|
|
|
|
.map(|err| err.failed_change_idx as u32),
|
|
|
|
|
}))
|
|
|
|
|
})))
|
|
|
|
|
} else {
|
|
|
|
|
Err(helix_lsp::jsonrpc::Error {
|
|
|
|
|
Some(Err(helix_lsp::jsonrpc::Error {
|
|
|
|
|
code: helix_lsp::jsonrpc::ErrorCode::InvalidRequest,
|
|
|
|
|
message: "Server must be initialized to request workspace edits"
|
|
|
|
|
.to_string(),
|
|
|
|
|
data: None,
|
|
|
|
|
})
|
|
|
|
|
}))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Ok(MethodCall::WorkspaceFolders) => {
|
|
|
|
|
Ok(json!(&*language_server!().workspace_folders().await))
|
|
|
|
|
Some(Ok(json!(&*language_server!().workspace_folders().await)))
|
|
|
|
|
}
|
|
|
|
|
Ok(MethodCall::ShowMessageRequest(params)) => {
|
|
|
|
|
if let Some(actions) = params.actions {
|
|
|
|
|
let call_id = id.clone();
|
|
|
|
|
let message_type = match params.typ {
|
|
|
|
|
MessageType::ERROR => "ERROR",
|
|
|
|
|
MessageType::WARNING => "WARNING",
|
|
|
|
|
MessageType::INFO => "INFO",
|
|
|
|
|
_ => "LOG",
|
|
|
|
|
};
|
|
|
|
|
let message = format!("{}: {}", message_type, ¶ms.message);
|
|
|
|
|
let rope = Rope::from(message);
|
|
|
|
|
let picker =
|
|
|
|
|
Picker::new(actions, (), move |ctx, message_action, _event| {
|
|
|
|
|
let server_from_id =
|
|
|
|
|
ctx.editor.language_servers.get_by_id(server_id);
|
|
|
|
|
let language_server = match server_from_id {
|
|
|
|
|
Some(language_server) => language_server,
|
|
|
|
|
None => {
|
|
|
|
|
warn!(
|
|
|
|
|
"can't find language server with id `{server_id}`"
|
|
|
|
|
);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
let response = match message_action {
|
|
|
|
|
Some(item) => json!(item),
|
|
|
|
|
None => serde_json::Value::Null,
|
|
|
|
|
};
|
|
|
|
|
tokio::spawn(
|
|
|
|
|
language_server.reply(call_id.clone(), Ok(response)),
|
|
|
|
|
);
|
|
|
|
|
})
|
|
|
|
|
.with_preview(
|
|
|
|
|
move |_editor, _value| {
|
|
|
|
|
let file_location: FileLocation =
|
|
|
|
|
(rope.clone().into(), None);
|
|
|
|
|
Some(file_location)
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
let popup_id = "show-message-request";
|
|
|
|
|
let popup = Popup::new(popup_id, picker);
|
|
|
|
|
self.compositor.replace_or_push(popup_id, popup);
|
|
|
|
|
// do not send a reply just yet
|
|
|
|
|
None
|
|
|
|
|
} else {
|
|
|
|
|
Some(Ok(serde_json::Value::Null))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Ok(MethodCall::WorkspaceConfiguration(params)) => {
|
|
|
|
|
let language_server = language_server!();
|
|
|
|
@ -1039,7 +1087,7 @@ impl Application {
|
|
|
|
|
Some(config)
|
|
|
|
|
})
|
|
|
|
|
.collect();
|
|
|
|
|
Ok(json!(result))
|
|
|
|
|
Some(Ok(json!(result)))
|
|
|
|
|
}
|
|
|
|
|
Ok(MethodCall::RegisterCapability(params)) => {
|
|
|
|
|
if let Some(client) = self.editor.language_servers.get_by_id(server_id) {
|
|
|
|
@ -1077,7 +1125,7 @@ impl Application {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(serde_json::Value::Null)
|
|
|
|
|
Some(Ok(serde_json::Value::Null))
|
|
|
|
|
}
|
|
|
|
|
Ok(MethodCall::UnregisterCapability(params)) => {
|
|
|
|
|
for unreg in params.unregisterations {
|
|
|
|
@ -1093,18 +1141,26 @@ impl Application {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Ok(serde_json::Value::Null)
|
|
|
|
|
Some(Ok(serde_json::Value::Null))
|
|
|
|
|
}
|
|
|
|
|
Ok(MethodCall::ShowDocument(params)) => {
|
|
|
|
|
let language_server = language_server!();
|
|
|
|
|
let offset_encoding = language_server.offset_encoding();
|
|
|
|
|
|
|
|
|
|
let result = self.handle_show_document(params, offset_encoding);
|
|
|
|
|
Ok(json!(result))
|
|
|
|
|
Some(Ok(json!(result)))
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
tokio::spawn(language_server!().reply(id, reply));
|
|
|
|
|
if let Some(reply) = reply {
|
|
|
|
|
let lanaguage_server = match self.editor.language_servers.get_by_id(server_id) {
|
|
|
|
|
Some(language_server) => language_server,
|
|
|
|
|
None => {
|
|
|
|
|
warn!("can't find language server with id `{}`", server_id);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
tokio::spawn(lanaguage_server.reply(id, reply));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Call::Invalid { id } => log::error!("LSP invalid method call id={:?}", id),
|
|
|
|
|
}
|
|
|
|
|