summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lsp-parse.c53
-rw-r--r--lsp-write.c8
-rw-r--r--lsp.c7
-rw-r--r--lsp.h26
-rw-r--r--main.c3
-rw-r--r--ted-internal.h2
-rw-r--r--ted.c6
7 files changed, 104 insertions, 1 deletions
diff --git a/lsp-parse.c b/lsp-parse.c
index ace4881..5337de5 100644
--- a/lsp-parse.c
+++ b/lsp-parse.c
@@ -708,6 +708,56 @@ static bool parse_window_message(LSP *lsp, const JSON *json, LSPRequest *request
return true;
}
+static bool parse_diagnostic(LSP *lsp, LSPRequest *request, const JSON *json, JSONObject diagnostic_in, LSPDiagnostic *diagnostic_out) {
+ if (!parse_range(lsp, json, json_object_get(json, diagnostic_in, "range"),
+ &diagnostic_out->range))
+ return false;
+ diagnostic_out->message = lsp_request_add_json_string(
+ request, json,
+ json_object_get_string(json, diagnostic_in, "request")
+ );
+ JSONValue severity_val = json_object_get(json, diagnostic_in, "severity");
+ LSPDiagnosticSeverity severity = LSP_DIAGNOSTIC_SEVERITY_INFORMATION;
+ if (severity_val.type == JSON_NUMBER) {
+ int s = (int)json_force_number(severity_val);
+ if (s >= LSP_DIAGNOSTIC_SEVERITY_MIN && s <= LSP_DIAGNOSTIC_SEVERITY_MAX) {
+ severity = (LSPDiagnosticSeverity)s;
+ }
+ }
+ diagnostic_out->severity = severity;
+ JSONValue code_val = json_object_get(json, diagnostic_in, "code");
+ if (code_val.type == JSON_NUMBER) {
+ int code = (int)code_val.val.number;
+ char string[32] = {0};
+ strbuf_printf(string, "%d", code);
+ diagnostic_out->code = lsp_request_add_string(request, string);
+ } else if (code_val.type == JSON_STRING) {
+ diagnostic_out->code = lsp_request_add_json_string(request, json, code_val.val.string);
+ }
+ JSONObject code_description = json_object_get_object(json, diagnostic_in, "codeDescription");
+ diagnostic_out->code_description_uri = lsp_request_add_json_string(
+ request, json,
+ json_object_get_string(json, code_description, "href")
+ );
+ return true;
+}
+
+static bool parse_publish_diagnostics(LSP *lsp, const JSON *json, LSPRequest *request) {
+ LSPRequestPublishDiagnostics *pub = &request->data.publish_diagnostics;
+ JSONObject params = json_force_object(json_get(json, "params"));
+ JSONValue uri_val = json_object_get(json, params, "uri");
+ if (!parse_document_uri(lsp, json, uri_val, &pub->document))
+ return false;
+ JSONArray diagnostics = json_object_get_array(json, params, "diagnostics");
+ for (u32 i = 0; i < diagnostics.len; ++i) {
+ JSONObject diagnostic_in = json_array_get_object(json, diagnostics, i);
+ LSPDiagnostic *diagnostic_out = arr_addp(pub->diagnostics);
+ if (!parse_diagnostic(lsp, request, json, diagnostic_in, diagnostic_out))
+ return false;
+ }
+ return true;
+}
+
// returns true if `request` was actually filled with a request.
static bool parse_server2client_request(LSP *lsp, JSON *json, LSPRequest *request) {
JSONValue method_value = json_get(json, "method");
@@ -750,7 +800,8 @@ static bool parse_server2client_request(LSP *lsp, JSON *json, LSPRequest *reques
} else if (str_has_prefix(method, "$/") || str_has_prefix(method, "telemetry/")) {
// we can safely ignore this
} else if (streq(method, "textDocument/publishDiagnostics")) {
- // currently ignored
+ request->type = LSP_REQUEST_PUBLISH_DIAGNOSTICS;
+ return parse_publish_diagnostics(lsp, json, request);
} else {
debug_println("Unrecognized request method: %s", method);
}
diff --git a/lsp-write.c b/lsp-write.c
index 99a4e82..fd80799 100644
--- a/lsp-write.c
+++ b/lsp-write.c
@@ -274,6 +274,8 @@ static const char *lsp_request_method(LSPRequest *request) {
return "textDocument/completion";
case LSP_REQUEST_SIGNATURE_HELP:
return "textDocument/signatureHelp";
+ case LSP_REQUEST_PUBLISH_DIAGNOSTICS:
+ return "textDocument/publishDiagnostics";
case LSP_REQUEST_HOVER:
return "textDocument/hover";
case LSP_REQUEST_REFERENCES:
@@ -392,6 +394,7 @@ void write_request(LSP *lsp, LSPRequest *request) {
case LSP_REQUEST_SHOW_MESSAGE:
case LSP_REQUEST_LOG_MESSAGE:
case LSP_REQUEST_WORKSPACE_FOLDERS:
+ case LSP_REQUEST_PUBLISH_DIAGNOSTICS:
assert(0);
break;
case LSP_REQUEST_SHUTDOWN:
@@ -454,6 +457,11 @@ void write_request(LSP *lsp, LSPRequest *request) {
write_key_obj_start(o, "documentLink");
write_key_bool(o, "tooltipSupport", true);
write_obj_end(o);
+
+ // publish diagnostics capabilities
+ write_key_obj_start(o, "publishDiagnostics");
+ write_key_bool(o, "codeDescriptionSupport", true);
+ write_obj_end(o);
write_obj_end(o);
write_key_obj_start(o, "workspace");
write_key_bool(o, "workspaceFolders", true);
diff --git a/lsp.c b/lsp.c
index 5944c29..ec9d3d7 100644
--- a/lsp.c
+++ b/lsp.c
@@ -119,6 +119,11 @@ void lsp_request_free(LSPRequest *r) {
case LSP_REQUEST_DOCUMENT_LINK:
case LSP_REQUEST_CONFIGURATION:
case LSP_REQUEST_DID_OPEN:
+ break;
+ case LSP_REQUEST_PUBLISH_DIAGNOSTICS: {
+ LSPRequestPublishDiagnostics *pub = &r->data.publish_diagnostics;
+ arr_free(pub->diagnostics);
+ } break;
case LSP_REQUEST_SHOW_MESSAGE:
case LSP_REQUEST_LOG_MESSAGE:
case LSP_REQUEST_RENAME:
@@ -209,6 +214,7 @@ static bool lsp_supports_request(LSP *lsp, const LSPRequest *request) {
case LSP_REQUEST_SHOW_MESSAGE:
case LSP_REQUEST_LOG_MESSAGE:
case LSP_REQUEST_WORKSPACE_FOLDERS:
+ case LSP_REQUEST_PUBLISH_DIAGNOSTICS:
return false;
case LSP_REQUEST_INITIALIZE:
case LSP_REQUEST_INITIALIZED:
@@ -268,6 +274,7 @@ static bool request_type_is_notification(LSPRequestType type) {
case LSP_REQUEST_DID_CHANGE:
case LSP_REQUEST_DID_CHANGE_WORKSPACE_FOLDERS:
case LSP_REQUEST_CONFIGURATION:
+ case LSP_REQUEST_PUBLISH_DIAGNOSTICS:
return true;
case LSP_REQUEST_INITIALIZE:
case LSP_REQUEST_SHUTDOWN:
diff --git a/lsp.h b/lsp.h
index a03256d..1d9d8ee 100644
--- a/lsp.h
+++ b/lsp.h
@@ -94,6 +94,7 @@ typedef enum {
LSP_REQUEST_SHOW_MESSAGE, //< window/showMessage and window/showMessageRequest
LSP_REQUEST_LOG_MESSAGE, //< window/logMessage
LSP_REQUEST_WORKSPACE_FOLDERS, //< workspace/workspaceFolders - NOTE: this is handled directly in lsp-parse.c (because it only needs information from the LSP struct)
+ LSP_REQUEST_PUBLISH_DIAGNOSTICS, //< textDocument/publishDiagnostics
} LSPRequestType;
typedef enum {
@@ -148,6 +149,30 @@ typedef struct {
LSPString message;
} LSPRequestMessage;
+typedef enum {
+#define LSP_DIAGNOSTIC_SEVERITY_MIN 1
+ LSP_DIAGNOSTIC_SEVERITY_ERROR = 1,
+ LSP_DIAGNOSTIC_SEVERITY_WARNING = 2,
+ LSP_DIAGNOSTIC_SEVERITY_INFORMATION = 3,
+ LSP_DIAGNOSTIC_SEVERITY_HINT = 4,
+#define LSP_DIAGNOSTIC_SEVERITY_MAX 4
+} LSPDiagnosticSeverity;
+
+typedef struct {
+ LSPRange range;
+ LSPDiagnosticSeverity severity;
+ LSPString code;
+ LSPString message;
+ /// URI to description of code
+ /// e.g. for Rust's E0621, this would be https://doc.rust-lang.org/error_codes/E0621.html
+ LSPString code_description_uri;
+} LSPDiagnostic;
+
+typedef struct {
+ LSPDocumentID document;
+ LSPDiagnostic *diagnostics; // dynamic array
+} LSPRequestPublishDiagnostics;
+
/// these triggers are used for completion context and signature help context.
#define LSP_TRIGGER_NONE 0 // not actually defined in LSP spec
@@ -247,6 +272,7 @@ typedef struct {
LSPRequestDidChangeWorkspaceFolders change_workspace_folders;
LSPRequestRename rename;
LSPRequestDocumentLink document_link;
+ LSPRequestPublishDiagnostics publish_diagnostics;
} data;
} LSPRequest;
diff --git a/main.c b/main.c
index 1bb1163..12324ce 100644
--- a/main.c
+++ b/main.c
@@ -885,6 +885,9 @@ int main(int argc, char **argv) {
LSPRequestMessage *m = &r->data.message;
ted_log(ted, "%s\n", lsp_request_string(r, m->message));
} break;
+ case LSP_REQUEST_PUBLISH_DIAGNOSTICS: {
+ ted_process_publish_diagnostics(ted, r);
+ } break;
default: break;
}
} break;
diff --git a/ted-internal.h b/ted-internal.h
index 406ce55..49ca912 100644
--- a/ted-internal.h
+++ b/ted-internal.h
@@ -711,5 +711,7 @@ void ted_color_settings_for_message_type(MessageType type, ColorSetting *bg_colo
void ted_load_fonts(Ted *ted);
/// Free all of ted's fonts.
void ted_free_fonts(Ted *ted);
+/// process textDocument/publishDiagnostics request
+void ted_process_publish_diagnostics(Ted *ted, LSPRequest *request);
#endif // TED_INTERNAL_H_
diff --git a/ted.c b/ted.c
index 762b269..7ce2e87 100644
--- a/ted.c
+++ b/ted.c
@@ -875,3 +875,9 @@ bool ted_close_buffer_with_file(Ted *ted, const char *path) {
ted_close_buffer(ted, buffer);
return true;
}
+
+void ted_process_publish_diagnostics(Ted *ted, LSPRequest *request) {
+ assert(request->type == LSP_REQUEST_PUBLISH_DIAGNOSTICS);
+ LSPRequestPublishDiagnostics *pub = &request->data.publish_diagnostics;
+ printf("%u diagnostics\n",arr_len(pub->diagnostics));
+}