summaryrefslogtreecommitdiff
path: root/src/lsp/json_rpc.c
diff options
context:
space:
mode:
authorZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-11 15:11:00 +0000
committerZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-11 15:11:00 +0000
commit55247a3f12a9eee7ba3fd7ca6d8fcea7a82c20f3 (patch)
treea2a71e2eb8ca0b2c483518c1902d89d18709c9ab /src/lsp/json_rpc.c
parent2e7abed7cfe84a2c0df371cde35f8f68cfdca16c (diff)
Added src/ folder. Now I will add the rest.
Diffstat (limited to 'src/lsp/json_rpc.c')
-rw-r--r--src/lsp/json_rpc.c192
1 files changed, 192 insertions, 0 deletions
diff --git a/src/lsp/json_rpc.c b/src/lsp/json_rpc.c
new file mode 100644
index 0000000..008a147
--- /dev/null
+++ b/src/lsp/json_rpc.c
@@ -0,0 +1,192 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "json_rpc.h"
+
+// Basic JSON parsing helpers
+char *get_json_string(const char *json, const char *key)
+{
+ char search[256];
+ sprintf(search, "\"%s\":\"", key);
+ char *p = strstr(json, search);
+ if (!p)
+ {
+ return NULL;
+ }
+ p += strlen(search);
+ char *end = strchr(p, '"');
+ if (!end)
+ {
+ return NULL;
+ }
+ int len = end - p;
+ char *res = malloc(len + 1);
+ strncpy(res, p, len);
+ res[len] = 0;
+ return res;
+}
+
+// Extract nested "text" from params/contentChanges/0/text or params/textDocument/text
+// This is very hacky for MVP. proper JSON library needed.
+
+char *get_text_content(const char *json)
+{
+ char *p = strstr(json, "\"text\":\"");
+ if (!p)
+ {
+ return NULL;
+ }
+ p += 8;
+
+ size_t cap = strlen(p);
+ char *res = malloc(cap + 1);
+ char *dst = res;
+
+ while (*p)
+ {
+ if (*p == '\\')
+ {
+ p++;
+ if (*p == 'n')
+ {
+ *dst++ = '\n';
+ }
+ else if (*p == 'r')
+ {
+ *dst++ = '\r';
+ }
+ else if (*p == 't')
+ {
+ *dst++ = '\t';
+ }
+ else if (*p == '"')
+ {
+ *dst++ = '"';
+ }
+ else if (*p == '\\')
+ {
+ *dst++ = '\\';
+ }
+ else
+ {
+ *dst++ = *p; // preserve others
+ }
+ p++;
+ }
+ else if (*p == '"')
+ {
+ break; // End of string.
+ }
+ else
+ {
+ *dst++ = *p++;
+ }
+ }
+ *dst = 0;
+ return res;
+}
+
+// Helper to get line/char
+void get_json_position(const char *json, int *line, int *col)
+{
+ char *pos = strstr(json, "\"position\":");
+ if (!pos)
+ {
+ return;
+ }
+ char *l = strstr(pos, "\"line\":");
+ if (l)
+ {
+ *line = atoi(l + 7);
+ }
+ char *c = strstr(pos, "\"character\":");
+ if (c)
+ {
+ *col = atoi(c + 12);
+ }
+}
+
+void lsp_check_file(const char *uri, const char *src);
+void lsp_goto_definition(const char *uri, int line, int col);
+void lsp_hover(const char *uri, int line, int col);
+void lsp_completion(const char *uri, int line, int col);
+
+void handle_request(const char *json_str)
+{
+ if (strstr(json_str, "\"method\":\"initialize\""))
+ {
+ const char *response =
+ "{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":{\"capabilities\":{\"textDocumentSync\":1,"
+ "\"definitionProvider\":true,\"hoverProvider\":true,\"completionProvider\":{"
+ "\"triggerCharacters\":[\".\"]}}}}";
+ fprintf(stdout, "Content-Length: %ld\r\n\r\n%s", strlen(response), response);
+ fflush(stdout);
+ return;
+ }
+
+ if (strstr(json_str, "\"method\":\"textDocument/didOpen\"") ||
+ strstr(json_str, "\"method\":\"textDocument/didChange\""))
+ {
+
+ char *uri = get_json_string(json_str, "uri");
+ char *text = get_text_content(json_str);
+
+ if (uri && text)
+ {
+ fprintf(stderr, "zls: Checking %s\n", uri);
+ lsp_check_file(uri, text);
+ }
+
+ if (uri)
+ {
+ free(uri);
+ }
+ if (text)
+ {
+ free(text);
+ }
+ }
+
+ if (strstr(json_str, "\"method\":\"textDocument/definition\""))
+ {
+ char *uri = get_json_string(json_str, "uri");
+ int line = 0, col = 0;
+ get_json_position(json_str, &line, &col);
+
+ if (uri)
+ {
+ fprintf(stderr, "zls: Definition request at %d:%d\n", line, col);
+ lsp_goto_definition(uri, line, col);
+ free(uri);
+ }
+ }
+
+ if (strstr(json_str, "\"method\":\"textDocument/hover\""))
+ {
+ char *uri = get_json_string(json_str, "uri");
+ int line = 0, col = 0;
+ get_json_position(json_str, &line, &col);
+
+ if (uri)
+ {
+ fprintf(stderr, "zls: Hover request at %d:%d\n", line, col);
+ lsp_hover(uri, line, col);
+ free(uri);
+ }
+ }
+
+ if (strstr(json_str, "\"method\":\"textDocument/completion\""))
+ {
+ char *uri = get_json_string(json_str, "uri");
+ int line = 0, col = 0;
+ get_json_position(json_str, &line, &col);
+
+ if (uri)
+ {
+ fprintf(stderr, "zls: Completion request at %d:%d\n", line, col);
+ lsp_completion(uri, line, col);
+ free(uri);
+ }
+ }
+}