summaryrefslogtreecommitdiff
path: root/lsp.c
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2023-09-13 23:11:15 -0400
committerpommicket <pommicket@gmail.com>2023-09-14 10:47:51 -0400
commit52015e0c9a4e3bc8dc558929a85461f079dda303 (patch)
treebfdf9bda87934dbd96d4da1e87454d22184545b7 /lsp.c
parente33379bab95031555ed5459ee8a73672f24fd0a0 (diff)
batch write requests, fix tiny memory leak in ide-autocomplete
Diffstat (limited to 'lsp.c')
-rw-r--r--lsp.c102
1 files changed, 70 insertions, 32 deletions
diff --git a/lsp.c b/lsp.c
index 274176c..bb1b5e9 100644
--- a/lsp.c
+++ b/lsp.c
@@ -483,6 +483,42 @@ static bool lsp_receive(LSP *lsp, size_t max_size) {
return true;
}
+/// send string to LSP
+static void lsp_send_string(LSP *lsp, const char *str, size_t len) {
+ if (len == 0) {
+ return;
+ }
+ const long long bytes_written = lsp->socket
+ ? socket_write(lsp->socket, str, len)
+ : process_write(lsp->process, str, len);
+ if (bytes_written == -1) {
+ // we'll handle this properly next time we do a read.
+ if (lsp->log) fprintf(lsp->log, "LSP server closed connection unexpectedly\n");
+ } else if (bytes_written < 0) {
+ if (lsp->log) fprintf(lsp->log, "Error writing to LSP server (errno = %d)\n", errno);
+ } else {
+ assert((size_t)bytes_written == len);
+ }
+
+ if (lsp->log) {
+ fprintf(lsp->log, "LSP CLIENT TO SERVER\n%.*s\n\n", (int)len, str);
+ }
+ #if LSP_SHOW_C2S
+ const int limit = (int)min_u64(1000, len);
+ debug_println("%s%.*s%s%s",term_bold(stdout),limit,str,
+ len > (size_t)limit ? "..." : "",
+ term_clear(stdout));
+ #endif
+
+}
+
+void lsp_send_request_direct(LSP *lsp, LSPRequest *request) {
+ StrBuilder b = str_builder_new();
+ write_request(lsp, request, &b);
+ lsp_send_string(lsp, b.str, str_builder_len(&b));
+ str_builder_free(&b);
+}
+
/// send requests.
///
/// returns `false` if we should quit.
@@ -494,22 +530,28 @@ static bool lsp_send(LSP *lsp) {
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);
-
- #if __GNUC__ && !__clang__
- #pragma GCC diagnostic push
- // i don't know why GCC is giving me this. some compiler bug.
- #pragma GCC diagnostic ignored "-Wfree-nonheap-object"
- #endif
- arr_clear(lsp->messages_client2server);
- #if __GNUC__ && !__clang__
- #pragma GCC diagnostic pop
- #endif
-
+ size_t n_messages = arr_len(lsp->messages_client2server);
+ if (n_messages) {
+ messages = calloc(n_messages, sizeof *messages);
+ memcpy(messages, lsp->messages_client2server, n_messages * sizeof *messages);
+ }
+ #if __GNUC__ && !__clang__
+ #pragma GCC diagnostic push
+ // i don't know why GCC is giving me this. some compiler bug.
+ #pragma GCC diagnostic ignored "-Wfree-nonheap-object"
+ #endif
+ arr_clear(lsp->messages_client2server);
+ #if __GNUC__ && !__clang__
+ #pragma GCC diagnostic pop
+ #endif
SDL_UnlockMutex(lsp->messages_mutex);
+ if (!messages) {
+ // nothing to do
+ return true;
+ }
+
+ StrBuilder builder = str_builder_new();
bool alive = true;
for (size_t i = 0; i < n_messages; ++i) {
LSPMessage *m = &messages[i];
@@ -538,7 +580,7 @@ static bool lsp_send(LSP *lsp) {
}
if (send) {
- write_message(lsp, m);
+ write_message(lsp, m, &builder);
} else {
lsp_message_free(m);
}
@@ -547,7 +589,8 @@ static bool lsp_send(LSP *lsp) {
alive = false;
}
}
-
+ lsp_send_string(lsp, builder.str, str_builder_len(&builder));
+ str_builder_free(&builder);
free(messages);
return alive;
}
@@ -571,25 +614,15 @@ static int lsp_communication_thread(void *data) {
.type = LSP_REQUEST_INITIALIZE
};
initialize.id = get_request_id();
- write_request(lsp, &initialize);
+ lsp_send_request_direct(lsp, &initialize);
- const double send_delay = lsp->send_delay;
- double last_send = -DBL_MAX;
+ const u32 send_delay_ms = max_u32(16, (u32)(lsp->send_delay * 1000));
while (1) {
- bool send = true;
- if (send_delay > 0) {
- double t = time_get_seconds();
- if (t - last_send > send_delay) {
- last_send = t;
- } else {
- send = false;
- }
- }
- if (send && !lsp_send(lsp))
+ if (!lsp_send(lsp))
break;
if (!lsp_receive(lsp, (size_t)10<<20))
break;
- if (SDL_SemWaitTimeout(lsp->quit_sem, 5) == 0)
+ if (SDL_SemWaitTimeout(lsp->quit_sem, send_delay_ms) == 0)
break;
}
@@ -611,8 +644,13 @@ static int lsp_communication_thread(void *data) {
// just spam these things
// we're supposed to be nice and wait for the shutdown
// response, but who gives a fuck
- write_request(lsp, &shutdown);
- write_request(lsp, &exit);
+ {
+ StrBuilder b = str_builder_new();
+ write_request(lsp, &shutdown, &b);
+ write_request(lsp, &exit, &b);
+ lsp_send_string(lsp, b.str, str_builder_len(&b));
+ str_builder_free(&b);
+ }
}
return 0;
}