From b906df08a805e704e45cb7f2bc4b31e83d3222fe Mon Sep 17 00:00:00 2001 From: pommicket Date: Thu, 22 Dec 2022 23:24:08 -0500 Subject: deprecated support! --- autocomplete.c | 21 ++++++++++---- json.c | 87 +++++++++++++++++++++++++++++++++++++--------------------- lsp-parse.c | 19 +++++++++++-- lsp-write.c | 1 + lsp.h | 2 ++ ted.h | 1 + 6 files changed, 91 insertions(+), 40 deletions(-) diff --git a/autocomplete.c b/autocomplete.c index 514c9a5..f6c6ff6 100644 --- a/autocomplete.c +++ b/autocomplete.c @@ -147,6 +147,7 @@ static void autocomplete_process_lsp_response(Ted *ted, const LSPResponse *respo const char *detail = lsp_response_string(response, lsp_completion->detail); ted_completion->detail = *detail ? str_dup(detail) : NULL; ted_completion->kind = lsp_completion_kind_to_ted(lsp_completion->kind); + ted_completion->deprecated = lsp_completion->deprecated; } } autocomplete_update_suggested(ted); @@ -293,13 +294,14 @@ static void autocomplete_frame(Ted *ted) { state.min_x = x + padding; state.min_y = y; state.max_x = x + menu_width - padding; state.max_y = y + menu_height; rgba_u32_to_floats(colors[COLOR_TEXT], state.color); - u8 border_thickness = settings->border_thickness; + float border_thickness = settings->border_thickness; if (ac->waiting_for_lsp) { state.x = x + padding; state.y = y; text_utf8_with_state(font, &state, "Loading..."); } else { for (size_t i = 0; i < ncompletions; ++i) { + const Autocompletion *completion = &completions[i]; state.x = x; state.y = y; if (i != ncompletions-1) { @@ -308,14 +310,14 @@ static void autocomplete_frame(Ted *ted) { colors[COLOR_AUTOCOMPLETE_BORDER]); } - ColorSetting label_color = color_for_symbol_kind(completions[i].kind); + ColorSetting label_color = color_for_symbol_kind(completion->kind); if (!settings->syntax_highlighting) label_color = COLOR_TEXT; rgba_u32_to_floats(colors[label_color], state.color); // draw icon - char icon_text[2] = {symbol_kind_icon(completions[i].kind), 0}; + char icon_text[2] = {symbol_kind_icon(completion->kind), 0}; state.x += padding; text_utf8_with_state(font, &state, icon_text); state.x += padding; @@ -323,10 +325,10 @@ static void autocomplete_frame(Ted *ted) { colors[COLOR_AUTOCOMPLETE_BORDER]); state.x += padding; + float label_x = (float)state.x; + text_utf8_with_state(font, &state, completion->label); - text_utf8_with_state(font, &state, completions[i].label); - - const char *detail = completions[i].detail; + const char *detail = completion->detail; if (detail) { double label_end_x = state.x; @@ -355,6 +357,13 @@ static void autocomplete_frame(Ted *ted) { colors[COLOR_COMMENT], ANCHOR_TOP_RIGHT); } } + + if (completion->deprecated) { + gl_geometry_rect(rect(V2(label_x, y + (char_height - border_thickness) * 0.5f), + V2((float)state.x - label_x, 1)), + colors[COLOR_TEXT]); + } + y += char_height; } } diff --git a/json.c b/json.c index e07b0ec..61c8103 100644 --- a/json.c +++ b/json.c @@ -444,54 +444,79 @@ JSONValue json_object_get(const JSON *json, JSONObject object, const char *name) return (JSONValue){0}; } -// returns (JSONString){0} (which is interpreted as an empty string) if `name` does -// not exist or is not a string. -JSONString json_object_get_string(const JSON *json, JSONObject object, const char *name) { - JSONValue value = json_object_get(json, object, name); - if (value.type == JSON_STRING) { - return value.val.string; +JSONValue json_array_get(const JSON *json, JSONArray array, u64 i) { + if (i < array.len) { + return json->values[array.elements + i]; + } + return (JSONValue){0}; +} + +// returns NaN if `x` is not a number (ha ha). +double json_force_number(JSONValue x) { + if (x.type == JSON_NUMBER) { + return x.val.number; + } else { + return NAN; + } +} + +double json_object_get_number(const JSON *json, JSONObject object, const char *name) { + return json_force_number(json_object_get(json, object, name)); +} + +double json_array_get_number(const JSON *json, JSONArray array, size_t i) { + return json_force_number(json_array_get(json, array, i)); +} + +// returns (JSONString){0} (which is interpreted as an empty string) if `x` is not a string +JSONString json_force_string(JSONValue x) { + if (x.type == JSON_STRING) { + return x.val.string; } else { return (JSONString){0}; } } -// returns (JSONObject){0} (which is interpreted as an empty object) if `name` does -// not exist or is not an object. -JSONObject json_object_get_object(const JSON *json, JSONObject object, const char *name) { - JSONValue value = json_object_get(json, object, name); - if (value.type == JSON_OBJECT) { - return value.val.object; +JSONString json_object_get_string(const JSON *json, JSONObject object, const char *name) { + return json_force_string(json_object_get(json, object, name)); +} + +JSONString json_array_get_string(const JSON *json, JSONArray array, size_t i) { + return json_force_string(json_array_get(json, array, i)); +} + +// returns (JSONObject){0} (which is interpreted as an empty object) if `x` is not an object +JSONObject json_force_object(JSONValue x) { + if (x.type == JSON_OBJECT) { + return x.val.object; } else { return (JSONObject){0}; } } -// returns (JSONArray){0} (which is interpreted as an empty array) if `name` does -// not exist or is not an array. -JSONArray json_object_get_array(const JSON *json, JSONObject object, const char *name) { - JSONValue value = json_object_get(json, object, name); - if (value.type == JSON_ARRAY) { - return value.val.array; +JSONObject json_object_get_object(const JSON *json, JSONObject object, const char *name) { + return json_force_object(json_object_get(json, object, name)); +} + +JSONObject json_array_get_object(const JSON *json, JSONArray array, size_t i) { + return json_force_object(json_array_get(json, array, i)); +} + +// returns (JSONArray){0} (which is interpreted as an empty array) if `x` is not an array +JSONArray json_force_array(JSONValue x) { + if (x.type == JSON_ARRAY) { + return x.val.array; } else { return (JSONArray){0}; } } -// returns NaN if `name` does not exist or is not a number. -double json_object_get_number(const JSON *json, JSONObject object, const char *name) { - JSONValue value = json_object_get(json, object, name); - if (value.type == JSON_NUMBER) { - return value.val.number; - } else { - return NAN; - } +JSONArray json_object_get_array(const JSON *json, JSONObject object, const char *name) { + return json_force_array(json_object_get(json, object, name)); } -JSONValue json_array_get(const JSON *json, JSONArray array, u64 i) { - if (i < array.len) { - return json->values[array.elements + i]; - } - return (JSONValue){0}; +JSONArray json_array_get_array(const JSON *json, JSONArray array, size_t i) { + return json_force_array(json_array_get(json, array, i)); } // e.g. if json is { "a" : { "b": 3 }}, then json_get(json, "a.b") = 3. diff --git a/lsp-parse.c b/lsp-parse.c index 947feb9..6b4dc46 100644 --- a/lsp-parse.c +++ b/lsp-parse.c @@ -106,10 +106,10 @@ static bool parse_completion(LSP *lsp, const JSON *json, LSPResponse *response) arr_set_len(completion->items, items.len); - for (u32 i = 0; i < items.len; ++i) { - LSPCompletionItem *item = &completion->items[i]; + for (u32 item_idx = 0; item_idx < items.len; ++item_idx) { + LSPCompletionItem *item = &completion->items[item_idx]; - JSONValue item_value = json_array_get(json, items, i); + JSONValue item_value = json_array_get(json, items, item_idx); if (!lsp_expect_object(lsp, item_value, "completion list")) return false; JSONObject item_object = item_value.val.object; @@ -141,6 +141,19 @@ static bool parse_completion(LSP *lsp, const JSON *json, LSPResponse *response) item->sort_text = lsp_response_add_json_string(response, json, sort_text); } + JSONValue deprecated = json_object_get(json, item_object, "deprecated"); + if (deprecated.type == JSON_TRUE) { + item->deprecated = true; + } + + JSONArray tags = json_object_get_array(json, item_object, "tags"); + for (u32 i = 0; i < tags.len; ++i) { + double tag = json_array_get_number(json, tags, i); + if (tag == 1 /* deprecated */) { + item->deprecated = true; + } + } + JSONString filter_text = json_object_get_string(json, item_object, "filterText"); if (filter_text.pos) { // LSP allows using a different string for filtering. diff --git a/lsp-write.c b/lsp-write.c index 51f638f..9922862 100644 --- a/lsp-write.c +++ b/lsp-write.c @@ -291,6 +291,7 @@ static void write_request(LSP *lsp, LSPRequest *request) { // completion capabilities write_key_obj_start(o, "completionItem"); write_key_bool(o, "snippetSupport", false); + write_key_bool(o, "deprecatedSupport", true); write_obj_end(o); // "completion item kinds" supported by ted // (these are the little icons displayed for function/variable/etc.) diff --git a/lsp.h b/lsp.h index 0aa8628..612b370 100644 --- a/lsp.h +++ b/lsp.h @@ -207,6 +207,8 @@ typedef struct { // note: the items are sorted here in this file, // so you probably don't need to access this. LSPString sort_text; + // is this function/type/whatever deprecated? + bool deprecated; // type of completion LSPCompletionKind kind; } LSPCompletionItem; diff --git a/ted.h b/ted.h index 7d23088..6f10bfb 100644 --- a/ted.h +++ b/ted.h @@ -368,6 +368,7 @@ typedef struct { char *filter; char *text; char *detail; // this can be NULL! + bool deprecated; SymbolKind kind; } Autocompletion; -- cgit v1.2.3