From 9a5cad47fe6a8b84892f62e110ca887c95df5eff Mon Sep 17 00:00:00 2001 From: pommicket Date: Mon, 26 Dec 2022 20:41:43 -0500 Subject: workspace/workspaceFolders request --- lsp-parse.c | 6 ++++-- lsp-write.c | 50 +++++++++++++++++++++++++++++---------------- lsp.c | 68 ++++++++++++++++++++++++++++++++++++++++--------------------- lsp.h | 6 ++---- main.c | 5 ++++- 5 files changed, 87 insertions(+), 48 deletions(-) diff --git a/lsp-parse.c b/lsp-parse.c index de63401..6d436d9 100644 --- a/lsp-parse.c +++ b/lsp-parse.c @@ -370,6 +370,7 @@ static void process_message(LSP *lsp, JSON *json) { JSONValue result = json_get(json, "result"); if (result.type != JSON_UNDEFINED) { + // server-to-client response LSPResponse response = {0}; bool add_to_messages = false; response.request = response_to; @@ -405,7 +406,7 @@ static void process_message(LSP *lsp, JSON *json) { } if (add_to_messages) { SDL_LockMutex(lsp->messages_mutex); - LSPMessage *message = arr_addp(lsp->messages); + LSPMessage *message = arr_addp(lsp->messages_server2client); message->type = LSP_RESPONSE; message->u.response = response; SDL_UnlockMutex(lsp->messages_mutex); @@ -414,10 +415,11 @@ static void process_message(LSP *lsp, JSON *json) { lsp_response_free(&response); } } else if (json_has(json, "method")) { + // server-to-client request LSPRequest request = {0}; if (parse_server2client_request(lsp, json, &request)) { SDL_LockMutex(lsp->messages_mutex); - LSPMessage *message = arr_addp(lsp->messages); + LSPMessage *message = arr_addp(lsp->messages_server2client); message->type = LSP_REQUEST; message->u.request = request; SDL_UnlockMutex(lsp->messages_mutex); diff --git a/lsp-write.c b/lsp-write.c index ef60b91..5d402c4 100644 --- a/lsp-write.c +++ b/lsp-write.c @@ -463,9 +463,9 @@ static void write_request(LSP *lsp, LSPRequest *request) { if (is_notification) { lsp_request_free(request); } else { - SDL_LockMutex(lsp->requests_mutex); + SDL_LockMutex(lsp->messages_mutex); arr_add(lsp->requests_sent, *request); - SDL_UnlockMutex(lsp->requests_mutex); + SDL_UnlockMutex(lsp->messages_mutex); } } @@ -477,24 +477,38 @@ static void write_response(LSP *lsp, LSPResponse *response) { JSONWriter *o = &writer; LSPRequest *request = &response->request; - if (request->id_string) - write_key_string(o, "id", request->id_string); - else - write_key_number(o, "id", request->id); - write_key_obj_start(o, "result"); - - switch (response->request.type) { - case LSP_REQUEST_WORKSPACE_FOLDERS: - write_workspace_folders(o, lsp->workspace_folders); - break; - default: - // this is not a valid client-to-server response. - assert(0); - break; - } + write_obj_start(o); + if (request->id_string) + write_key_string(o, "id", request->id_string); + else + write_key_number(o, "id", request->id); + write_key_string(o, "jsonrpc", "2.0"); + write_key(o, "result"); + switch (response->request.type) { + case LSP_REQUEST_WORKSPACE_FOLDERS: + write_workspace_folders(o, lsp->workspace_folders); + break; + default: + // this is not a valid client-to-server response. + assert(0); + break; + } write_obj_end(o); message_writer_write_and_free(lsp, o); - lsp_response_free(response); } + +static void write_message(LSP *lsp, LSPMessage *message) { + switch (message->type) { + case LSP_REQUEST: + write_request(lsp, &message->u.request); + break; + case LSP_RESPONSE: + write_response(lsp, &message->u.response); + break; + } + // it's okay to free the message here since the request/response part has been zeroed. + // (as i'm writing this, this won't do anything but it might in the future) + lsp_message_free(message); +} diff --git a/lsp.c b/lsp.c index 4267fd3..0c9aede 100644 --- a/lsp.c +++ b/lsp.c @@ -130,14 +130,26 @@ static bool lsp_supports_request(LSP *lsp, const LSPRequest *request) { return false; } +void lsp_send_message(LSP *lsp, LSPMessage *message) { + SDL_LockMutex(lsp->messages_mutex); + arr_add(lsp->messages_client2server, *message); + SDL_UnlockMutex(lsp->messages_mutex); +} + void lsp_send_request(LSP *lsp, LSPRequest *request) { if (!lsp_supports_request(lsp, request)) { lsp_request_free(request); return; } - SDL_LockMutex(lsp->requests_mutex); - arr_add(lsp->requests_client2server, *request); - SDL_UnlockMutex(lsp->requests_mutex); + LSPMessage message = {.type = LSP_REQUEST}; + message.u.request = *request; + lsp_send_message(lsp, &message); +} + +void lsp_send_response(LSP *lsp, LSPResponse *response) { + LSPMessage message = {.type = LSP_RESPONSE}; + message.u.response = *response; + lsp_send_message(lsp, &message); } const char *lsp_response_string(const LSPResponse *response, LSPString string) { @@ -215,21 +227,21 @@ static bool lsp_send(LSP *lsp) { return false; } - LSPRequest *requests = NULL; - SDL_LockMutex(lsp->requests_mutex); - size_t n_requests = arr_len(lsp->requests_client2server); - requests = calloc(n_requests, sizeof *requests); - memcpy(requests, lsp->requests_client2server, n_requests * sizeof *requests); - arr_clear(lsp->requests_client2server); - SDL_UnlockMutex(lsp->requests_mutex); + LSPMessage *messages = NULL; + SDL_LockMutex(lsp->messages_mutex); + size_t n_messages = arr_len(lsp->messages_client2server); + messages = calloc(n_messages, sizeof *messages); + memcpy(messages, lsp->messages_client2server, n_messages * sizeof *messages); + arr_clear(lsp->messages_client2server); + SDL_UnlockMutex(lsp->messages_mutex); bool quit = false; - for (size_t i = 0; i < n_requests; ++i) { - LSPRequest *r = &requests[i]; + for (size_t i = 0; i < n_messages; ++i) { + LSPMessage *m = &messages[i]; if (quit) { - lsp_request_free(r); + lsp_message_free(m); } else { - write_request(lsp, r); + write_message(lsp, m); } if (SDL_SemTryWait(lsp->quit_sem) == 0) { @@ -237,7 +249,7 @@ static bool lsp_send(LSP *lsp) { } } - free(requests); + free(messages); return quit; } @@ -315,7 +327,6 @@ LSP *lsp_create(const char *root_dir, Language language, const char *analyzer_co lsp->language = language; lsp->quit_sem = SDL_CreateSemaphore(0); lsp->messages_mutex = SDL_CreateMutex(); - lsp->requests_mutex = SDL_CreateMutex(); ProcessSettings settings = { .stdin_blocking = true, @@ -338,9 +349,9 @@ LSP *lsp_create(const char *root_dir, Language language, const char *analyzer_co bool lsp_next_message(LSP *lsp, LSPMessage *message) { bool any = false; SDL_LockMutex(lsp->messages_mutex); - if (arr_len(lsp->messages)) { - *message = lsp->messages[0]; - arr_remove(lsp->messages, 0); + if (arr_len(lsp->messages_server2client)) { + *message = lsp->messages_server2client[0]; + arr_remove(lsp->messages_server2client, 0); any = true; } SDL_UnlockMutex(lsp->messages_mutex); @@ -351,21 +362,32 @@ void lsp_free(LSP *lsp) { SDL_SemPost(lsp->quit_sem); SDL_WaitThread(lsp->communication_thread, NULL); SDL_DestroyMutex(lsp->messages_mutex); - SDL_DestroyMutex(lsp->requests_mutex); SDL_DestroySemaphore(lsp->quit_sem); process_kill(&lsp->process); + arr_free(lsp->received_data); + str_hash_table_clear(&lsp->document_ids); for (size_t i = 0; i < arr_len(lsp->document_data); ++i) free(lsp->document_data[i].path); arr_free(lsp->document_data); - arr_foreach_ptr(lsp->messages, LSPMessage, message) { + + arr_foreach_ptr(lsp->messages_server2client, LSPMessage, message) lsp_message_free(message); - } + arr_free(lsp->messages_server2client); + + arr_foreach_ptr(lsp->messages_client2server, LSPMessage, message) + lsp_message_free(message); + arr_free(lsp->messages_client2server); + + arr_foreach_ptr(lsp->requests_sent, LSPRequest, r) + lsp_request_free(r); + arr_free(lsp->requests_sent); + arr_foreach_ptr(lsp->workspace_folders, char *, folder) free(*folder); arr_free(lsp->workspace_folders); - arr_free(lsp->messages); + arr_free(lsp->trigger_chars); memset(lsp, 0, sizeof *lsp); free(lsp); diff --git a/lsp.h b/lsp.h index 666ff1b..85993cb 100644 --- a/lsp.h +++ b/lsp.h @@ -259,15 +259,13 @@ typedef struct LSP { // this is a dynamic array which just keeps growing. // but the user isn't gonna open millions of files so it's fine. LSPDocumentData *document_data; - LSPMessage *messages; SDL_mutex *messages_mutex; - LSPRequest *requests_client2server; - LSPRequest *requests_server2client; + LSPMessage *messages_server2client; + LSPMessage *messages_client2server; // we keep track of client-to-server requests // so that we can process responses. // this also lets us re-send requests if that's ever necessary. LSPRequest *requests_sent; - SDL_mutex *requests_mutex; bool initialized; // has the response to the initialize request been sent? SDL_Thread *communication_thread; SDL_sem *quit_sem; diff --git a/main.c b/main.c index 7fdb6de..9339b95 100644 --- a/main.c +++ b/main.c @@ -1,9 +1,9 @@ /* @TODO: -- what's wrong with gopls? - ignore telemetry/event - handle window/showMessageRequest - make sure "save as" works +- what's wrong with gopls? - more LSP stuff: - hover - go to definition using LSP @@ -17,6 +17,8 @@ - run everything through valgrind ideally with leak checking - grep -i -n TODO *.[ch] --- LSP MERGE --- +- improve structure of ted source code to make LSP completions better + (make every c file a valid translation unit) - rename buffer->filename to buffer->path - make buffer->path NULL for untitled buffers & fix resulting mess - rust-analyzer bug reports: @@ -1083,6 +1085,7 @@ int main(int argc, char **argv) { SDL_SetWindowTitle(window, ted->window_title); SDL_SetCursor(ted->cursor); + // annoyingly, SDL_GL_SwapWindow seems to be a busy loop on my laptop for some reason... // enforce a framerate of 60. this isn't ideal but SDL_GetDisplayMode is *extremely slow* (250ms), so we don't really have a choice. int refresh_rate = 60; -- cgit v1.2.3