diff options
author | pommicket <pommicket@gmail.com> | 2023-09-07 14:38:49 -0400 |
---|---|---|
committer | pommicket <pommicket@gmail.com> | 2023-09-07 14:38:49 -0400 |
commit | 815d652b570f53c989f62d0c7db847d7d6dfd940 (patch) | |
tree | c977583cfcc5b682a8cee5546bcf3c837014df1b | |
parent | bb4b7774aabc2686f936935b02899b1aa0bf1f2b (diff) |
textDocument/publishDiagnostics parsing
-rw-r--r-- | lsp-parse.c | 53 | ||||
-rw-r--r-- | lsp-write.c | 8 | ||||
-rw-r--r-- | lsp.c | 7 | ||||
-rw-r--r-- | lsp.h | 26 | ||||
-rw-r--r-- | main.c | 3 | ||||
-rw-r--r-- | ted-internal.h | 2 | ||||
-rw-r--r-- | ted.c | 6 |
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); @@ -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: @@ -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; @@ -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_ @@ -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)); +} |