Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(lsp): commands #1304

Merged
merged 4 commits into from
Dec 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion helix-lsp/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ impl Client {
Ok(result) => Output::Success(Success {
jsonrpc: Some(Version::V2),
id,
result,
result: serde_json::to_value(result)?,
}),
Err(error) => Output::Failure(Failure {
jsonrpc: Some(Version::V2),
Expand Down Expand Up @@ -800,4 +800,16 @@ impl Client {
let response = self.request::<lsp::request::Rename>(params).await?;
Ok(response.unwrap_or_default())
}

pub fn command(&self, command: lsp::Command) -> impl Future<Output = Result<Value>> {
let params = lsp::ExecuteCommandParams {
command: command.command,
arguments: command.arguments.unwrap_or_default(),
work_done_progress_params: lsp::WorkDoneProgressParams {
work_done_token: None,
},
};

self.call::<lsp::request::ExecuteCommand>(params)
}
}
7 changes: 7 additions & 0 deletions helix-lsp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ pub mod util {
#[derive(Debug, PartialEq, Clone)]
pub enum MethodCall {
WorkDoneProgressCreate(lsp::WorkDoneProgressCreateParams),
ApplyWorkspaceEdit(lsp::ApplyWorkspaceEditParams),
}

impl MethodCall {
Expand All @@ -215,6 +216,12 @@ impl MethodCall {
.expect("Failed to parse WorkDoneCreate params");
Self::WorkDoneProgressCreate(params)
}
lsp::request::ApplyWorkspaceEdit::METHOD => {
let params: lsp::ApplyWorkspaceEditParams = params
.parse()
.expect("Failed to parse ApplyWorkspaceEdit params");
Self::ApplyWorkspaceEdit(params)
}
_ => {
log::warn!("unhandled lsp request: {}", method);
return None;
Expand Down
48 changes: 39 additions & 9 deletions helix-term/src/application.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
use helix_core::{merge_toml_values, syntax};
use helix_lsp::{lsp, util::lsp_pos_to_pos, LspProgressMap};
use helix_view::{theme, Editor};
use serde_json::json;

use crate::{args::Args, compositor::Compositor, config::Config, job::Jobs, ui};
use crate::{
args::Args, commands::apply_workspace_edit, compositor::Compositor, config::Config, job::Jobs,
ui,
};

use log::{error, warn};

Expand Down Expand Up @@ -530,14 +534,6 @@ impl Application {
Call::MethodCall(helix_lsp::jsonrpc::MethodCall {
method, params, id, ..
}) => {
let language_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;
}
};

let call = match MethodCall::parse(&method, params) {
Some(call) => call,
None => {
Expand Down Expand Up @@ -567,8 +563,42 @@ impl Application {
if spinner.is_stopped() {
spinner.start();
}
let language_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(language_server.reply(id, Ok(serde_json::Value::Null)));
}
MethodCall::ApplyWorkspaceEdit(params) => {
apply_workspace_edit(
&mut self.editor,
helix_lsp::OffsetEncoding::Utf8,
&params.edit,
);

let language_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(language_server.reply(
id,
Ok(json!(lsp::ApplyWorkspaceEditResponse {
applied: true,
failure_reason: None,
failed_change: None,
})),
));
}
}
}
e => unreachable!("{:?}", e),
Expand Down
33 changes: 30 additions & 3 deletions helix-term/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3277,12 +3277,19 @@ pub fn code_action(cx: &mut Context) {
move |editor, code_action, _action| match code_action {
lsp::CodeActionOrCommand::Command(command) => {
log::debug!("code action command: {:?}", command);
editor.set_error(String::from("Handling code action command is not implemented yet, see https://github.com/helix-editor/helix/issues/183"));
execute_lsp_command(editor, command.clone());
}
lsp::CodeActionOrCommand::CodeAction(code_action) => {
log::debug!("code action: {:?}", code_action);
if let Some(ref workspace_edit) = code_action.edit {
apply_workspace_edit(editor, offset_encoding, workspace_edit)
log::debug!("edit: {:?}", workspace_edit);
apply_workspace_edit(editor, offset_encoding, workspace_edit);
}

// if code action provides both edit and command first the edit
// should be applied and then the command
if let Some(command) = &code_action.command {
execute_lsp_command(editor, command.clone());
}
}
},
Expand All @@ -3293,6 +3300,26 @@ pub fn code_action(cx: &mut Context) {
)
}

pub fn execute_lsp_command(editor: &mut Editor, cmd: lsp::Command) {
let (_view, doc) = current!(editor);

let language_server = match doc.language_server() {
Some(language_server) => language_server,
None => return,
};

// the command is executed on the server and communicated back
// to the client asynchronously using workspace edits
let command_future = language_server.command(cmd);
tokio::spawn(async move {
let res = command_future.await;

if let Err(e) = res {
log::error!("execute LSP command: {}", e);
}
});
}

pub fn apply_document_resource_op(op: &lsp::ResourceOp) -> std::io::Result<()> {
use lsp::ResourceOp;
use std::fs;
Expand Down Expand Up @@ -3346,7 +3373,7 @@ pub fn apply_document_resource_op(op: &lsp::ResourceOp) -> std::io::Result<()> {
}
}

fn apply_workspace_edit(
pub fn apply_workspace_edit(
editor: &mut Editor,
offset_encoding: OffsetEncoding,
workspace_edit: &lsp::WorkspaceEdit,
Expand Down