From d51f4ce90fc40bb6b1813e7716d1db40cf91ee15 Mon Sep 17 00:00:00 2001 From: pommicket Date: Fri, 30 Dec 2022 15:27:38 -0500 Subject: cancelling requests --- ide-definitions.c | 17 +++++++++-------- lsp-parse.c | 3 ++- lsp-write.c | 8 ++++++++ lsp.c | 11 +++++++++++ lsp.h | 25 ++++++++++++++++++++++++- main.c | 2 +- ted.h | 1 + 7 files changed, 56 insertions(+), 11 deletions(-) diff --git a/ide-definitions.c b/ide-definitions.c index d76925b..6c48e26 100644 --- a/ide-definitions.c +++ b/ide-definitions.c @@ -1,3 +1,8 @@ +void definition_cancel_lookup(Ted *ted) { + Definitions *defs = &ted->definitions; + lsp_cancel_request(ted_get_lsp_by_id(ted, defs->last_request_lsp), defs->last_request_id); + defs->last_request_id = 0; +} static SymbolKind symbol_kind_to_ted(LSPSymbolKind kind) { switch (kind) { @@ -51,8 +56,9 @@ void definition_goto(Ted *ted, LSP *lsp, const char *name, LSPDocumentPosition p LSPRequest request = {.type = LSP_REQUEST_DEFINITION}; request.data.definition.position = position; LSPRequestID id = lsp_send_request(lsp, &request); - // @TODO : cancel old request + lsp_cancel_request(lsp, defs->last_request_id); // cancel old request defs->last_request_id = id; + defs->last_request_lsp = lsp->id; defs->last_request_time = ted->frame_time; } else { // just go to the tag @@ -60,12 +66,6 @@ void definition_goto(Ted *ted, LSP *lsp, const char *name, LSPDocumentPosition p } } -void definition_cancel_lookup(Ted *ted) { - Definitions *defs = &ted->definitions; - defs->last_request_id = 0; -} - - void definitions_frame(Ted *ted) { Definitions *defs = &ted->definitions; if (defs->last_request_id && timespec_sub(ted->frame_time, defs->last_request_time) > 0.2) { @@ -193,6 +193,7 @@ void definitions_send_request_if_needed(Ted *ted) { LSPRequestWorkspaceSymbols *syms = &request.data.workspace_symbols; syms->query = str_dup(query); defs->last_request_id = lsp_send_request(lsp, &request); + defs->last_request_lsp = lsp->id; defs->last_request_time = ted->frame_time; free(defs->last_request_query); defs->last_request_query = query; @@ -219,7 +220,7 @@ void definitions_selector_open(Ted *ted) { void definitions_selector_close(Ted *ted) { Definitions *defs = &ted->definitions; definitions_clear_entries(defs); - // @TODO : cancel + lsp_cancel_request(ted_get_lsp_by_id(ted, defs->last_request_lsp), defs->last_request_id); defs->last_request_id = 0; free(defs->last_request_query); defs->last_request_query = NULL; diff --git a/lsp-parse.c b/lsp-parse.c index f720d12..a816ec9 100644 --- a/lsp-parse.c +++ b/lsp-parse.c @@ -694,6 +694,7 @@ static void process_message(LSP *lsp, JSON *json) { } } + double error_code = json_force_number(json_get(json, "error.code")); JSONValue error = json_get(json, "error.message"); JSONValue result = json_get(json, "result"); if (result.type != JSON_UNDEFINED || error.type == JSON_STRING) { @@ -708,7 +709,7 @@ static void process_message(LSP *lsp, JSON *json) { response.error = json_string_get_alloc(json, error.val.string); } - if (response.error) { + if (response.error && error_code != LSP_ERROR_REQUEST_CANCELLED) { add_to_messages = true; } else switch (response_to.type) { case LSP_REQUEST_COMPLETION: diff --git a/lsp-write.c b/lsp-write.c index b8167b4..e5e0d09 100644 --- a/lsp-write.c +++ b/lsp-write.c @@ -253,6 +253,8 @@ static const char *lsp_request_method(LSPRequest *request) { return "shutdown"; case LSP_REQUEST_EXIT: return "exit"; + case LSP_REQUEST_CANCEL: + return "$/cancelRequest"; case LSP_REQUEST_SHOW_MESSAGE: return "window/showMessage"; case LSP_REQUEST_LOG_MESSAGE: @@ -451,6 +453,12 @@ static void write_request(LSP *lsp, LSPRequest *request) { write_obj_end(o); write_obj_end(o); } break; + case LSP_REQUEST_CANCEL: { + const LSPRequestCancel *cancel = &request->data.cancel; + write_key_obj_start(o, "params"); + write_key_number(o, "id", cancel->id); + write_obj_end(o); + } break; case LSP_REQUEST_DID_OPEN: { const LSPRequestDidOpen *open = &request->data.open; write_key_obj_start(o, "params"); diff --git a/lsp.c b/lsp.c index 60dd4d1..875aab2 100644 --- a/lsp.c +++ b/lsp.c @@ -46,6 +46,7 @@ static void lsp_request_free(LSPRequest *r) { case LSP_REQUEST_INITIALIZE: case LSP_REQUEST_INITIALIZED: case LSP_REQUEST_SHUTDOWN: + case LSP_REQUEST_CANCEL: case LSP_REQUEST_EXIT: case LSP_REQUEST_COMPLETION: case LSP_REQUEST_SIGNATURE_HELP: @@ -145,6 +146,7 @@ static bool lsp_supports_request(LSP *lsp, const LSPRequest *request) { return false; case LSP_REQUEST_INITIALIZE: case LSP_REQUEST_INITIALIZED: + case LSP_REQUEST_CANCEL: case LSP_REQUEST_DID_OPEN: case LSP_REQUEST_DID_CLOSE: case LSP_REQUEST_DID_CHANGE: @@ -182,6 +184,7 @@ static bool request_type_is_notification(LSPRequestType type) { case LSP_REQUEST_NONE: break; case LSP_REQUEST_INITIALIZED: case LSP_REQUEST_EXIT: + case LSP_REQUEST_CANCEL: case LSP_REQUEST_DID_OPEN: case LSP_REQUEST_DID_CLOSE: case LSP_REQUEST_DID_CHANGE: @@ -575,3 +578,11 @@ bool lsp_covers_path(LSP *lsp, const char *path) { SDL_UnlockMutex(lsp->workspace_folders_mutex); return ret; } + +void lsp_cancel_request(LSP *lsp, LSPRequestID id) { + if (!id) return; + + LSPRequest request = {.type = LSP_REQUEST_CANCEL}; + request.data.cancel.id = id; + lsp_send_request(lsp, &request); +} diff --git a/lsp.h b/lsp.h index 90f70d7..5d5f3c4 100644 --- a/lsp.h +++ b/lsp.h @@ -38,6 +38,7 @@ typedef enum { // client-to-server LSP_REQUEST_INITIALIZE, // initialize LSP_REQUEST_INITIALIZED, // initialized + LSP_REQUEST_CANCEL, // $/cancelRequest // workspace/didChangeConfiguration with parameters specifically for jdtls. // we need this because annoyingly jdtls refuses to give signature help // unless you specifically configure it to do that @@ -60,6 +61,24 @@ typedef enum { LSP_REQUEST_WORKSPACE_FOLDERS, // workspace/workspaceFolders - NOTE: this is handled directly in lsp-parse.c (because it only needs information from the LSP struct) } LSPRequestType; +typedef enum { + LSP_ERROR_PARSE = -32700, + LSP_ERROR_INVALID_REQUEST = -32600, + LSP_ERROR_METHOD_NOT_FOUND = -32601, + LSP_ERROR_INVALID_PARAMS = -32602, + LSP_ERROR_INTERNAL = -32603, + LSP_ERROR_SERVER_NOT_INITIALIZED = -32002, + LSP_ERROR_UNKNOWN_CODE = -32001, + LSP_ERROR_REQUEST_FAILED = -32803, + LSP_ERROR_SERVER_CANCELLED = -32802, + LSP_ERROR_CONTENT_MODIFIED = -32801, + LSP_ERROR_REQUEST_CANCELLED = -32800, +} LSPError; + +typedef struct { + LSPRequestID id; +} LSPRequestCancel; + typedef struct { Language language; LSPDocumentID document; @@ -138,11 +157,12 @@ typedef struct { } LSPRequestDidChangeWorkspaceFolders; typedef struct { - u32 id; + LSPRequestID id; LSPRequestType type; char *id_string; // if not NULL, this is the ID (only for server-to-client messages; we always use integer IDs) // one member of this union is set depending on `type`. union { + LSPRequestCancel cancel; LSPRequestDidOpen open; LSPRequestDidClose close; LSPRequestDidChange change; @@ -427,6 +447,9 @@ const char *lsp_document_path(LSP *lsp, LSPDocumentID id); // returns the ID of the sent request, or 0 if the request is not supported by the LSP // don't free the contents of this request (even on failure)! let me handle it! LSPRequestID lsp_send_request(LSP *lsp, LSPRequest *request); +// send a $/cancelRequest notification +// if id = 0, nothing will happen. +void lsp_cancel_request(LSP *lsp, LSPRequestID id); // don't free the contents of this response! let me handle it! void lsp_send_response(LSP *lsp, LSPResponse *response); const char *lsp_response_string(const LSPResponse *response, LSPString string); diff --git a/main.c b/main.c index c2b9638..211b47a 100644 --- a/main.c +++ b/main.c @@ -1,7 +1,6 @@ /* @TODO: - handle multiple symbols with same name -- cancelling requests e.g. in ide-definitions.c - more LSP stuff: - find usages - refactoring? @@ -9,6 +8,7 @@ - check if there are any other non-optional/nice-to-have-support-for server-to-client requests - better non-error window/showMessage(Request) - document lsp.h and lsp.c. +- add last_request_id checking to autocomplete_process_lsp_response - maximum queue size for requests/responses just in case? - idea: configurable timeout - what to do if initialize request takes a long time? diff --git a/ted.h b/ted.h index 8132e1e..5acbba4 100644 --- a/ted.h +++ b/ted.h @@ -424,6 +424,7 @@ typedef struct { } SymbolInfo; typedef struct { + LSPID last_request_lsp; // used for cancellation // ID of the last request which was sent out. // used to process responses in chronological order (= ID order). // if we got a response for the last request, or no requests have been made, -- cgit v1.2.3