summaryrefslogtreecommitdiff
path: root/lsp-parse.c
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2022-12-29 18:44:37 -0500
committerpommicket <pommicket@gmail.com>2022-12-29 18:44:37 -0500
commitd77782564bf0a090a4e7fa4f4c4bb685383275dc (patch)
treea4bc3c0bf142c663ea7f293b4381927adc896f1c /lsp-parse.c
parent5f7af06a9085835a3d1ad3a51374c245859d7d97 (diff)
textDocument/definition for ctrl+click
Diffstat (limited to 'lsp-parse.c')
-rw-r--r--lsp-parse.c73
1 files changed, 72 insertions, 1 deletions
diff --git a/lsp-parse.c b/lsp-parse.c
index 07837b5..a892539 100644
--- a/lsp-parse.c
+++ b/lsp-parse.c
@@ -25,6 +25,7 @@ static WarnUnusedResult bool lsp_expect_number(LSP *lsp, JSONValue value, const
return lsp_expect_type(lsp, value, JSON_NUMBER, what);
}
+
static LSPString lsp_response_add_json_string(LSPResponse *response, const JSON *json, JSONString string) {
u32 offset = arr_len(response->string_data);
arr_set_len(response->string_data, offset + string.len + 1);
@@ -80,6 +81,24 @@ static bool parse_range(LSP *lsp, const JSON *json, JSONValue range_value, LSPRa
return success;
}
+static bool parse_document_uri(LSP *lsp, const JSON *json, JSONValue value, LSPDocumentID *id) {
+ if (value.type != JSON_STRING) {
+ lsp_set_error(lsp, "Expected string for URI, got %s",
+ json_type_to_str(value.type));
+ return false;
+ }
+ char *string = json_string_get_alloc(json, value.val.string);
+ if (!str_has_prefix(string, "file://")) {
+ lsp_set_error(lsp, "Can't process non-local URI %s",
+ string);
+ free(string);
+ return false;
+ }
+ *id = lsp_document_id(lsp, string + strlen("file://"));
+ free(string);
+ return true;
+}
+
static uint32_t *parse_trigger_characters(const JSON *json, JSONArray trigger_chars) {
uint32_t *array = NULL;
@@ -136,6 +155,12 @@ static void parse_capabilities(LSP *lsp, const JSON *json, JSONObject capabiliti
cap->hover_support = true;
}
+ // check for definition support
+ JSONValue definition_value = json_object_get(json, capabilities, "definitionProvider");
+ if (definition_value.type != JSON_UNDEFINED) {
+ cap->definition_support = true;
+ }
+
JSONObject workspace = json_object_get_object(json, capabilities, "workspace");
// check WorkspaceFoldersServerCapabilities
JSONObject workspace_folders = json_object_get_object(json, workspace, "workspaceFolders");
@@ -208,7 +233,7 @@ static bool parse_completion(LSP *lsp, const JSON *json, LSPResponse *response)
item->text_edit = (LSPTextEdit) {
.type = LSP_TEXT_EDIT_PLAIN,
.at_cursor = true,
- .range = {{0}},
+ .range = {{0}, {0}},
.new_text = item->label
};
@@ -462,6 +487,47 @@ static bool parse_hover(LSP *lsp, const JSON *json, LSPResponse *response) {
return true;
}
+// parse a Location: {uri: DocumentUri, range: Range}
+static bool parse_location(LSP *lsp, const JSON *json, JSONValue value, LSPLocation *location) {
+ if (value.type != JSON_OBJECT) {
+ lsp_set_error(lsp, "Expected object for location but got %s",
+ json_type_to_str(value.type));
+ return false;
+ }
+ JSONObject object = value.val.object;
+ JSONValue uri = json_object_get(json, object, "uri");
+ if (!parse_document_uri(lsp, json, uri, &location->document))
+ return false;
+ JSONValue range = json_object_get(json, object, "range");
+ if (!parse_range(lsp, json, range, &location->range))
+ return false;
+ return true;
+}
+
+static bool parse_definition(LSP *lsp, const JSON *json, LSPResponse *response) {
+ JSONValue result = json_get(json, "result");
+ if (result.type == JSON_NULL) {
+ // no location
+ return true;
+ }
+ LSPResponseDefinition *definition = &response->data.definition;
+ if (result.type == JSON_ARRAY) {
+ JSONArray locations = result.val.array;
+ if (locations.len == 0)
+ return true;
+ for (u32 l = 0; l < locations.len; ++l) {
+ JSONValue location_json = json_array_get(json, locations, l);
+ LSPLocation *location = arr_addp(definition->locations);
+ if (!parse_location(lsp, json, location_json, location))
+ return false;
+ }
+ return true;
+ } else {
+ LSPLocation *location = arr_addp(definition->locations);
+ return parse_location(lsp, json, result, location);
+ }
+}
+
// fills request->id/id_string appropriately given the request's json
// returns true on success
static WarnUnusedResult bool parse_id(JSON *json, LSPRequest *request) {
@@ -552,6 +618,8 @@ static bool parse_server2client_request(LSP *lsp, JSON *json, LSPRequest *reques
return false;
}
+
+
static void process_message(LSP *lsp, JSON *json) {
#if 0
@@ -601,6 +669,9 @@ static void process_message(LSP *lsp, JSON *json) {
case LSP_REQUEST_HOVER:
add_to_messages = parse_hover(lsp, json, &response);
break;
+ case LSP_REQUEST_DEFINITION:
+ add_to_messages = parse_definition(lsp, json, &response);
+ break;
case LSP_REQUEST_INITIALIZE: {
// it's the response to our initialize request!
if (result.type == JSON_OBJECT) {