diff options
Diffstat (limited to 'lsp.c')
-rw-r--r-- | lsp.c | 109 |
1 files changed, 104 insertions, 5 deletions
@@ -1,10 +1,32 @@ +typedef enum { + LSP_INITIALIZE, + LSP_OPEN, + LSP_CHANGE, + LSP_CLOSE, +} LSPRequestType; + +typedef struct { + // buffer language + Language language; + // these will be free'd. + char *filename; + char *file_contents; +} LSPRequestOpen; + +typedef struct { + LSPRequestType type; + union { + LSPRequestOpen open; + } data; +} LSPRequest; + typedef struct { Process process; char error[256]; } LSP; -static void send_request(LSP *lsp, const char *content) { +static void send_request_content(LSP *lsp, const char *content) { char header[128]; size_t content_size = strlen(content); strbuf_printf(header, "Content-Length: %zu\r\n\r\n", content_size); @@ -12,6 +34,84 @@ static void send_request(LSP *lsp, const char *content) { process_write(&lsp->process, content, content_size); } +static const char *lsp_language_id(Language lang) { + switch (lang) { + case LANG_CONFIG: + case LANG_TED_CFG: + case LANG_NONE: + return "text"; + case LANG_C: + return "c"; + case LANG_CPP: + return "cpp"; + case LANG_JAVA: + return "java"; + case LANG_JAVASCRIPT: + return "javascript"; + case LANG_MARKDOWN: + return "markdown"; + case LANG_GO: + return "go"; + case LANG_RUST: + return "rust"; + case LANG_PYTHON: + return "python"; + case LANG_HTML: + return "html"; + case LANG_TEX: + return "latex"; + case LANG_COUNT: break; + } + assert(0); + return "text"; +} + +static void send_request(LSP *lsp, const LSPRequest *request) { + static unsigned long long id; + ++id; + + switch (request->type) { + case LSP_INITIALIZE: { + char content[1024]; + strbuf_printf(content, + "{\"jsonrpc\":\"2.0\",\"id\":%llu,\"method\":\"initialize\",\"params\":{" + "\"processId\":%d," + "\"capabilities\":{}" + "}}", id, process_get_id()); + send_request_content(lsp, content); + } break; + case LSP_OPEN: { + const LSPRequestOpen *open = &request->data.open; + char *escaped_filename = json_escape(open->filename); + char *did_open = a_sprintf( + "{\"jsonrpc\":\"2.0\",\"id\":%llu,\"method\":\"textDocument/open\",\"params\":{" + "textDocument:{" + "uri:\"file://%s\"," + "languageId:\"%s\"," + "version:1," + "text:\"", + id, escaped_filename, lsp_language_id(open->language)); + free(escaped_filename); + + size_t did_open_sz = strlen(did_open) + 2 * strlen(open->file_contents) + 16; + did_open = realloc(did_open, did_open_sz); + + size_t n = json_escape_to(did_open + strlen(did_open), + did_open_sz - 10 - strlen(did_open), + open->file_contents); + char *p = did_open + n; + sprintf(p, "\"}}}"); + + free(did_open); + + send_request_content(lsp, did_open); + } break; + default: + // @TODO + abort(); + } +} + static bool recv_response(LSP *lsp, JSON *json) { static char response_data[500000]; // i think this should always read all the response data. @@ -30,7 +130,7 @@ static bool recv_response(LSP *lsp, JSON *json) { return false; } JSONValue result = json_get(json, "result"); - if (result.type == JSON_NULL) { + if (result.type == JSON_UNDEFINED) { // uh oh JSONValue error = json_get(json, "error.message"); if (error.type == JSON_STRING) { @@ -60,12 +160,11 @@ bool lsp_create(LSP *lsp, const char *analyzer_command) { "\"capabilities\":{}" "}}", process_get_id()); - send_request(lsp, init_request); + send_request_content(lsp, init_request); JSON json = {0}; if (!recv_response(lsp, &json)) { return false; } - JSONValue response = json_get(&json, "result.capabilities.textDocumentSync.openClose"); - json_debug_print_value(&json, &response);printf("\n"); + json_debug_print(&json); return true; } |