Branch: refs/heads/master Author: Jiří Techet techet@gmail.com Committer: Thomas Martitz thomas.martitz@mailbox.org Date: Sat, 27 Aug 2022 22:44:50 UTC Commit: 2a5da2225f7aa87bdc7f82c3966f6fb32754ae5c https://github.com/geany/geany/commit/2a5da2225f7aa87bdc7f82c3966f6fb32754ae...
Log Message: ----------- Rewrite member_at_method_scope() to handle more situations
When performing scope completion for
void A::foo() { bar. // <-- }
we need to determine what 'bar' is. It could be a global variable, in which case we should look for variable tags, it could however also be a member of A in which case we should look for member tags.
To determine this, the previous code checked whether there's a tag named 'bar' with the same scope as the method tag. One drawback of this approach is that it doesn't take namespace manipulation functions like 'using namespace' into account so for header
namespace X { class A { Baz bar; }; };
and source
using namespace X;
void A::foo() { bar. // <-- }
it wouldn't find 'bar' because ctags reports foo() to have scope A and bar to have scope X::A.
Another drawback of this approach is that it doesn't take inheritance into account so it wouldn't find 'bar' when defined in a super-class, such as
class B { Baz bar; };
class A : B { void foo(); }
To avoid these problems, this patch rewrites member_at_method_scope() (and renames it to member_accessible()) so it gets the class name from the scope of the method in which we are (A in the above example) and returns all members of A (including the super-classes members). Afterwards, it checks if one of the members is really the member tag we are interested in ('bar' in the above example).
Modified Paths: -------------- src/tagmanager/tm_workspace.c
Modified: src/tagmanager/tm_workspace.c 54 lines changed, 25 insertions(+), 29 deletions(-) =================================================================== @@ -1047,8 +1047,8 @@ find_scope_members (const GPtrArray *tags_array, const gchar *name, TMSourceFile }
-/* Checks whether a member tag is directly accessible from method with method_scope */ -static gboolean member_at_method_scope(const GPtrArray *tags, const gchar *method_scope, TMTag *member_tag, +/* Checks whether a member tag is directly accessible from method */ +static gboolean member_accessible(const GPtrArray *tags, const gchar *method_scope, TMTag *member_tag, TMParserType lang) { const gchar *sep = tm_parser_scope_separator(lang); @@ -1061,35 +1061,31 @@ static gboolean member_at_method_scope(const GPtrArray *tags, const gchar *metho len = g_strv_length(comps); if (len > 1) { - gchar *method, *member_scope, *cls, *cls_scope; - - /* get method/member scope */ - method = comps[len - 1]; - comps[len - 1] = NULL; - member_scope = g_strjoinv(sep, comps); - comps[len - 1] = method; - - /* get class scope */ - cls = comps[len - 2]; - comps[len - 2] = NULL; - cls_scope = g_strjoinv(sep, comps); - comps[len - 2] = cls; - cls_scope = strlen(cls_scope) > 0 ? cls_scope : NULL; - - /* check whether member inside the class */ - if (g_strcmp0(member_tag->scope, member_scope) == 0) + gchar *cls = comps[len - 2]; + + if (*cls) { - const GPtrArray *src = member_tag->file ? member_tag->file->tags_array : tags; - GPtrArray *cls_tags = g_ptr_array_new(); + /* find method's class members */ + GPtrArray *cls_tags = find_scope_members(tags, cls, NULL, lang, FALSE);
- /* check whether the class exists */ - fill_find_tags_array(cls_tags, src, cls, cls_scope, TM_TYPE_WITH_MEMBERS | tm_tag_namespace_t, lang); - ret = cls_tags->len > 0; - g_ptr_array_free(cls_tags, TRUE); - } + if (cls_tags) + { + guint i; + + /* check if one of the class members is member_tag */ + for (i = 0; i < cls_tags->len; i++) + { + TMTag *t = cls_tags->pdata[i];
- g_free(cls_scope); - g_free(member_scope); + if (t == member_tag) + { + ret = TRUE; + break; + } + } + g_ptr_array_free(cls_tags, TRUE); + } + } }
g_strfreev(comps); @@ -1129,7 +1125,7 @@ find_scope_members_all(const GPtrArray *tags, const GPtrArray *searched_array, T * inside a method where foo is a class member, we want scope completion * for foo. */ if (!(tag->type & member_types) || member || - member_at_method_scope(tags, current_scope, tag, lang)) + member_accessible(searched_array, current_scope, tag, lang)) { gchar *tag_type = strip_type(tag->var_type, tag->lang, TRUE);
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).