From 65f84df5cae544deaf3a4ca56c7f29d8e13329d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Techet?= Date: Fri, 11 Mar 2016 11:29:50 +0100 Subject: [PATCH 1/3] Improve Goto Symbol popup contents * always filter-out symbol from the current line from the list * when clicked on a symbol on the current line always swap definition/declaration search even if there are more symbols from the current search direction Fixes #950 --- src/symbols.c | 130 +++++++++++++++++++++++++++----------------------- 1 file changed, 71 insertions(+), 59 deletions(-) diff --git a/src/symbols.c b/src/symbols.c index 77e2dcc025..3a170265e7 100644 --- a/src/symbols.c +++ b/src/symbols.c @@ -2071,102 +2071,114 @@ static TMTag *find_best_goto_tag(GeanyDocument *doc, GPtrArray *tags) } +static GPtrArray *filter_tags(GPtrArray *tags, TMTag *current_tag, gboolean definition) +{ + const TMTagType forward_types = tm_tag_prototype_t | tm_tag_externvar_t; + TMTag *tmtag, *last_tag = NULL; + GPtrArray *filtered_tags = g_ptr_array_new(); + guint i; + + foreach_ptr_array(tmtag, i, tags) + { + if (definition && !(tmtag->type & forward_types) || + !definition && (tmtag->type & forward_types)) + { + /* If there are typedefs of e.g. a struct such as + * "typedef struct Foo {} Foo;", filter out the typedef unless + * cursor is at the struct name. */ + if (last_tag != NULL && last_tag->file == tmtag->file && + last_tag->type != tm_tag_typedef_t && tmtag->type == tm_tag_typedef_t) + { + if (last_tag == current_tag) + g_ptr_array_add(filtered_tags, tmtag); + } + else if (tmtag != current_tag) + g_ptr_array_add(filtered_tags, tmtag); + + last_tag = tmtag; + } + } + + return filtered_tags; +} + + static gboolean goto_tag(const gchar *name, gboolean definition) { const TMTagType forward_types = tm_tag_prototype_t | tm_tag_externvar_t; - TMTagType type; - TMTag *tmtag, *last_tag; + TMTag *tmtag, *current_tag = NULL; GeanyDocument *old_doc = document_get_current(); gboolean found = FALSE; const GPtrArray *all_tags; - GPtrArray *workspace_tags, *filtered_tags; + GPtrArray *tags, *filtered_tags; guint i; guint current_line = sci_get_current_line(old_doc->editor->sci) + 1; - /* goto tag definition: all except prototypes / forward declarations / externs */ - type = (definition) ? tm_tag_max_t - forward_types : forward_types; - all_tags = tm_workspace_find(name, NULL, type, NULL, old_doc->file_type->lang); + all_tags = tm_workspace_find(name, NULL, tm_tag_max_t, NULL, old_doc->file_type->lang); - /* get rid of global tags */ - workspace_tags = g_ptr_array_new(); + /* get rid of global tags and find tag at current line */ + tags = g_ptr_array_new(); foreach_ptr_array(tmtag, i, all_tags) { if (tmtag->file) - g_ptr_array_add(workspace_tags, tmtag); - } - - /* If there are typedefs of e.g. a struct such as "typedef struct Foo {} Foo;", - * keep just one of the names in the list - when the cursor is on the struct - * name, keep the typename, otherwise keep the struct name. */ - last_tag = NULL; - filtered_tags = g_ptr_array_new(); - foreach_ptr_array(tmtag, i, workspace_tags) - { - if (last_tag != NULL && last_tag->file == tmtag->file && - last_tag->type != tm_tag_typedef_t && tmtag->type == tm_tag_typedef_t) { - if (last_tag->line == current_line && filtered_tags->len > 0) - /* if cursor on struct, replace struct with the typedef */ - filtered_tags->pdata[filtered_tags->len-1] = tmtag; - /* if cursor anywhere else, use struct (already added) and discard typedef */ + g_ptr_array_add(tags, tmtag); + if (tmtag->file == old_doc->tm_file && tmtag->line == current_line) + current_tag = tmtag; } - else - g_ptr_array_add(filtered_tags, tmtag); + } + + if (current_tag) + /* swap definition/declaration search */ + definition = current_tag->type & forward_types; - last_tag = tmtag; + filtered_tags = filter_tags(tags, current_tag, definition); + if (current_tag && filtered_tags->len == 0) + { + /* if we previously swapped definition/declaration search and didn't + * find anything, try again with the opposite type */ + g_ptr_array_free(filtered_tags, TRUE); + filtered_tags = filter_tags(tags, current_tag, !definition); } - g_ptr_array_free(workspace_tags, TRUE); - workspace_tags = filtered_tags; + g_ptr_array_free(tags, TRUE); + tags = filtered_tags; - if (workspace_tags->len == 1) + if (tags->len == 1) { GeanyDocument *new_doc; - tmtag = workspace_tags->pdata[0]; - new_doc = document_find_by_real_path( - tmtag->file->file_name); + tmtag = tags->pdata[0]; + new_doc = document_find_by_real_path(tmtag->file->file_name); - if (new_doc) - { - /* If we are already on the tag line, swap definition/declaration */ - if (new_doc == old_doc && tmtag->line == current_line) - { - if (goto_tag(name, !definition)) - found = TRUE; - } - } - else - { + if (!new_doc) /* not found in opened document, should open */ new_doc = document_open_file(tmtag->file->file_name, FALSE, NULL, NULL); - } - if (!found && navqueue_goto_line(old_doc, new_doc, tmtag->line)) - found = TRUE; + navqueue_goto_line(old_doc, new_doc, tmtag->line); } - else if (workspace_tags->len > 1) + else if (tags->len > 1) { - GPtrArray *tags; + GPtrArray *tag_list; TMTag *tag, *best_tag; - g_ptr_array_sort(workspace_tags, compare_tags_by_name_line); - best_tag = find_best_goto_tag(old_doc, workspace_tags); + g_ptr_array_sort(tags, compare_tags_by_name_line); + best_tag = find_best_goto_tag(old_doc, tags); - tags = g_ptr_array_new(); + tag_list = g_ptr_array_new(); if (best_tag) - g_ptr_array_add(tags, best_tag); - foreach_ptr_array(tag, i, workspace_tags) + g_ptr_array_add(tag_list, best_tag); + foreach_ptr_array(tag, i, tags) { if (tag != best_tag) - g_ptr_array_add(tags, tag); + g_ptr_array_add(tag_list, tag); } - show_goto_popup(old_doc, tags, best_tag != NULL); + show_goto_popup(old_doc, tag_list, best_tag != NULL); - g_ptr_array_free(tags, TRUE); - found = TRUE; + g_ptr_array_free(tag_list, TRUE); } - g_ptr_array_free(workspace_tags, TRUE); + found = tags->len > 0; + g_ptr_array_free(tags, TRUE); return found; } From ca8ef9643e7ca347a03875798fa1bbd122e9c917 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Techet?= Date: Thu, 9 Jun 2016 09:41:09 +0200 Subject: [PATCH 2/3] Add parentheses in an if to make the condition more clear --- src/symbols.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/symbols.c b/src/symbols.c index 3a170265e7..16a17b060f 100644 --- a/src/symbols.c +++ b/src/symbols.c @@ -2080,8 +2080,8 @@ static GPtrArray *filter_tags(GPtrArray *tags, TMTag *current_tag, gboolean defi foreach_ptr_array(tmtag, i, tags) { - if (definition && !(tmtag->type & forward_types) || - !definition && (tmtag->type & forward_types)) + if ((definition && !(tmtag->type & forward_types)) || + (!definition && (tmtag->type & forward_types))) { /* If there are typedefs of e.g. a struct such as * "typedef struct Foo {} Foo;", filter out the typedef unless From 20e368155812e611f2ec991273b05fae914f1c45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Techet?= Date: Thu, 9 Jun 2016 10:01:59 +0200 Subject: [PATCH 3/3] Try harder when definition/declaration was not found Even when we know when should be searching for definition (or declaration), we can keep searching for the opposite type too when we didn't find anything with the "correct" def/decl type. So at least we find "something" of that name. --- src/symbols.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/symbols.c b/src/symbols.c index 16a17b060f..e34930f228 100644 --- a/src/symbols.c +++ b/src/symbols.c @@ -2133,10 +2133,9 @@ static gboolean goto_tag(const gchar *name, gboolean definition) definition = current_tag->type & forward_types; filtered_tags = filter_tags(tags, current_tag, definition); - if (current_tag && filtered_tags->len == 0) + if (filtered_tags->len == 0) { - /* if we previously swapped definition/declaration search and didn't - * find anything, try again with the opposite type */ + /* if we didn't find anything, try again with the opposite type */ g_ptr_array_free(filtered_tags, TRUE); filtered_tags = filter_tags(tags, current_tag, !definition); }