diff options
| author | Albert Cervin <albert@acervin.com> | 2024-09-17 08:47:03 +0200 |
|---|---|---|
| committer | Albert Cervin <albert@acervin.com> | 2025-11-01 22:11:14 +0100 |
| commit | 4459b8b3aa9d73895391785a99dcc87134e80601 (patch) | |
| tree | a5204f447a0b2b05f63504c7fe958ef9bbf1918a /src/main/lsp/actions.c | |
| parent | 4689f3f38277bb64981fc960e8e384e2d065d659 (diff) | |
| download | dged-4459b8b3aa9d73895391785a99dcc87134e80601.tar.gz dged-4459b8b3aa9d73895391785a99dcc87134e80601.tar.xz dged-4459b8b3aa9d73895391785a99dcc87134e80601.zip | |
More lsp support
This makes the LSP support complete for now:
- Completion
- Diagnostics
- Goto implementation/declaration
- Rename
- Documentation
- Find references
Diffstat (limited to 'src/main/lsp/actions.c')
| -rw-r--r-- | src/main/lsp/actions.c | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/src/main/lsp/actions.c b/src/main/lsp/actions.c new file mode 100644 index 0000000..ea792a1 --- /dev/null +++ b/src/main/lsp/actions.c @@ -0,0 +1,129 @@ +#include "actions.h" + +#include "dged/buffer.h" +#include "dged/buffer_view.h" +#include "dged/lsp.h" +#include "dged/minibuffer.h" +#include "dged/window.h" +#include "main/lsp.h" +#include "main/lsp/diagnostics.h" + +#include "choice-buffer.h" +#include "types.h" + +static struct code_actions g_code_actions_result = {}; + +static void code_action_command_selected(void *selected, void *userdata) { + struct lsp_server *server = (struct lsp_server *)userdata; + struct lsp_command *command = (struct lsp_command *)selected; + struct s8 json_payload = lsp_command_to_json(command); + + uint64_t id = new_pending_request(server, NULL, NULL); + lsp_send( + lsp_backend(server), + lsp_create_request(id, s8("workspace/executeCommand"), json_payload)); + + s8delete(json_payload); +} + +static void code_action_selected(void *selected, void *userdata) { + struct lsp_server *server = (struct lsp_server *)userdata; + struct code_action *action = (struct code_action *)selected; + + if (action->has_edit) { + apply_edits(server, &action->edit); + } + + if (action->has_command) { + struct s8 json_payload = lsp_command_to_json(&action->command); + + uint64_t id = new_pending_request(server, NULL, NULL); + lsp_send( + lsp_backend(server), + lsp_create_request(id, s8("workspace/executeCommand"), json_payload)); + s8delete(json_payload); + } +} + +static void code_action_closed(void *userdata) { + (void)userdata; + lsp_code_actions_free(&g_code_actions_result); +} + +static void handle_code_actions_response(struct lsp_server *server, + struct lsp_response *response, + void *userdata) { + struct code_actions actions = + lsp_code_actions_from_json(&response->value.result); + + struct buffers *buffers = (struct buffers *)userdata; + + if (VEC_SIZE(&actions.commands) == 0 && + VEC_SIZE(&actions.code_actions) == 0) { + minibuffer_echo_timeout(4, "no code actions available"); + lsp_code_actions_free(&actions); + } else { + g_code_actions_result = actions; + struct choice_buffer *buf = + choice_buffer_create(s8("Code Actions"), buffers, code_action_selected, + code_action_closed, NULL, server); + + VEC_FOR_EACH(&actions.code_actions, struct code_action * action) { + struct s8 line = + s8from_fmt("%.*s, (%.*s)", action->title.l, action->title.s, + action->kind.l, action->kind.s); + choice_buffer_add_choice_with_callback(buf, line, action, + code_action_selected); + s8delete(line); + } + + VEC_FOR_EACH(&actions.commands, struct lsp_command * command) { + struct s8 line = s8from_fmt("%.*s", command->title.l, command->title.s); + choice_buffer_add_choice_with_callback(buf, line, command, + code_action_command_selected); + s8delete(line); + } + } +} + +int32_t code_actions_cmd(struct command_ctx ctx, int argc, const char **argv) { + (void)argc; + (void)argv; + + struct buffer_view *bv = window_buffer_view(windows_get_active()); + + struct lsp_server *server = lsp_server_for_lang_id(bv->buffer->lang.id); + if (server == NULL) { + return 0; + } + + uint64_t id = + new_pending_request(server, handle_code_actions_response, ctx.buffers); + struct versioned_text_document_identifier doc = + versioned_identifier_from_buffer(bv->buffer); + struct code_action_params params = { + .text_document.uri = doc.uri, + .range = region_new(bv->dot, bv->dot), + }; + + VEC_INIT(¶ms.context.diagnostics, 8); + + diagnostic_vec *d = + diagnostics_for_buffer(lsp_server_diagnostics(server), bv->buffer); + if (d != NULL) { + VEC_FOR_EACH(d, struct diagnostic * diag) { + if (location_is_between(bv->dot, diag->region.begin, diag->region.end)) { + VEC_PUSH(¶ms.context.diagnostics, *diag); + } + } + } + + struct s8 json_payload = code_action_params_to_json(¶ms); + lsp_send(lsp_backend(server), + lsp_create_request(id, s8("textDocument/codeAction"), json_payload)); + + VEC_DESTROY(¶ms.context.diagnostics); + versioned_text_document_identifier_free(&doc); + s8delete(json_payload); + return 0; +} |
