diff options
Diffstat (limited to 'lsp-parse.c')
-rw-r--r-- | lsp-parse.c | 87 |
1 files changed, 86 insertions, 1 deletions
diff --git a/lsp-parse.c b/lsp-parse.c index 63d5605..5881ec3 100644 --- a/lsp-parse.c +++ b/lsp-parse.c @@ -280,6 +280,11 @@ static void parse_capabilities(LSP *lsp, const JSON *json, JSONObject capabiliti cap->range_formatting_support = true; } + JSONValue code_action_value = json_object_get(json, capabilities, "codeActionProvider"); + if (code_action_value.type == JSON_OBJECT || code_action_value.type == JSON_TRUE) { + cap->code_action_support = true; + } + JSONObject workspace = json_object_get_object(json, capabilities, "workspace"); // check WorkspaceFoldersServerCapabilities JSONObject workspace_folders = json_object_get_object(json, workspace, "workspaceFolders"); @@ -795,10 +800,14 @@ static bool parse_publish_diagnostics(LSP *lsp, const JSON *json, LSPRequest *re return false; JSONArray diagnostics = json_object_get_array(json, params, "diagnostics"); for (u32 i = 0; i < diagnostics.len; ++i) { - JSONObject diagnostic_in = json_array_get_object(json, diagnostics, i); + JSONValue diagnostic_val = json_array_get(json, diagnostics, i); + JSONObject diagnostic_in = json_force_object(diagnostic_val); LSPDiagnostic *diagnostic_out = arr_addp(pub->diagnostics); if (!parse_diagnostic(lsp, request, json, diagnostic_in, diagnostic_out)) return false; + char *raw = json_reserialize(json, diagnostic_val); + diagnostic_out->raw = lsp_request_add_string(request, raw); + free(raw); } return true; } @@ -1081,6 +1090,79 @@ static bool parse_formatting_response(LSP *lsp, const JSON *json, LSPResponse *r return true; } +static bool parse_command(LSP *lsp, LSPResponse *response, const JSON *json, JSONObject command_in, LSPCommand *command_out) { + JSONString command_str = json_object_get_string(json, command_in, "command"); + JSONArray arguments = json_object_get_array(json, command_in, "arguments"); + char command[64]; + json_string_get(json, command_str, command, sizeof command); + if (strcmp(command, "java.apply.workspaceEdit") == 0) { + // why does this exist?? + if (arguments.len != 1) { + lsp_set_error(lsp, "Expected 1 argument to %s; got %" PRIu32, command, arguments.len); + return false; + } + JSONObject edit = json_array_get_object(json, arguments, 0); + if (!parse_workspace_edit(lsp, response, json, edit, &command_out->data.edit)) { + lsp_workspace_edit_free(&command_out->data.edit); + return false; + } + command_out->kind = LSP_COMMAND_WORKSPACE_EDIT; + return true; + } + eprint("Unrecognized command: %s\n", command); + (void)command_out; + return false; +} + +static LSPCodeActionKind parse_code_action_kind(const char *kind) { + if (streq(kind, "quickfix")) + return LSP_CODE_ACTION_QUICKFIX; + return LSP_CODE_ACTION_OTHER; +} + +static bool parse_code_action_response(LSP *lsp, const JSON *json, LSPResponse *response) { + JSONValue actions_val = json_get(json, "result"); + if (actions_val.type == JSON_NULL) { + // nothing there + return true; + } + if (actions_val.type != JSON_ARRAY) { + lsp_set_error(lsp, "Expected array or null for code action response; got %s", + json_type_to_str(actions_val.type)); + return false; + } + JSONArray actions = json_force_array(actions_val); + for (u32 i = 0; i < actions.len; i++) { + JSONObject action = json_array_get_object(json, actions, i); + JSONValue command_val = json_object_get(json, action, "command"); + LSPCodeAction action_out = {0}; + JSONString title_str = json_object_get_string(json, action, "title"); + action_out.name = lsp_response_add_json_string(response, json, title_str); + action_out.is_preferred = json_object_get_bool(json, action, "isPreferred", false); + JSONString kind_str = json_object_get_string(json, action, "kind"); + char kind[32]; + json_string_get(json, kind_str, kind, sizeof kind); + action_out.kind = parse_code_action_kind(kind); + bool understood = true; + if (command_val.type == JSON_STRING) { + // this action is a Command + understood &= parse_command(lsp, response, json, action, &action_out.command); + } else { + // this action is a CodeAction + JSONValue edit = json_object_get(json, action, "edit"); + if (edit.type == JSON_OBJECT) { + understood &= parse_workspace_edit(lsp, response, json, edit.val.object, &action_out.edit); + } + if (command_val.type == JSON_OBJECT) { + understood &= parse_command(lsp, response, json, command_val.val.object, &action_out.command); + } + } + if (understood) + arr_add(response->data.code_action.actions, action_out); + } + return true; +} + void process_message(LSP *lsp, JSON *json) { #if 0 @@ -1164,6 +1246,9 @@ void process_message(LSP *lsp, JSON *json) { case LSP_REQUEST_DOCUMENT_LINK: add_to_messages = parse_document_link_response(lsp, json, &response); break; + case LSP_REQUEST_CODE_ACTION: + add_to_messages = parse_code_action_response(lsp, json, &response); + break; case LSP_REQUEST_INITIALIZE: if (!lsp->initialized) { // it's the response to our initialize request! |