Add scope completion for namespaces
Pop up scope completion dialog for namespaces too; e.g. for boost:: show all symbols defined in the namespace. Determine whether the namespace scope completion should be used based on whether user typed a scope separator. If so, perform completion for namespaces before normal scope completion - this seems to work better e.g. for Scintilla where Scintilla:: would otherwise pop up the varible sci instead of showing everything in the namespace (might be more questionable for languages where the scope separator is identical to the dereference operator like Java's "." but we have to make some choice anyway). The performance seems to be reasonable - for the completion all tags have to be walked but after testing with big C++ projects like boost and Mozilla, the completion takes only something like 0.2s which is acceptable as the delay happens only on typing the scope completion separator and feels kind of expected. Also tested with linux kernel sources which normally lack any scope information by hacking TM a bit and injecting 10-character scope for each tag - then the completion takes something over 0.5s.
This commit is contained in:
parent
725083ffe7
commit
77f6e98de8
12
src/editor.c
12
src/editor.c
@ -711,6 +711,7 @@ static gboolean autocomplete_scope(GeanyEditor *editor, const gchar *root, gsize
|
|||||||
GPtrArray *tags;
|
GPtrArray *tags;
|
||||||
gboolean function = FALSE;
|
gboolean function = FALSE;
|
||||||
gboolean member;
|
gboolean member;
|
||||||
|
gboolean scope_sep_typed = FALSE;
|
||||||
gboolean ret = FALSE;
|
gboolean ret = FALSE;
|
||||||
const gchar *current_scope;
|
const gchar *current_scope;
|
||||||
const gchar *context_sep = tm_tag_context_separator(ft->lang);
|
const gchar *context_sep = tm_tag_context_separator(ft->lang);
|
||||||
@ -729,10 +730,13 @@ static gboolean autocomplete_scope(GeanyEditor *editor, const gchar *root, gsize
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* make sure to keep in sync with similar checks below */
|
/* make sure to keep in sync with similar checks below */
|
||||||
if (typed == '.')
|
if (match_last_chars(sci, pos, context_sep))
|
||||||
pos -= 1;
|
{
|
||||||
else if (match_last_chars(sci, pos, context_sep))
|
|
||||||
pos -= strlen(context_sep);
|
pos -= strlen(context_sep);
|
||||||
|
scope_sep_typed = TRUE;
|
||||||
|
}
|
||||||
|
else if (typed == '.')
|
||||||
|
pos -= 1;
|
||||||
else if ((ft->id == GEANY_FILETYPES_C || ft->id == GEANY_FILETYPES_CPP) &&
|
else if ((ft->id == GEANY_FILETYPES_C || ft->id == GEANY_FILETYPES_CPP) &&
|
||||||
match_last_chars(sci, pos, "->"))
|
match_last_chars(sci, pos, "->"))
|
||||||
pos -= 2;
|
pos -= 2;
|
||||||
@ -777,7 +781,7 @@ static gboolean autocomplete_scope(GeanyEditor *editor, const gchar *root, gsize
|
|||||||
if (symbols_get_current_scope(editor->document, ¤t_scope) == -1)
|
if (symbols_get_current_scope(editor->document, ¤t_scope) == -1)
|
||||||
current_scope = "";
|
current_scope = "";
|
||||||
tags = tm_workspace_find_scope_members(editor->document->tm_file, name, function,
|
tags = tm_workspace_find_scope_members(editor->document->tm_file, name, function,
|
||||||
member, current_scope);
|
member, current_scope, scope_sep_typed);
|
||||||
if (tags)
|
if (tags)
|
||||||
{
|
{
|
||||||
GPtrArray *filtered = g_ptr_array_new();
|
GPtrArray *filtered = g_ptr_array_new();
|
||||||
|
@ -1039,6 +1039,22 @@ find_scope_members_all(const GPtrArray *tags, const GPtrArray *searched_array, l
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static GPtrArray *find_namespace_members_all(const GPtrArray *tags, const GPtrArray *searched_array, langType lang)
|
||||||
|
{
|
||||||
|
GPtrArray *member_tags = NULL;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
for (i = 0; i < tags->len && !member_tags; i++)
|
||||||
|
{
|
||||||
|
TMTag *tag = TM_TAG(tags->pdata[i]);
|
||||||
|
|
||||||
|
member_tags = find_scope_members_tags(searched_array, tag, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return member_tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Returns all member tags of a struct/union/class if the provided name is a variable
|
/* Returns all member tags of a struct/union/class if the provided name is a variable
|
||||||
of such a type or the name of the type.
|
of such a type or the name of the type.
|
||||||
@param source_file TMSourceFile of the edited source file or NULL if not available
|
@param source_file TMSourceFile of the edited source file or NULL if not available
|
||||||
@ -1046,10 +1062,11 @@ find_scope_members_all(const GPtrArray *tags, const GPtrArray *searched_array, l
|
|||||||
@param function TRUE if the name is a name of a function
|
@param function TRUE if the name is a name of a function
|
||||||
@param member TRUE if invoked on class/struct member (e.g. after the last dot in foo.bar.)
|
@param member TRUE if invoked on class/struct member (e.g. after the last dot in foo.bar.)
|
||||||
@param current_scope The current scope in the editor
|
@param current_scope The current scope in the editor
|
||||||
|
@param search_namespace Whether to search the contents of namespace (e.g. after MyNamespace::)
|
||||||
@return A GPtrArray of TMTag pointers to struct/union/class members or NULL when not found */
|
@return A GPtrArray of TMTag pointers to struct/union/class members or NULL when not found */
|
||||||
GPtrArray *
|
GPtrArray *
|
||||||
tm_workspace_find_scope_members (TMSourceFile *source_file, const char *name,
|
tm_workspace_find_scope_members (TMSourceFile *source_file, const char *name,
|
||||||
gboolean function, gboolean member, const gchar *current_scope)
|
gboolean function, gboolean member, const gchar *current_scope, gboolean search_namespace)
|
||||||
{
|
{
|
||||||
langType lang = source_file ? source_file->lang : -1;
|
langType lang = source_file ? source_file->lang : -1;
|
||||||
GPtrArray *tags, *member_tags = NULL;
|
GPtrArray *tags, *member_tags = NULL;
|
||||||
@ -1059,6 +1076,19 @@ tm_workspace_find_scope_members (TMSourceFile *source_file, const char *name,
|
|||||||
~(function_types | tm_tag_enumerator_t | tm_tag_namespace_t | tm_tag_package_t);
|
~(function_types | tm_tag_enumerator_t | tm_tag_namespace_t | tm_tag_package_t);
|
||||||
TMTagAttrType sort_attr[] = {tm_tag_attr_name_t, 0};
|
TMTagAttrType sort_attr[] = {tm_tag_attr_name_t, 0};
|
||||||
|
|
||||||
|
if (search_namespace)
|
||||||
|
{
|
||||||
|
tags = tm_workspace_find(name, NULL, tm_tag_namespace_t, NULL, lang);
|
||||||
|
|
||||||
|
member_tags = find_namespace_members_all(tags, theWorkspace->tags_array, lang);
|
||||||
|
if (!member_tags)
|
||||||
|
member_tags = find_namespace_members_all(tags, theWorkspace->global_tags, lang);
|
||||||
|
|
||||||
|
g_ptr_array_free(tags, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!member_tags)
|
||||||
|
{
|
||||||
if (function)
|
if (function)
|
||||||
tag_type = function_types;
|
tag_type = function_types;
|
||||||
|
|
||||||
@ -1079,6 +1109,7 @@ tm_workspace_find_scope_members (TMSourceFile *source_file, const char *name,
|
|||||||
member, current_scope);
|
member, current_scope);
|
||||||
|
|
||||||
g_ptr_array_free(tags, TRUE);
|
g_ptr_array_free(tags, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
tm_tags_dedup(member_tags, sort_attr, FALSE);
|
tm_tags_dedup(member_tags, sort_attr, FALSE);
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ GPtrArray *tm_workspace_find(const char *name, const char *scope, TMTagType type
|
|||||||
GPtrArray *tm_workspace_find_prefix(const char *prefix, langType lang, guint max_num);
|
GPtrArray *tm_workspace_find_prefix(const char *prefix, langType lang, guint max_num);
|
||||||
|
|
||||||
GPtrArray *tm_workspace_find_scope_members (TMSourceFile *source_file, const char *name,
|
GPtrArray *tm_workspace_find_scope_members (TMSourceFile *source_file, const char *name,
|
||||||
gboolean function, gboolean member, const gchar *current_scope);
|
gboolean function, gboolean member, const gchar *current_scope, gboolean search_namespace);
|
||||||
|
|
||||||
|
|
||||||
void tm_workspace_add_source_file_noupdate(TMSourceFile *source_file);
|
void tm_workspace_add_source_file_noupdate(TMSourceFile *source_file);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user