summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2023-01-03 23:22:15 -0500
committerpommicket <pommicket@gmail.com>2023-01-03 23:22:15 -0500
commitb6460a7aac5196b8cb6174bdaa8cc2ab82310380 (patch)
treedd6be579865b4b3bb62a4d709a4347bf2bf1446e
parentadabc989a118190a4dc7e85315b5a337b806b314 (diff)
handle multiple definitions of a symbol with the same name
in the definitions menu
-rw-r--r--ide-definitions.c63
-rw-r--r--main.c2
-rw-r--r--ted.h4
-rw-r--r--test/lsp/.ted-root0
-rw-r--r--test/lsp/multidef.cpp9
5 files changed, 51 insertions, 27 deletions
diff --git a/ide-definitions.c b/ide-definitions.c
index 185a270..d86e6b3 100644
--- a/ide-definitions.c
+++ b/ide-definitions.c
@@ -97,11 +97,11 @@ void definitions_frame(Ted *ted) {
}
static void definitions_clear_entries(Definitions *defs) {
- arr_foreach_ptr(defs->selector_all_definitions, SymbolInfo, def) {
+ arr_foreach_ptr(defs->all_definitions, SymbolInfo, def) {
free(def->name);
free(def->detail);
}
- arr_clear(defs->selector_all_definitions);
+ arr_clear(defs->all_definitions);
arr_clear(defs->selector.entries);
defs->selector.n_entries = 0;
}
@@ -131,14 +131,22 @@ static void definitions_selector_filter_entries(Ted *ted) {
char *search_term = str32_to_utf8_cstr(buffer_get_line(&ted->line_buffer, 0));
arr_clear(sel->entries);
-
- arr_foreach_ptr(defs->selector_all_definitions, SymbolInfo, info) {
+
+ for (u32 i = 0; i < arr_len(defs->all_definitions); ++i) {
+ SymbolInfo *info = &defs->all_definitions[i];
if (!search_term || strstr_case_insensitive(info->name, search_term)) {
SelectorEntry *entry = arr_addp(sel->entries);
entry->name = info->name;
entry->color = info->color;
entry->detail = info->detail;
+ // this isn't exactly ideal but we're sorting these entries so
+ // it's probably the nicest way of keeping track of the definition
+ // this corresponds to
+ entry->userdata = i;
}
+ // don't try to display too many entries
+ if (arr_len(sel->entries) >= 1000)
+ break;
}
free(search_term);
@@ -187,10 +195,10 @@ void definitions_process_lsp_response(Ted *ted, LSP *lsp, const LSPResponse *res
const u32 *colors = settings->colors;
definitions_clear_entries(defs);
- arr_set_len(defs->selector_all_definitions, arr_len(symbols));
+ arr_set_len(defs->all_definitions, arr_len(symbols));
for (size_t i = 0; i < arr_len(symbols); ++i) {
const LSPSymbolInformation *symbol = &symbols[i];
- SymbolInfo *def = &defs->selector_all_definitions[i];
+ SymbolInfo *def = &defs->all_definitions[i];
def->name = str_dup(lsp_response_string(response, symbol->name));
SymbolKind kind = symbol_kind_to_ted(symbol->kind);
@@ -241,7 +249,7 @@ void definitions_selector_open(Ted *ted) {
if (lsp) {
definitions_send_request_if_needed(ted);
} else {
- defs->selector_all_definitions = tags_get_symbols(ted);
+ defs->all_definitions = tags_get_symbols(ted);
}
ted_switch_to_buffer(ted, &ted->line_buffer);
buffer_select_all(ted->active_buffer);
@@ -271,24 +279,31 @@ void definitions_selector_update(Ted *ted) {
char *chosen = selector_update(ted, sel);
if (chosen) {
- arr_foreach_ptr(defs->selector_all_definitions, SymbolInfo, info) {
- if (strcmp(info->name, chosen) == 0) {
- if (info->from_lsp) {
- // NOTE: we need to get this before calling menu_close,
- // since that clears selector_all_definitions
- LSPDocumentPosition position = info->position;
-
- menu_close(ted);
- ted_go_to_lsp_document_position(ted, NULL, position);
- } else {
- menu_close(ted);
- tag_goto(ted, chosen);
- }
- break;
- }
+ free(chosen), chosen = NULL;
+ // we ignore `chosen` and use the cursor instead.
+ // this is because a single symbol can have multiple definitions,
+ // e.g. with overloading.
+ if (sel->cursor >= sel->n_entries) {
+ assert(0);
+ return;
+ }
+ u64 def_idx = sel->entries[sel->cursor].userdata;
+ if (def_idx >= arr_len(defs->all_definitions)) {
+ assert(0);
+ return;
+ }
+ SymbolInfo *info = &defs->all_definitions[def_idx];
+ if (info->from_lsp) {
+ // NOTE: we need to get this before calling menu_close,
+ // since that clears selector_all_definitions
+ LSPDocumentPosition position = info->position;
+
+ menu_close(ted);
+ ted_go_to_lsp_document_position(ted, NULL, position);
+ } else {
+ menu_close(ted);
+ tag_goto(ted, chosen);
}
-
- free(chosen);
}
}
diff --git a/main.c b/main.c
index 34f85da..a130706 100644
--- a/main.c
+++ b/main.c
@@ -1,8 +1,6 @@
/*
@TODO:
- ted.h documentation
-- handle multiple symbols with same name in go-to-definition menu
-- better non-error window/showMessage(Request)
- document lsp.h and lsp.c.
- check LSP process status (TEST: what happens if LSP server is not installed)
- make tags_dir the root folder
diff --git a/ted.h b/ted.h
index 6fb6754..98b78d6 100644
--- a/ted.h
+++ b/ted.h
@@ -300,6 +300,8 @@ typedef struct {
// if not NULL, this will show on the right side of the entry.
const char *detail;
u32 color;
+ // use this for whatever you want
+ u64 userdata;
} SelectorEntry;
typedef struct {
@@ -482,7 +484,7 @@ typedef struct {
char *last_request_query; // last query string which we sent a request for
Selector selector; // for "go to definition of..." menu
- SymbolInfo *selector_all_definitions; // an array of all definitions
+ SymbolInfo *all_definitions; // an array of all definitions (gotten from workspace/symbols) for "go to definition" menu
} Definitions;
typedef struct {
diff --git a/test/lsp/.ted-root b/test/lsp/.ted-root
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/lsp/.ted-root
diff --git a/test/lsp/multidef.cpp b/test/lsp/multidef.cpp
index eb5336d..6cd5e1a 100644
--- a/test/lsp/multidef.cpp
+++ b/test/lsp/multidef.cpp
@@ -5,3 +5,12 @@ void f(int x, int y) {
void f(int x) {
}
+
+void f(const char *s) {
+}
+
+
+void g() {
+}
+void g(int y) {
+}