summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2022-12-30 15:27:38 -0500
committerpommicket <pommicket@gmail.com>2022-12-30 15:27:38 -0500
commitd51f4ce90fc40bb6b1813e7716d1db40cf91ee15 (patch)
treedbd72d0add72d4923244e93e476deeb422b0ff99
parent547bfbba7a1ef84d397711882a501fc4914addba (diff)
cancelling requests
-rw-r--r--ide-definitions.c17
-rw-r--r--lsp-parse.c3
-rw-r--r--lsp-write.c8
-rw-r--r--lsp.c11
-rw-r--r--lsp.h25
-rw-r--r--main.c2
-rw-r--r--ted.h1
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,