summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2023-01-07 16:09:30 -0500
committerpommicket <pommicket@gmail.com>2023-01-07 16:09:30 -0500
commit66da8ac5dcfe02d3aa79f72ba415235eb872ec1d (patch)
tree651dbbeabf79f70b84f6e1c4394ebd703837737c
parent7640ecce499fc49cad3d9b9f391cce0b74e435c9 (diff)
better request cancellation system
-rw-r--r--ide-autocomplete.c16
-rw-r--r--ide-definitions.c22
-rw-r--r--ide-highlights.c10
-rw-r--r--ide-usages.c16
-rw-r--r--lsp.c9
-rw-r--r--lsp.h10
-rw-r--r--main.c3
-rw-r--r--ted.c7
-rw-r--r--ted.h22
9 files changed, 54 insertions, 61 deletions
diff --git a/ide-autocomplete.c b/ide-autocomplete.c
index 728a54b..f2382cb 100644
--- a/ide-autocomplete.c
+++ b/ide-autocomplete.c
@@ -106,8 +106,7 @@ void autocomplete_close(Ted *ted) {
ac->open = false;
autocomplete_clear_phantom(ac);
autocomplete_clear_completions(ac);
- ted_cancel_lsp_request(ted, ac->last_request_lsp, ac->last_request_id);
- ac->last_request_id = 0;
+ ted_cancel_lsp_request(ted, &ac->last_request);
}
static void autocomplete_update_suggested(Ted *ted) {
@@ -140,7 +139,7 @@ static void autocomplete_send_completion_request(Ted *ted, TextBuffer *buffer, B
LSP *lsp = buffer_lsp(buffer);
Autocomplete *ac = &ted->autocomplete;
- ted_cancel_lsp_request(ted, ac->last_request_lsp, ac->last_request_id);
+ ted_cancel_lsp_request(ted, &ac->last_request);
LSPRequest request = {
.type = LSP_REQUEST_COMPLETION
@@ -164,9 +163,8 @@ static void autocomplete_send_completion_request(Ted *ted, TextBuffer *buffer, B
};
if (trigger < UNICODE_CODE_POINTS)
unicode_utf32_to_utf8(request.data.completion.context.trigger_character, trigger);
- ac->last_request_id = lsp_send_request(lsp, &request);
- if (ac->last_request_id) {
- ac->last_request_lsp = lsp->id;
+ ac->last_request = lsp_send_request(lsp, &request);
+ if (ac->last_request.id) {
ac->last_request_time = ted->frame_time;
ac->last_request_phantom = phantom;
// *technically sepaking* this can mess things up if a complete
@@ -290,9 +288,9 @@ void autocomplete_process_lsp_response(Ted *ted, const LSPResponse *response) {
if (request->type != LSP_REQUEST_COMPLETION)
return;
Autocomplete *ac = &ted->autocomplete;
- if (request->id != ac->last_request_id)
+ if (request->id != ac->last_request.id)
return; // old request
- ac->last_request_id = 0;
+ ac->last_request.id = 0;
if (!ac->open && !ac->last_request_phantom) {
// user hit escape or down or something before completions arrived.
return;
@@ -489,7 +487,7 @@ void autocomplete_frame(Ted *ted) {
autocomplete_find_completions(ted, TRIGGER_INCOMPLETE, false);
size_t ncompletions = arr_len(ac->suggested);
- bool waiting_for_lsp = ac->last_request_id != 0;
+ bool waiting_for_lsp = ac->last_request.id != 0;
if (waiting_for_lsp && ncompletions == 0) {
double now = ted->frame_time;
diff --git a/ide-definitions.c b/ide-definitions.c
index a6809b6..673fe63 100644
--- a/ide-definitions.c
+++ b/ide-definitions.c
@@ -5,8 +5,7 @@
void definition_cancel_lookup(Ted *ted) {
Definitions *defs = &ted->definitions;
- ted_cancel_lsp_request(ted, defs->last_request_lsp, defs->last_request_id);
- defs->last_request_id = 0;
+ ted_cancel_lsp_request(ted, &defs->last_request);
}
static SymbolKind symbol_kind_to_ted(LSPSymbolKind kind) {
@@ -77,14 +76,13 @@ void definition_goto(Ted *ted, LSP *lsp, const char *name, LSPDocumentPosition p
// send that request
LSPRequest request = {.type = request_type};
request.data.definition.position = position;
- LSPRequestID id = lsp_send_request(lsp, &request);
- if (id == 0 && request.type == LSP_REQUEST_IMPLEMENTATION) {
+ LSPServerRequestID id = lsp_send_request(lsp, &request);
+ if (id.id == 0 && request.type == LSP_REQUEST_IMPLEMENTATION) {
// if we can't go to the implementation, try going to the definition
request.type = LSP_REQUEST_DEFINITION;
id = lsp_send_request(lsp, &request);
}
- defs->last_request_id = id;
- defs->last_request_lsp = lsp->id;
+ defs->last_request = id;
defs->last_request_time = ted->frame_time;
} else {
// just go to the tag
@@ -94,7 +92,7 @@ void definition_goto(Ted *ted, LSP *lsp, const char *name, LSPDocumentPosition p
void definitions_frame(Ted *ted) {
Definitions *defs = &ted->definitions;
- if (defs->last_request_id && ted->frame_time - defs->last_request_time > 0.2) {
+ if (defs->last_request.id && ted->frame_time - defs->last_request_time > 0.2) {
ted->cursor = ted->cursor_wait;
}
}
@@ -162,12 +160,12 @@ static void definitions_selector_filter_entries(Ted *ted) {
void definitions_process_lsp_response(Ted *ted, LSP *lsp, const LSPResponse *response) {
Definitions *defs = &ted->definitions;
- if (response->request.id != defs->last_request_id) {
+ if (response->request.id != defs->last_request.id) {
// response to an old/irrelevant request
return;
}
- defs->last_request_id = 0;
+ defs->last_request.id = 0;
switch (response->request.type) {
case LSP_REQUEST_DEFINITION:
@@ -243,8 +241,7 @@ void definitions_send_request_if_needed(Ted *ted) {
syms->query = str_dup(query);
// cancel old request
definition_cancel_lookup(ted);
- defs->last_request_id = lsp_send_request(lsp, &request);
- defs->last_request_lsp = lsp->id;
+ defs->last_request = lsp_send_request(lsp, &request);
defs->last_request_time = ted->frame_time;
free(defs->last_request_query);
defs->last_request_query = query;
@@ -271,8 +268,7 @@ void definitions_selector_open(Ted *ted) {
void definitions_selector_close(Ted *ted) {
Definitions *defs = &ted->definitions;
definitions_clear_entries(defs);
- ted_cancel_lsp_request(ted, defs->last_request_lsp, defs->last_request_id);
- defs->last_request_id = 0;
+ ted_cancel_lsp_request(ted, &defs->last_request);
free(defs->last_request_query);
defs->last_request_query = NULL;
}
diff --git a/ide-highlights.c b/ide-highlights.c
index 424d640..fee01d4 100644
--- a/ide-highlights.c
+++ b/ide-highlights.c
@@ -5,8 +5,7 @@
void highlights_close(Ted *ted) {
Highlights *hls = &ted->highlights;
arr_clear(hls->highlights);
- ted_cancel_lsp_request(ted, hls->last_request_lsp, hls->last_request_id);
- hls->last_request_id = 0;
+ ted_cancel_lsp_request(ted, &hls->last_request);
hls->requested_position = (LSPDocumentPosition){0};
}
@@ -26,9 +25,8 @@ static void highlights_send_request(Ted *ted) {
LSPRequest request = {.type = LSP_REQUEST_HIGHLIGHT};
request.data.highlight.position = pos;
- ted_cancel_lsp_request(ted, hls->last_request_lsp, hls->last_request_id);
- hls->last_request_id = lsp_send_request(lsp, &request);
- hls->last_request_lsp = lsp->id;
+ ted_cancel_lsp_request(ted, &hls->last_request);
+ hls->last_request = lsp_send_request(lsp, &request);
hls->requested_position = pos;
}
@@ -37,7 +35,7 @@ void highlights_process_lsp_response(Ted *ted, LSPResponse *response) {
Highlights *hls = &ted->highlights;
if (response->request.type != LSP_REQUEST_HIGHLIGHT)
return; // not a highlight request
- if (response->request.id != hls->last_request_id)
+ if (response->request.id != hls->last_request.id)
return; // old request
const LSPResponseHighlight *hl_response = &response->data.highlight;
arr_set_len(hls->highlights, arr_len(hl_response->highlights));
diff --git a/ide-usages.c b/ide-usages.c
index 95324fd..a3b9194 100644
--- a/ide-usages.c
+++ b/ide-usages.c
@@ -4,10 +4,7 @@
void usages_cancel_lookup(Ted *ted) {
Usages *usages = &ted->usages;
- if (usages->last_request_id) {
- ted_cancel_lsp_request(ted, usages->last_request_lsp, usages->last_request_id);
- usages->last_request_id = 0;
- }
+ ted_cancel_lsp_request(ted, &usages->last_request);
}
void usages_find(Ted *ted) {
@@ -23,8 +20,7 @@ void usages_find(Ted *ted) {
refs->include_declaration = true;
refs->position = buffer_cursor_pos_as_lsp_document_position(buffer);
usages_cancel_lookup(ted);
- usages->last_request_lsp = lsp->id;
- usages->last_request_id = lsp_send_request(lsp, &request);
+ usages->last_request= lsp_send_request(lsp, &request);
usages->last_request_time = ted->frame_time;
}
@@ -33,9 +29,9 @@ void usages_process_lsp_response(Ted *ted, const LSPResponse *response) {
Usages *usages = &ted->usages;
if (response->request.type != LSP_REQUEST_REFERENCES)
return; // not for us
- if (response->request.id != usages->last_request_id)
+ if (response->request.id != usages->last_request.id)
return;
- LSP *lsp = ted_get_lsp_by_id(ted, usages->last_request_lsp);
+ LSP *lsp = ted_get_lsp_by_id(ted, usages->last_request.lsp);
const LSPResponseReferences *refs = &response->data.references;
if (lsp && arr_len(refs->locations)) {
TextBuffer *buffer = &ted->build_buffer;
@@ -126,11 +122,11 @@ void usages_process_lsp_response(Ted *ted, const LSPResponse *response) {
} else {
ted_flash_error_cursor(ted);
}
- usages->last_request_id = 0;
+ usages->last_request.id = 0;
}
void usages_frame(Ted *ted) {
Usages *usages = &ted->usages;
- if (usages->last_request_id && ted->frame_time - usages->last_request_time > 0.2)
+ if (usages->last_request.id && ted->frame_time - usages->last_request_time > 0.2)
ted->cursor = ted->cursor_wait; // this request is takin a while
}
diff --git a/lsp.c b/lsp.c
index 34f56ae..e208617 100644
--- a/lsp.c
+++ b/lsp.c
@@ -241,10 +241,10 @@ static bool request_type_is_notification(LSPRequestType type) {
return false;
}
-LSPRequestID lsp_send_request(LSP *lsp, LSPRequest *request) {
+LSPServerRequestID lsp_send_request(LSP *lsp, LSPRequest *request) {
if (!lsp_supports_request(lsp, request)) {
lsp_request_free(request);
- return 0;
+ return (LSPServerRequestID){0};
}
bool is_notification = request_type_is_notification(request->type);
@@ -253,7 +253,10 @@ LSPRequestID lsp_send_request(LSP *lsp, LSPRequest *request) {
LSPMessage message = {.type = LSP_REQUEST};
message.u.request = *request;
lsp_send_message(lsp, &message);
- return request->id;
+ return (LSPServerRequestID) {
+ .lsp = lsp->id,
+ .id = request->id
+ };
}
void lsp_send_response(LSP *lsp, LSPResponse *response) {
diff --git a/lsp.h b/lsp.h
index b87f2a9..61c5610 100644
--- a/lsp.h
+++ b/lsp.h
@@ -18,6 +18,12 @@ typedef struct SDL_mutex *LSPMutex;
typedef struct SDL_semaphore *LSPSemaphore;
typedef struct SDL_Thread *LSPThread;
+// a struct for keeping track of a LSP server ID and a request ID
+typedef struct {
+ LSPID lsp;
+ LSPRequestID id;
+} LSPServerRequestID;
+
// interface Position in the LSP spec
typedef struct {
u32 line;
@@ -587,9 +593,9 @@ void lsp_message_free(LSPMessage *message);
u32 lsp_document_id(LSP *lsp, const char *path);
// returned pointer lives as long as lsp.
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
+// returns the ID of the sent request, or (LSPServerRequestID){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);
+LSPServerRequestID 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);
diff --git a/main.c b/main.c
index d035efc..a1d3cab 100644
--- a/main.c
+++ b/main.c
@@ -1,5 +1,8 @@
/*
@TODO:
+- cancel signature help requests
+- cancel hover requests
+- don't let 0 be a valid LSPDocumentID
- TESTING: check all IDE features with different servers
- run everything through valgrind ideally with leak checking
- some way of opening + closing all C files in directory for clangd
diff --git a/ted.c b/ted.c
index ae1908b..e7f3098 100644
--- a/ted.c
+++ b/ted.c
@@ -637,11 +637,12 @@ void ted_go_to_lsp_document_position(Ted *ted, LSP *lsp, LSPDocumentPosition pos
ted_go_to_position(ted, path, line, character, true);
}
-void ted_cancel_lsp_request(Ted *ted, LSPID lsp, LSPRequestID request) {
+void ted_cancel_lsp_request(Ted *ted, LSPServerRequestID *request) {
if (!request) return;
- LSP *lsp_obj = ted_get_lsp_by_id(ted, lsp);
+ LSP *lsp_obj = ted_get_lsp_by_id(ted, request->lsp);
if (!lsp_obj) return;
- lsp_cancel_request(lsp_obj, request);
+ lsp_cancel_request(lsp_obj, request->id);
+ memset(request, 0, sizeof *request);
}
diff --git a/ted.h b/ted.h
index a17fb23..500ba0d 100644
--- a/ted.h
+++ b/ted.h
@@ -376,8 +376,7 @@ typedef struct {
// or one of the TRIGGER_* constants above
uint32_t trigger;
- LSPID last_request_lsp;
- LSPRequestID last_request_id;
+ LSPServerRequestID last_request;
// when we sent the request to the LSP for completions
// (this is used to figure out when we should display "Loading...")
double last_request_time;
@@ -398,8 +397,7 @@ typedef struct {
// data needed for finding usages
typedef struct {
- LSPID last_request_lsp;
- LSPRequestID last_request_id;
+ LSPServerRequestID last_request;
double last_request_time;
} Usages;
@@ -457,12 +455,8 @@ typedef enum {
} GotoType;
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,
- // last_request_id is set to 0.
- LSPRequestID last_request_id;
+ // information about last LSP request sent
+ LSPServerRequestID last_request;
double last_request_time;
char *last_request_query; // last query string which we sent a request for
@@ -473,8 +467,7 @@ typedef struct {
// "highlight" information from LSP server
typedef struct {
LSPHighlight *highlights;
- LSPRequestID last_request_id;
- LSPID last_request_lsp;
+ LSPServerRequestID last_request;
LSPDocumentPosition requested_position;
} Highlights;
@@ -1373,9 +1366,8 @@ void ted_flash_error_cursor(Ted *ted);
void ted_go_to_position(Ted *ted, const char *path, u32 line, u32 index, bool is_lsp);
// go to this LSP document position, opening a new buffer containing the file if necessary.
void ted_go_to_lsp_document_position(Ted *ted, LSP *lsp, LSPDocumentPosition position);
-// cancel this LSP request. if `lsp` or `request` is 0,
-// or if `lsp` is not a valid LSP ID, nothing happens.
-void ted_cancel_lsp_request(Ted *ted, LSPID lsp, LSPRequestID request);
+// cancel this LSP request. also zeroes *request
+void ted_cancel_lsp_request(Ted *ted, LSPServerRequestID *request);
// how tall is a line buffer?
float ted_line_buffer_height(Ted *ted);
// check for orphaned nodes and node cycles