From c9c4b74376017b52a024705622c42d7d35c5bda0 Mon Sep 17 00:00:00 2001 From: pommicket Date: Sat, 9 Sep 2023 22:14:25 -0400 Subject: start incremental sync support --- lsp-parse.c | 29 +++++++++++++++++++++++++++++ lsp.c | 15 ++++++++++----- lsp.h | 8 +++++++- main.c | 1 - 4 files changed, 46 insertions(+), 7 deletions(-) diff --git a/lsp-parse.c b/lsp-parse.c index e941f1a..ff243fb 100644 --- a/lsp-parse.c +++ b/lsp-parse.c @@ -151,6 +151,35 @@ static uint32_t *parse_trigger_characters(const JSON *json, JSONArray trigger_ch static void parse_capabilities(LSP *lsp, const JSON *json, JSONObject capabilities) { LSPCapabilities *cap = &lsp->capabilities; + { + // document syncing capabilities + JSONValue sync_value = json_object_get(json, capabilities, "textDocumentSync"); + double change_type_double = sync_value.type == JSON_NUMBER + ? sync_value.val.number + : json_object_get_number(json, json_force_object(sync_value), "change"); + int change_type = isfinite(change_type_double) + && change_type_double >= 0 + && change_type_double <= 2 + ? (int)change_type_double + : 0; + bool open_close = true; + if (sync_value.type == JSON_NUMBER) { + // nothing to do. + // i think. it's unclear whether we're supposed to send didOpen/didClose + // with this type (it's deprecated, so the spec isn't giving us any information) + } else if (sync_value.type == JSON_OBJECT) { + JSONObject sync = sync_value.val.object; + open_close = json_object_get_bool(json, sync, "openClose", false); + if (!open_close) { + // we're not even allowed to send didChange without a didOpen first, + // so this should always be zero? spec is really unclear here. + change_type = 0; + } + } + cap->open_close_support = open_close; + cap->sync_support = change_type >= 1; + cap->incremental_sync_support = change_type == 2; + } // check CompletionOptions JSONValue completion_value = json_object_get(json, capabilities, "completionProvider"); diff --git a/lsp.c b/lsp.c index e8cb630..025e2be 100644 --- a/lsp.c +++ b/lsp.c @@ -227,12 +227,14 @@ static bool lsp_supports_request(LSP *lsp, const LSPRequest *request) { case LSP_REQUEST_WORKSPACE_FOLDERS: case LSP_REQUEST_PUBLISH_DIAGNOSTICS: return false; - case LSP_REQUEST_INITIALIZE: - case LSP_REQUEST_INITIALIZED: - case LSP_REQUEST_CANCEL: case LSP_REQUEST_DID_OPEN: case LSP_REQUEST_DID_CLOSE: + return cap->open_close_support; case LSP_REQUEST_DID_CHANGE: + return cap->sync_support; + case LSP_REQUEST_INITIALIZE: + case LSP_REQUEST_INITIALIZED: + case LSP_REQUEST_CANCEL: case LSP_REQUEST_CONFIGURATION: case LSP_REQUEST_SHUTDOWN: case LSP_REQUEST_EXIT: @@ -436,8 +438,11 @@ static bool lsp_receive(LSP *lsp, size_t max_size) { // kind of a hack. this is needed because arr_set_len zeroes the data. arr_hdr_(lsp->received_data)->len = (u32)received_so_far; lsp->received_data[received_so_far] = '\0';// null terminate - #if LSP_SHOW_S2C - printf("%s%s%s\n",term_italics(stdout),lsp->received_data,term_clear(stdout)); + #if 0 + const int limit = 1000; + printf("%s%.*s%s%s\n",term_italics(stdout),limit,lsp->received_data, + strlen(lsp->received_data) > (size_t)limit ? "..." : "", + term_clear(stdout)); #endif u64 response_offset=0, response_size=0; diff --git a/lsp.h b/lsp.h index 395f5ee..27f2706 100644 --- a/lsp.h +++ b/lsp.h @@ -588,6 +588,12 @@ typedef struct { } LSPDocumentData; typedef struct { + /// send didChange? + bool sync_support; + /// can didChange notifications have partial changes? + bool incremental_sync_support; + /// send didOpen/didClose? + bool open_close_support; bool signature_help_support; bool completion_support; bool hover_support; @@ -866,7 +872,7 @@ void lsp_write_quit(void); /// print server-to-client communication #define LSP_SHOW_S2C 0 /// print client-to-server communication -#define LSP_SHOW_C2S 1 +#define LSP_SHOW_C2S 0 #endif // LSP_INTERNAL diff --git a/main.c b/main.c index 7506c08..d1569f7 100644 --- a/main.c +++ b/main.c @@ -1,7 +1,6 @@ /* TODO: - figure out what's wrong with godot language server -- automatically restart server FUTURE FEATURES: - autodetect indentation (tabs vs spaces) - custom file/build command associations -- cgit v1.2.3