summaryrefslogtreecommitdiff
path: root/lsp.c
diff options
context:
space:
mode:
Diffstat (limited to 'lsp.c')
-rw-r--r--lsp.c109
1 files changed, 75 insertions, 34 deletions
diff --git a/lsp.c b/lsp.c
index 980a2b2..8b62853 100644
--- a/lsp.c
+++ b/lsp.c
@@ -36,9 +36,31 @@ typedef struct {
SDL_Thread *communication_thread;
SDL_sem *quit_sem;
char *received_data; // dynamic array
+ SDL_mutex *error_mutex;
char error[256];
} LSP;
+// returns true if there's an error.
+// returns false and sets error to "" if there's no error.
+// if clear = true, the error will be cleared.
+// you may set error = NULL, error_size = 0, clear = true to just clear the error
+bool lsp_get_error(LSP *lsp, char *error, size_t error_size, bool clear) {
+ bool has_err = false;
+ SDL_LockMutex(lsp->error_mutex);
+ has_err = *lsp->error != '\0';
+ if (error_size)
+ str_cpy(error, error_size, lsp->error);
+ if (clear)
+ *lsp->error = '\0';
+ SDL_UnlockMutex(lsp->error_mutex);
+ return has_err;
+}
+
+#define lsp_set_error(lsp, ...) do {\
+ SDL_LockMutex(lsp->error_mutex);\
+ strbuf_printf(lsp->error, __VA_ARGS__);\
+ SDL_UnlockMutex(lsp->error_mutex);\
+ } while (0)
static void write_request_content(LSP *lsp, const char *content) {
char header[128];
@@ -136,7 +158,7 @@ static u64 write_request(LSP *lsp, const LSPRequest *request) {
char content[1024];
// no params needed
strbuf_printf(content,
- "{\"jsonrpc\":\"2.0\",\"id\":%llu,\"method\":\"initialize\",\"params\":{"
+ "{\"jsonrpc\":\"2.0\",\"id\":%llu,\"method\":\"textDocument/completion\",\"params\":{"
"}}", id);
write_request_content(lsp, content);
} break;
@@ -177,6 +199,50 @@ void lsp_send_request(LSP *lsp, const LSPRequest *request) {
SDL_UnlockMutex(lsp->requests_mutex);
}
+static void process_response(LSP *lsp, const JSON *json) {
+
+ #if 1
+ printf("\x1b[3m");
+ json_debug_print(json);
+ printf("\x1b[0m\n");
+ #endif
+
+
+ JSONValue result = json_get(json, "result");
+ JSONValue id = json_get(json, "id");
+
+ if (result.type == JSON_UNDEFINED || id.type != JSON_NUMBER) {
+ // uh oh
+ JSONValue error = json_get(json, "error.message");
+ if (error.type == JSON_STRING) {
+ char err[256] = {0};
+ json_string_get(json, &error.val.string, err, sizeof err);;
+ lsp_set_error(lsp, "%s", err);
+ } else {
+ lsp_set_error(lsp, "Server error (no message)");
+ }
+ } else if (id.val.number == 0) {
+ // it's the response to our initialize request!
+ // let's send back an "initialized" request (notification) because apparently
+ // that's something we need to do.
+ LSPRequest initialized = {
+ .type = LSP_INITIALIZED,
+ .data = {0},
+ };
+ u64 initialized_id = write_request(lsp, &initialized);
+ // this should be the second request.
+ (void)initialized_id;
+ assert(initialized_id == 1);
+ // we can now send requests which have nothing to do with initialization
+ lsp->initialized = true;
+ } else {
+ SDL_LockMutex(lsp->responses_mutex);
+ arr_add(lsp->responses, *json);
+ SDL_UnlockMutex(lsp->responses_mutex);
+ }
+
+}
+
// receive responses from LSP, up to max_size bytes.
static void lsp_receive(LSP *lsp, size_t max_size) {
@@ -214,41 +280,15 @@ static void lsp_receive(LSP *lsp, size_t max_size) {
while (has_response(lsp->received_data, received_so_far, &response_offset, &response_size)) {
char *copy = strn_dup(lsp->received_data + response_offset, response_size);
JSON json = {0};
- json_parse(&json, copy);
- assert(json.text == copy);
- json.is_text_copied = true;
-
- JSONValue result = json_get(&json, "result");
- JSONValue id = json_get(&json, "id");
-
- if (result.type == JSON_UNDEFINED || id.type != JSON_NUMBER) {
- // uh oh
- JSONValue error = json_get(&json, "error.message");
- if (error.type == JSON_STRING) {
- json_string_get(&json, &error.val.string, lsp->error, sizeof lsp->error);
- } else {
- strbuf_printf(lsp->error, "Server error (no message)");
- }
- } else if (id.val.number == 0) {
- // it's the response to our initialize request!
- // let's send back an "initialized" request (notification) because apparently
- // that's something we need to do.
- LSPRequest initialized = {
- .type = LSP_INITIALIZED,
- .data = {0},
- };
- u64 initialized_id = write_request(lsp, &initialized);
- // this should be the second request.
- (void)initialized_id;
- assert(initialized_id == 1);
- // we can now send requests which have nothing to do with initialization
- lsp->initialized = true;
+ if (json_parse(&json, copy)) {
+ assert(json.text == copy);
+ json.is_text_copied = true;
+ process_response(lsp, &json);
} else {
- SDL_LockMutex(lsp->responses_mutex);
- arr_add(lsp->responses, json);
- SDL_UnlockMutex(lsp->responses_mutex);
+
+ lsp_set_error(lsp, "couldn't parse response JSON: %s", json.error);
+ json_free(&json);
}
-
size_t leftover_data_len = arr_len(lsp->received_data) - (response_offset + response_size);
memmove(lsp->received_data, lsp->received_data + response_offset + response_size,
leftover_data_len);
@@ -289,6 +329,7 @@ static bool lsp_send(LSP *lsp) {
size_t n_requests = arr_len(lsp->requests);
requests = calloc(n_requests, sizeof *requests);
memcpy(requests, lsp->requests, n_requests * sizeof *requests);
+ arr_clear(lsp->requests);
SDL_UnlockMutex(lsp->requests_mutex);
bool quit = false;