Skip to content

Commit

Permalink
Update (non-scope) autocompletion to take into account local variables
Browse files Browse the repository at this point in the history
We have to ignore local variables that:
1. Are from a different file
2. Are declared later in the file than where the current cursor is
3. Have different scope than the current function scope
  • Loading branch information
techee authored and kugel- committed Aug 27, 2022
1 parent d5cc1d0 commit 9e4ef22
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 14 deletions.
11 changes: 9 additions & 2 deletions src/editor.c
Expand Up @@ -2019,12 +2019,19 @@ gboolean editor_show_calltip(GeanyEditor *editor, gint pos)
static gboolean
autocomplete_tags(GeanyEditor *editor, GeanyFiletype *ft, const gchar *root, gsize rootlen)
{
GeanyDocument *doc = editor->document;
const gchar *current_scope = NULL;
guint current_line;
GPtrArray *tags;
gboolean found;

g_return_val_if_fail(editor, FALSE);
g_return_val_if_fail(editor && doc, FALSE);

symbols_get_current_function(doc, &current_scope);
current_line = sci_get_current_line(editor->sci) + 1;

tags = tm_workspace_find_prefix(root, ft->lang, editor_prefs.autocompletion_max_entries);
tags = tm_workspace_find_prefix(root, doc->tm_file, current_line, current_scope,
ft->lang, editor_prefs.autocompletion_max_entries);
found = tags->len > 0;
if (found)
show_tags_list(editor, tags, rootlen);
Expand Down
49 changes: 38 additions & 11 deletions src/tagmanager/tm_workspace.c
Expand Up @@ -684,8 +684,25 @@ GPtrArray *tm_workspace_find(const char *name, const char *scope, TMTagType type
}


static gboolean is_valid_autocomplete_tag(TMTag *tag,
TMSourceFile *current_file,
guint current_line,
const gchar *current_scope)
{
/* ignore local variables from other files/functions or after current line */
return !(tag->type & tm_tag_local_var_t) ||
(current_file == tag->file &&
current_line >= tag->line &&
g_strcmp0(current_scope, tag->scope) == 0);
}


static void fill_find_tags_array_prefix(GPtrArray *dst, const GPtrArray *src,
const char *name, TMParserType lang, guint max_num)
const char *name,
TMSourceFile *current_file,
guint current_line,
const gchar *current_scope,
TMParserType lang, guint max_num)
{
TMTag **tag, *last = NULL;
guint i, count, num;
Expand All @@ -697,34 +714,44 @@ static void fill_find_tags_array_prefix(GPtrArray *dst, const GPtrArray *src,
tag = tm_tags_find(src, name, TRUE, &count);
for (i = 0; i < count && num < max_num; ++i)
{
if (tm_parser_langs_compatible(lang, (*tag)->lang) &&
!tm_tag_is_anon(*tag) &&
(!last || g_strcmp0(last->name, (*tag)->name) != 0))
if (is_valid_autocomplete_tag(*tag, current_file, current_line, current_scope))
{
g_ptr_array_add(dst, *tag);
last = *tag;
num++;
if (tm_parser_langs_compatible(lang, (*tag)->lang) &&
!tm_tag_is_anon(*tag) &&
(!last || g_strcmp0(last->name, (*tag)->name) != 0))
{
g_ptr_array_add(dst, *tag);
last = *tag;
num++;
}
}
tag++;
}
}


/* Returns tags with the specified prefix sorted by name. If there are several
/* Returns tags with the specified prefix sorted by name, ignoring local
variables from other files/functions or after current line. If there are several
tags with the same name, only one of them appears in the resulting array.
@param prefix The prefix of the tag to find.
@param lang Specifies the language(see the table in tm_parsers.h) of the tags to be found,
-1 for all.
@param max_num The maximum number of tags to return.
@return Array of matching tags sorted by their name.
*/
GPtrArray *tm_workspace_find_prefix(const char *prefix, TMParserType lang, guint max_num)
GPtrArray *tm_workspace_find_prefix(const char *prefix,
TMSourceFile *current_file,
guint current_line,
const gchar *current_scope,
TMParserType lang, guint max_num)
{
TMTagAttrType attrs[] = { tm_tag_attr_name_t, 0 };
GPtrArray *tags = g_ptr_array_new();

fill_find_tags_array_prefix(tags, theWorkspace->tags_array, prefix, lang, max_num);
fill_find_tags_array_prefix(tags, theWorkspace->global_tags, prefix, lang, max_num);
fill_find_tags_array_prefix(tags, theWorkspace->tags_array, prefix,
current_file, current_line, current_scope, lang, max_num);
fill_find_tags_array_prefix(tags, theWorkspace->global_tags, prefix,
current_file, current_line, current_scope, lang, max_num);

tm_tags_sort(tags, attrs, TRUE, FALSE);
if (tags->len > max_num)
Expand Down
4 changes: 3 additions & 1 deletion src/tagmanager/tm_workspace.h
Expand Up @@ -56,7 +56,9 @@ gboolean tm_workspace_create_global_tags(const char *pre_process, const char **i
GPtrArray *tm_workspace_find(const char *name, const char *scope, TMTagType type,
TMTagAttrType *attrs, TMParserType lang);

GPtrArray *tm_workspace_find_prefix(const char *prefix, TMParserType lang, guint max_num);
GPtrArray *tm_workspace_find_prefix(const char *prefix,
TMSourceFile *current_file, guint current_line, const gchar *current_scope,
TMParserType lang, guint max_num);

GPtrArray *tm_workspace_find_scope_members (TMSourceFile *source_file, const char *name,
gboolean function, gboolean member, const gchar *current_scope, gboolean search_namespace);
Expand Down

0 comments on commit 9e4ef22

Please sign in to comment.