summaryrefslogtreecommitdiff
path: root/lsp-parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'lsp-parse.c')
-rw-r--r--lsp-parse.c87
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!