From 9cfd7ebbf9b6f61abc874f105b926831cd55d3a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Techet?= Date: Wed, 29 May 2019 03:36:30 -0700 Subject: [PATCH 1/6] Rename pointerOrder TMtag member to flags We now use varType instead of pointerOrder and it has been the case for quite and we can use the pointerOrder field for storing something useful. When we store something else inside the renamed pointerOrder, we will break compatibility with some very old tag files but I don't think there are any such files around (also pointerOrder was probably just reported by the C parser). Bump API for the pointerOrder change to flags --- src/plugindata.h | 2 +- src/tagmanager/tm_ctags.c | 2 +- src/tagmanager/tm_source_file.c | 12 ++++++------ src/tagmanager/tm_tag.c | 2 +- src/tagmanager/tm_tag.h | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/plugindata.h b/src/plugindata.h index 107a0bc4f5..bd426d38ee 100644 --- a/src/plugindata.h +++ b/src/plugindata.h @@ -58,7 +58,7 @@ G_BEGIN_DECLS * @warning You should not test for values below 200 as previously * @c GEANY_API_VERSION was defined as an enum value, not a macro. */ -#define GEANY_API_VERSION 242 +#define GEANY_API_VERSION 243 /* hack to have a different ABI when built with different GTK major versions * because loading plugins linked to a different one leads to crashes. diff --git a/src/tagmanager/tm_ctags.c b/src/tagmanager/tm_ctags.c index b2b1e227f8..e0892cb93d 100644 --- a/src/tagmanager/tm_ctags.c +++ b/src/tagmanager/tm_ctags.c @@ -120,7 +120,7 @@ static gboolean init_tag(TMTag *tag, TMSourceFile *file, const tagEntryInfo *tag tag->name = g_strdup(tag_entry->name); tag->type = type; tag->local = tag_entry->isFileScope; - tag->pointerOrder = 0; /* backward compatibility (use var_type instead) */ + tag->flags = 0; tag->line = tag_entry->lineNumber; if (NULL != tag_entry->extensionFields.signature) tag->arglist = g_strdup(tag_entry->extensionFields.signature); diff --git a/src/tagmanager/tm_source_file.c b/src/tagmanager/tm_source_file.c index b1f37f3b4e..329f4fc117 100644 --- a/src/tagmanager/tm_source_file.c +++ b/src/tagmanager/tm_source_file.c @@ -65,7 +65,7 @@ enum TA_IMPL, TA_LANG, TA_INACTIVE, /* Obsolete */ - TA_POINTER + TA_FLAGS }; @@ -219,8 +219,8 @@ static gboolean init_tag_from_file(TMTag *tag, TMSourceFile *file, FILE *fp) case TA_SCOPE: tag->scope = g_strdup((gchar*)start + 1); break; - case TA_POINTER: - tag->pointerOrder = atoi((gchar*)start + 1); + case TA_FLAGS: + tag->flags = atoi((gchar*)start + 1); break; case TA_VARTYPE: tag->var_type = g_strdup((gchar*)start + 1); @@ -463,8 +463,8 @@ static gboolean write_tag(TMTag *tag, FILE *fp, TMTagAttrType attrs) fprintf(fp, "%c%s", TA_SCOPE, tag->scope); if ((attrs & tm_tag_attr_inheritance_t) && (NULL != tag->inheritance)) fprintf(fp, "%c%s", TA_INHERITS, tag->inheritance); - if (attrs & tm_tag_attr_pointer_t) - fprintf(fp, "%c%d", TA_POINTER, tag->pointerOrder); + if (attrs & tm_tag_attr_flags_t) + fprintf(fp, "%c%d", TA_FLAGS, tag->flags); if ((attrs & tm_tag_attr_vartype_t) && (NULL != tag->var_type)) fprintf(fp, "%c%s", TA_VARTYPE, tag->var_type); if ((attrs & tm_tag_attr_access_t) && (TAG_ACCESS_UNKNOWN != tag->access)) @@ -551,7 +551,7 @@ gboolean tm_source_file_write_tags_file(const gchar *tags_file, GPtrArray *tags_ ret = write_tag(tag, fp, tm_tag_attr_type_t | tm_tag_attr_scope_t | tm_tag_attr_arglist_t | tm_tag_attr_vartype_t - | tm_tag_attr_pointer_t); + | tm_tag_attr_flags_t); if (!ret) break; diff --git a/src/tagmanager/tm_tag.c b/src/tagmanager/tm_tag.c index 21c4d3ece2..1c49652ec9 100644 --- a/src/tagmanager/tm_tag.c +++ b/src/tagmanager/tm_tag.c @@ -228,7 +228,7 @@ gboolean tm_tags_equal(const TMTag *a, const TMTag *b) strcmp(FALLBACK(a->name, ""), FALLBACK(b->name, "")) == 0 && a->type == b->type && a->local == b->local && - a->pointerOrder == b->pointerOrder && + a->flags == b->flags && a->access == b->access && a->impl == b->impl && a->lang == b->lang && diff --git a/src/tagmanager/tm_tag.h b/src/tagmanager/tm_tag.h index 4205d37dc7..643b163ac4 100644 --- a/src/tagmanager/tm_tag.h +++ b/src/tagmanager/tm_tag.h @@ -65,7 +65,7 @@ typedef enum tm_tag_attr_impl_t = 4096, /**< Implementation (e.g. virtual) */ tm_tag_attr_lang_t = 8192, /**< Language (File tag only) */ tm_tag_attr_inactive_t = 16384, /**< Inactive file (File tag only, obsolete) */ - tm_tag_attr_pointer_t = 32768, /**< Pointer type */ + tm_tag_attr_flags_t = 32768, /**< Additional flags */ tm_tag_attr_max_t = 65535 /**< Maximum value */ } TMTagAttrType; @@ -94,7 +94,7 @@ typedef struct TMTag TMSourceFile *file; /**< File in which the tag occurs; NULL for global tags */ gulong line; /**< Line number of the tag */ gboolean local; /**< Is the tag of local scope */ - guint pointerOrder; + guint flags; /**< Additional flags */ char *arglist; /**< Argument list (functions/prototypes/macros) */ char *scope; /**< Scope of tag */ char *inheritance; /**< Parent classes */ From 8805f56bbe14b218356c3ce4c2c3e318aecef251 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Techet?= Date: Mon, 6 Dec 2021 22:10:45 +0100 Subject: [PATCH 2/6] Use XTAG_ANONYMOUS in Fortran parser Report anonymous tags using XTAG_ANONYMOUS. These anonymous tags aren't generated by the upstream uctags parser so this change hasn't been made available there (will have to be part of some future sync). --- ctags/parsers/geany_fortran.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ctags/parsers/geany_fortran.c b/ctags/parsers/geany_fortran.c index 79a6180f40..59a9ff50dd 100644 --- a/ctags/parsers/geany_fortran.c +++ b/ctags/parsers/geany_fortran.c @@ -190,6 +190,7 @@ typedef struct sTokenInfo { struct sTokenInfo *secondary; unsigned long lineNumber; MIOPos filePosition; + bool anonymous; } tokenInfo; /* @@ -430,6 +431,7 @@ static tokenInfo *newToken (void) token->secondary = NULL; token->lineNumber = getInputLineNumber (); token->filePosition = getInputFilePosition (); + token->anonymous = false; return token; } @@ -447,6 +449,7 @@ static tokenInfo *newAnonTokenFrom (tokenInfo *const token, const char *type) { char buffer[64]; tokenInfo *result = newTokenFrom (token); + result->anonymous = true; sprintf (buffer, "%s#%u", type, contextual_fake_count++); vStringClear (result->string); vStringCatS (result->string, buffer); @@ -492,6 +495,9 @@ static void makeFortranTag (tokenInfo *const token, tagType tag) if (token->tag == TAG_COMMON_BLOCK) e.lineNumberEntry = canUseLineNumberAsLocator(); + if (token->anonymous) + markTagExtraBit (&e, XTAG_ANONYMOUS); + e.lineNumber = token->lineNumber; e.filePosition = token->filePosition; e.isFileScope = isFileScope (token->tag); From b4afb8e75bda1a648020bdea731316bf0d162b20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Techet?= Date: Wed, 29 May 2019 03:46:43 -0700 Subject: [PATCH 3/6] Add a flag representing anonymous tags The flag is set when XTAG_ANONYMOUS is defined and is used for detecting anonymous tags inside tm_tag_is_anon(). --- src/tagmanager/tm_ctags.c | 4 +++- src/tagmanager/tm_tag.c | 3 +++ src/tagmanager/tm_tag.h | 7 +++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/tagmanager/tm_ctags.c b/src/tagmanager/tm_ctags.c index e0892cb93d..59f55b65f3 100644 --- a/src/tagmanager/tm_ctags.c +++ b/src/tagmanager/tm_ctags.c @@ -120,7 +120,9 @@ static gboolean init_tag(TMTag *tag, TMSourceFile *file, const tagEntryInfo *tag tag->name = g_strdup(tag_entry->name); tag->type = type; tag->local = tag_entry->isFileScope; - tag->flags = 0; + tag->flags = tm_tag_flag_none_t; + if (isTagExtraBitMarked(tag_entry, XTAG_ANONYMOUS)) + tag->flags = tm_tag_flag_anon_t; tag->line = tag_entry->lineNumber; if (NULL != tag_entry->extensionFields.signature) tag->arglist = g_strdup(tag_entry->extensionFields.signature); diff --git a/src/tagmanager/tm_tag.c b/src/tagmanager/tm_tag.c index 1c49652ec9..d4a36bee83 100644 --- a/src/tagmanager/tm_tag.c +++ b/src/tagmanager/tm_tag.c @@ -670,6 +670,9 @@ gboolean tm_tag_is_anon(const TMTag *tag) guint i; char dummy; + if (tag->flags & tm_tag_flag_anon_t) + return TRUE; + if (tag->lang == TM_PARSER_C || tag->lang == TM_PARSER_CPP) return sscanf(tag->name, "__anon%u%c", &i, &dummy) == 1; else if (tag->lang == TM_PARSER_FORTRAN || tag->lang == TM_PARSER_F77) diff --git a/src/tagmanager/tm_tag.h b/src/tagmanager/tm_tag.h index 643b163ac4..533d49af2f 100644 --- a/src/tagmanager/tm_tag.h +++ b/src/tagmanager/tm_tag.h @@ -81,6 +81,13 @@ typedef enum #define TAG_IMPL_VIRTUAL 'v' /**< Virtual implementation */ #define TAG_IMPL_UNKNOWN 'x' /**< Unknown implementation */ +enum +{ + tm_tag_flag_none_t = 0, /**< No flags */ + tm_tag_flag_anon_t = 1, /**< Anonymous tag */ + tm_tag_flag_max_t = 1, /**< Maximum value */ +}; + /** * The TMTag structure represents a single tag in the tag manager. **/ From ea660f8b1fab4c0da5a399db79487e56b59dc7da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Techet?= Date: Sat, 11 Dec 2021 17:00:18 +0100 Subject: [PATCH 4/6] Determine anonymous tags based on name only when necessary At this point all built in parsers should report anonymous tags correctly so for them we don't need to determine anonymous tags based on tag name. Since tag files might be generated without this information, we still have to determine anonymous tags based on name for them. --- src/tagmanager/tm_ctags.c | 2 +- src/tagmanager/tm_parser.c | 21 +++++++++++++++++++++ src/tagmanager/tm_parser.h | 2 ++ src/tagmanager/tm_source_file.c | 13 ++++++++++--- src/tagmanager/tm_tag.c | 15 ++------------- 5 files changed, 36 insertions(+), 17 deletions(-) diff --git a/src/tagmanager/tm_ctags.c b/src/tagmanager/tm_ctags.c index 59f55b65f3..bfce1c0ff3 100644 --- a/src/tagmanager/tm_ctags.c +++ b/src/tagmanager/tm_ctags.c @@ -122,7 +122,7 @@ static gboolean init_tag(TMTag *tag, TMSourceFile *file, const tagEntryInfo *tag tag->local = tag_entry->isFileScope; tag->flags = tm_tag_flag_none_t; if (isTagExtraBitMarked(tag_entry, XTAG_ANONYMOUS)) - tag->flags = tm_tag_flag_anon_t; + tag->flags |= tm_tag_flag_anon_t; tag->line = tag_entry->lineNumber; if (NULL != tag_entry->extensionFields.signature) tag->arglist = g_strdup(tag_entry->extensionFields.signature); diff --git a/src/tagmanager/tm_parser.c b/src/tagmanager/tm_parser.c index f4360f9e79..e4c91fc66e 100644 --- a/src/tagmanager/tm_parser.c +++ b/src/tagmanager/tm_parser.c @@ -862,6 +862,27 @@ const gchar *tm_parser_get_constructor_method(TMParserType lang) } +/* determine anonymous tags from tag names only when corresponding + * ctags information is not available */ +gboolean tm_parser_is_anon_name(TMParserType lang, gchar *name) +{ + guint i; + char dummy; + + if (sscanf(name, "__anon%u%c", &i, &dummy) == 1) /* uctags tags files */ + return TRUE; + else if (lang == TM_PARSER_C || lang == TM_PARSER_CPP) /* legacy Geany tags files */ + return sscanf(name, "anon_%*[a-z]_%u%c", &i, &dummy) == 1; + else if (lang == TM_PARSER_FORTRAN || lang == TM_PARSER_F77) /* legacy Geany tags files */ + { + return sscanf(name, "Structure#%u%c", &i, &dummy) == 1 || + sscanf(name, "Interface#%u%c", &i, &dummy) == 1 || + sscanf(name, "Enum#%u%c", &i, &dummy) == 1; + } + return FALSE; +} + + static gchar *replace_string_if_present(gchar *haystack, gchar *needle, gchar *subst) { if (strstr(haystack, needle)) diff --git a/src/tagmanager/tm_parser.h b/src/tagmanager/tm_parser.h index 27edf34e16..179945976e 100644 --- a/src/tagmanager/tm_parser.h +++ b/src/tagmanager/tm_parser.h @@ -128,6 +128,8 @@ gint tm_parser_scope_autocomplete_suffix(TMParserType lang, const gchar *str); const gchar *tm_parser_get_constructor_method(TMParserType lang); +gboolean tm_parser_is_anon_name(TMParserType lang, gchar *name); + gchar *tm_parser_update_scope(TMParserType lang, gchar *scope); gboolean tm_parser_enable_role(TMParserType lang, gchar kind); diff --git a/src/tagmanager/tm_source_file.c b/src/tagmanager/tm_source_file.c index 329f4fc117..d234b0ca9b 100644 --- a/src/tagmanager/tm_source_file.c +++ b/src/tagmanager/tm_source_file.c @@ -175,7 +175,7 @@ gchar tm_source_file_get_tag_access(const gchar *access) @param fp FILE pointer from where the tag line is read @return TRUE on success, FALSE on FAILURE */ -static gboolean init_tag_from_file(TMTag *tag, TMSourceFile *file, FILE *fp) +static gboolean init_tag_from_file(TMTag *tag, TMSourceFile *file, FILE *fp, TMParserType lang) { guchar buf[BUFSIZ]; guchar *start, *end; @@ -198,7 +198,11 @@ static gboolean init_tag_from_file(TMTag *tag, TMSourceFile *file, FILE *fp) if (!isprint(*start)) return FALSE; else + { tag->name = g_strdup((gchar*)start); + if (tm_parser_is_anon_name(lang, tag->name)) + tag->flags |= tm_tag_flag_anon_t; + } } else { @@ -220,7 +224,7 @@ static gboolean init_tag_from_file(TMTag *tag, TMSourceFile *file, FILE *fp) tag->scope = g_strdup((gchar*)start + 1); break; case TA_FLAGS: - tag->flags = atoi((gchar*)start + 1); + tag->flags |= atoi((gchar*)start + 1); break; case TA_VARTYPE: tag->var_type = g_strdup((gchar*)start + 1); @@ -324,6 +328,9 @@ static gboolean init_tag_from_file_ctags(TMTag *tag, TMSourceFile *file, FILE *f tag->name = g_strndup(p, (gsize)(tab - p)); p = tab + 1; + if (tm_parser_is_anon_name(lang, tag->name)) + tag->flags |= tm_tag_flag_anon_t; + /* tagfile, unused */ if (! (tab = strchr(p, '\t'))) { @@ -422,7 +429,7 @@ static TMTag *new_tag_from_tags_file(TMSourceFile *file, FILE *fp, TMParserType switch (format) { case TM_FILE_FORMAT_TAGMANAGER: - result = init_tag_from_file(tag, file, fp); + result = init_tag_from_file(tag, file, fp, mode); break; case TM_FILE_FORMAT_PIPE: result = init_tag_from_file_alt(tag, file, fp); diff --git a/src/tagmanager/tm_tag.c b/src/tagmanager/tm_tag.c index d4a36bee83..4ffaa28ba4 100644 --- a/src/tagmanager/tm_tag.c +++ b/src/tagmanager/tm_tag.c @@ -665,21 +665,10 @@ tm_get_current_tag (GPtrArray * file_tags, const gulong line, const TMTagType ta return matching_tag; } + gboolean tm_tag_is_anon(const TMTag *tag) { - guint i; - char dummy; - - if (tag->flags & tm_tag_flag_anon_t) - return TRUE; - - if (tag->lang == TM_PARSER_C || tag->lang == TM_PARSER_CPP) - return sscanf(tag->name, "__anon%u%c", &i, &dummy) == 1; - else if (tag->lang == TM_PARSER_FORTRAN || tag->lang == TM_PARSER_F77) - return sscanf(tag->name, "Structure#%u%c", &i, &dummy) == 1 || - sscanf(tag->name, "Interface#%u%c", &i, &dummy) == 1 || - sscanf(tag->name, "Enum#%u%c", &i, &dummy) == 1; - return FALSE; + return tag->flags & tm_tag_flag_anon_t; } From dbd0ebc914d5ac56baef3fe1c28acda9d7ff3e09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Techet?= Date: Mon, 6 Dec 2021 22:35:46 +0100 Subject: [PATCH 5/6] Consistently rename anonymous tags and drop the last ctags diff Check all the collected tags once a file is parsed (i.e. when we have all tags, including those from subparsers) and renamea them in the form anon_enum_1 anon_struct_1 anon_enum_2 anon_struct_2 where the second component is a ctags kind and the number is per-kind. In addition, scopes of the nested tags have to be updated if the parent tag is an anonymous tag. Finally, for anonymous tags of the form typedef struct Foo{int a;}; we can use the name of the typedef instead of generating the anonymous name. In this case we can drop the typedef tag once the anonymous tag is updated with its name. More details can be found in comments. --- ctags/ctags_changes.patch | 24 ------ ctags/main/parse.c | 6 -- scripts/update-ctags.py | 3 - src/tagmanager/tm_ctags.c | 141 ++++++++++++++++++++++++++++++++ src/tagmanager/tm_source_file.c | 5 +- src/tagmanager/tm_tag.h | 1 + 6 files changed, 145 insertions(+), 35 deletions(-) delete mode 100644 ctags/ctags_changes.patch diff --git a/ctags/ctags_changes.patch b/ctags/ctags_changes.patch deleted file mode 100644 index 7f7f882d2c..0000000000 --- a/ctags/ctags_changes.patch +++ /dev/null @@ -1,24 +0,0 @@ -A patch to ctags containing our changes to ctags -(changing anon tag names from anon to anon). -diff --git a/ctags/main/parse.c b/ctags/main/parse.c -index 8fbb7148..c12f8662 100644 ---- ctags/main/parse.c -+++ ctags/main/parse.c -@@ -4111,12 +4111,18 @@ extern void anonGenerate (vString *buffer, const char *prefix, int kind) - parser -> anonymousIdentiferId ++; - - char szNum[32]; -+#if 0 - char buf [9]; - - vStringCopyS(buffer, prefix); - - anonHashString (getInputFileName(), buf); - sprintf(szNum,"%s%02x%02x",buf,parser -> anonymousIdentiferId, kind); -+#else -+ /* we want to see numbers for anon functions in the tree view instead of the hash */ -+ vStringCopyS(buffer, prefix); -+ sprintf(szNum,"%u", parser -> anonymousIdentiferId); -+#endif - vStringCatS(buffer,szNum); - } diff --git a/ctags/main/parse.c b/ctags/main/parse.c index 4b41d3544b..1b1013d16d 100644 --- a/ctags/main/parse.c +++ b/ctags/main/parse.c @@ -4787,18 +4787,12 @@ extern void anonGenerate (vString *buffer, const char *prefix, int kind) parser -> anonymousIdentiferId ++; char szNum[32]; -#if 0 char buf [9]; vStringCopyS(buffer, prefix); anonHashString (getInputFileName(), buf); sprintf(szNum,"%s%02x%02x",buf,parser -> anonymousIdentiferId, kind); -#else - /* we want to see numbers for anon functions in the tree view instead of the hash */ - vStringCopyS(buffer, prefix); - sprintf(szNum,"%u", parser -> anonymousIdentiferId); -#endif vStringCatS(buffer,szNum); } diff --git a/scripts/update-ctags.py b/scripts/update-ctags.py index a575dc59c5..9dac9efb29 100755 --- a/scripts/update-ctags.py +++ b/scripts/update-ctags.py @@ -51,6 +51,3 @@ main_diff = set(main_src_files) - set(main_dst_files) if main_diff: print('Files added to main: ' + str(main_diff)) - -os.chdir(dstdir) -os.system('patch -p1 flags = tm_tag_flag_none_t; if (isTagExtraBitMarked(tag_entry, XTAG_ANONYMOUS)) tag->flags |= tm_tag_flag_anon_t; + tag->kind_letter = kind_letter; tag->line = tag_entry->lineNumber; if (NULL != tag_entry->extensionFields.signature) tag->arglist = g_strdup(tag_entry->extensionFields.signature); @@ -240,12 +241,152 @@ void tm_ctags_clear_ignore_symbols(void) } +/* call after all tags have been collected so we don't have to handle reparses + * with the counter (which gets complicated when also subparsers are involved) */ +static void rename_anon_tags(TMSourceFile *source_file) +{ + gint *anon_counter_table = NULL; + GPtrArray *removed_typedefs = NULL; + guint i; + + for (i = 0; i < source_file->tags_array->len; i++) + { + TMTag *tag = TM_TAG(source_file->tags_array->pdata[i]); + if (tm_tag_is_anon(tag)) + { + gchar *orig_name, *new_name = NULL; + guint j; + guint new_name_len, orig_name_len; + guint scope_len = tag->scope ? strlen(tag->scope) : 0; + gchar kind = tag->kind_letter; + + orig_name = tag->name; + orig_name_len = strlen(orig_name); + + if (source_file->lang == TM_PARSER_C || source_file->lang == TM_PARSER_CPP) + { + /* First check if there's a typedef behind the scope nesting + * such as typedef struct {} Foo; - in this case we can replace + * the anon tag with Foo */ + for (j = i + 1; j < source_file->tags_array->len; j++) + { + TMTag *nested_tag = TM_TAG(source_file->tags_array->pdata[j]); + guint nested_scope_len = nested_tag->scope ? strlen(nested_tag->scope) : 0; + + /* Nested tags have longer scope than the parent - once the scope + * is equal or lower than the parent scope, we are outside the tag's + * scope. */ + if (nested_scope_len <= scope_len) + break; + } + + /* We are out of the nesting - the next tag could be a typedef */ + if (j < source_file->tags_array->len) + { + TMTag *typedef_tag = TM_TAG(source_file->tags_array->pdata[j]); + guint typedef_scope_len = typedef_tag->scope ? strlen(typedef_tag->scope) : 0; + + /* Should be at the same scope level as the anon tag */ + if (typedef_tag->type == tm_tag_typedef_t && + typedef_scope_len == scope_len && + g_strcmp0(typedef_tag->var_type, tag->name) == 0) + { + /* set the name of the original anon tag and pretend + * it wasn't a anon tag */ + tag->name = g_strdup(typedef_tag->name); + tag->flags &= ~tm_tag_flag_anon_t; + new_name = tag->name; + /* the typedef tag will be removed */ + if (!removed_typedefs) + removed_typedefs = g_ptr_array_new(); + g_ptr_array_add(removed_typedefs, GUINT_TO_POINTER(j)); + } + } + } + + /* there's no typedef name for the anon tag so let's generate one */ + if (!new_name) + { + gchar buf[50]; + guint anon_counter; + const gchar *kind_name = tm_ctags_get_kind_name(kind, tag->lang); + + if (!anon_counter_table) + anon_counter_table = g_new0(gint, 256); + + anon_counter = ++anon_counter_table[kind]; + + sprintf(buf, "anon_%s_%u", kind_name, anon_counter); + tag->name = g_strdup(buf); + new_name = tag->name; + } + + new_name_len = strlen(new_name); + + /* Check if this tag is parent of some other tag - if so, we have to + * update the scope. It can only be parent of the following tags + * so start with the next tag. */ + for (j = i + 1; j < source_file->tags_array->len; j++) + { + TMTag *nested_tag = TM_TAG(source_file->tags_array->pdata[j]); + guint nested_scope_len = nested_tag->scope ? strlen(nested_tag->scope) : 0; + gchar *pos; + + /* Terminate if outside of tag scope, see above */ + if (nested_scope_len <= scope_len) + break; + + pos = strstr(nested_tag->scope, orig_name); + /* We found the parent name in the nested tag scope - replace it + * with the new name. Note: anonymous tag names generated by + * ctags are unique enough that we don't have to check for + * scope separators here. */ + if (pos) + { + gchar *str = g_malloc(nested_scope_len + 50); + guint prefix_len = pos - nested_tag->scope; + + strncpy(str, nested_tag->scope, prefix_len); + strcpy(str + prefix_len, new_name); + strcpy(str + prefix_len + new_name_len, pos + orig_name_len); + g_free(nested_tag->scope); + nested_tag->scope = str; + } + } + + g_free(orig_name); + } + } + + if (removed_typedefs) + { + for (i = 0; i < removed_typedefs->len; i++) + { + guint j = GPOINTER_TO_UINT(removed_typedefs->pdata[i]); + TMTag *tag = TM_TAG(source_file->tags_array->pdata[j]); + tm_tag_unref(tag); + source_file->tags_array->pdata[j] = NULL; + } + + /* remove NULL entries from the array */ + tm_tags_prune(source_file->tags_array); + + g_ptr_array_free(removed_typedefs, TRUE); + } + + if (anon_counter_table) + g_free(anon_counter_table); +} + + void tm_ctags_parse(guchar *buffer, gsize buffer_size, const gchar *file_name, TMParserType language, TMSourceFile *source_file) { g_return_if_fail(buffer != NULL || file_name != NULL); parseRawBuffer(file_name, buffer, buffer_size, language, source_file); + + rename_anon_tags(source_file); } diff --git a/src/tagmanager/tm_source_file.c b/src/tagmanager/tm_source_file.c index d234b0ca9b..488acdfdeb 100644 --- a/src/tagmanager/tm_source_file.c +++ b/src/tagmanager/tm_source_file.c @@ -383,9 +383,10 @@ static gboolean init_tag_from_file_ctags(TMTag *tag, TMSourceFile *file, FILE *f const gchar *kind = value ? value : key; if (kind[0] && kind[1]) - tag->type = tm_parser_get_tag_type(tm_ctags_get_kind_from_name(kind, lang), lang); + tag->kind_letter = tm_ctags_get_kind_from_name(kind, lang); else - tag->type = tm_parser_get_tag_type(*kind, lang); + tag->kind_letter = *kind; + tag->type = tm_parser_get_tag_type(tag->kind_letter, lang); } else if (0 == strcmp(key, "inherits")) /* comma-separated list of classes this class inherits from */ { diff --git a/src/tagmanager/tm_tag.h b/src/tagmanager/tm_tag.h index 533d49af2f..27a78aa5b1 100644 --- a/src/tagmanager/tm_tag.h +++ b/src/tagmanager/tm_tag.h @@ -109,6 +109,7 @@ typedef struct TMTag char access; /**< Access type (public/protected/private/etc.) */ char impl; /**< Implementation (e.g. virtual) */ TMParserType lang; /* Programming language of the file */ + gchar kind_letter; /* Kind letter from ctags */ } TMTag; /* The GType for a TMTag */ From 6f6261678fb91100269521ad5952d441d184c849 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Techet?= Date: Sun, 19 Dec 2021 22:24:32 +0100 Subject: [PATCH 6/6] Update unit tests with the anonymous tag changes --- tests/ctags/bit_field.c.tags | 32 +++++++++++------------ tests/ctags/bug1466117.c.tags | 4 --- tests/ctags/bug1491666.c.tags | 7 +++-- tests/ctags/bug556646.c.tags | 41 +++++++++++++++--------------- tests/ctags/bug639639.h.tags | 4 +-- tests/ctags/bug639644.hpp.tags | 4 +-- tests/ctags/complex-return.js.tags | 4 +-- tests/ctags/enum.f90.tags | 4 +-- tests/ctags/enumerators.f90.tags | 18 ++++++------- tests/ctags/interfaces.f90.tags | 2 +- tests/ctags/namespace.cpp.tags | 4 +-- tests/ctags/numlib.f90.tags | 2 +- tests/ctags/process_order.c.tags | 12 ++++----- tests/ctags/recursive.f95.tags | 4 +-- tests/ctags/structure.f.tags | 2 +- 15 files changed, 68 insertions(+), 76 deletions(-) diff --git a/tests/ctags/bit_field.c.tags b/tests/ctags/bit_field.c.tags index a2062d24be..adf8b51c05 100644 --- a/tests/ctags/bit_field.c.tags +++ b/tests/ctags/bit_field.c.tags @@ -1,26 +1,24 @@ # format=tagmanager -__anon1Ì2048Ö0 -__anon2Ì2048Ö0 -__anon3Ì2048Ö0 aÌ64Îbit_fieldsÖ0Ïunsigned int:1 +anon_struct_1Ì2048Ö1 bÌ64Îbit_fieldsÖ0Ïunsigned int:1 -bad2Ì64Î__anon2Ö0ÏBYTE:1 +bad2Ì64Îbitfield_flagsÖ0ÏBYTE:1 bit_fieldsÌ2048Ö0 -bitfield_flagsÌ4096Ö0Ï__anon2 +bitfield_flagsÌ2048Ö0 cÌ64Îbit_fieldsÖ0Ïunsigned int:2 -expÌ64Î__anon1Ö0Ïunsigned -frac0Ì64Î__anon1Ö0Ïunsigned -frac1Ì64Î__anon1Ö0Ïunsigned -groupÌ64Î__anon2Ö0ÏBYTE:1 +expÌ64Îanon_struct_1Ö0Ïunsigned +frac0Ì64Îanon_struct_1Ö0Ïunsigned +frac1Ì64Îanon_struct_1Ö0Ïunsigned +groupÌ64Îbitfield_flagsÖ0ÏBYTE:1 lowerÌ64Îshortname_infoÖ0Ïunsigned char:1 -mystructÌ4096Ö0Ï__anon3 -personalÌ64Î__anon2Ö0ÏBYTE:1 -privateÌ64Î__anon3Ö0ÏBYTE -publicÌ64Î__anon2Ö0ÏBYTE:1 -publicÌ64Î__anon3Ö0ÏBYTE +mystructÌ2048Ö0 +personalÌ64Îbitfield_flagsÖ0ÏBYTE:1 +privateÌ64ÎmystructÖ0ÏBYTE +publicÌ64Îbitfield_flagsÖ0ÏBYTE:1 +publicÌ64ÎmystructÖ0ÏBYTE shortname_infoÌ2048Ö0 -signÌ64Î__anon1Ö0Ïunsigned:1 -thatÌ64Î__anon3Ö0ÏBYTE -thisÌ64Î__anon3Ö0ÏBYTE +signÌ64Îanon_struct_1Ö0Ïunsigned:1 +thatÌ64ÎmystructÖ0ÏBYTE +thisÌ64ÎmystructÖ0ÏBYTE upperÌ64Îshortname_infoÖ0Ïunsigned char:1 validÌ64Îshortname_infoÖ0Ïunsigned char:1 diff --git a/tests/ctags/bug1466117.c.tags b/tests/ctags/bug1466117.c.tags index 960bd3b7be..8c318a6c3a 100644 --- a/tests/ctags/bug1466117.c.tags +++ b/tests/ctags/bug1466117.c.tags @@ -1,8 +1,4 @@ # format=tagmanager -__anon1Ì2048Ö0 -aÌ64Î__anon1Ö0Ïint aÌ64ÎmystructÖ0Ïint -bÌ64Î__anon1Ö0Ïint bÌ64ÎmystructÖ0Ïint mystructÌ2048Ö0 -mystructÌ4096Ö0Ï__anon1 diff --git a/tests/ctags/bug1491666.c.tags b/tests/ctags/bug1491666.c.tags index 697a27a9b1..3c6cc71239 100644 --- a/tests/ctags/bug1491666.c.tags +++ b/tests/ctags/bug1491666.c.tags @@ -1,6 +1,5 @@ # format=tagmanager -__anon1Ì2048Ö0 mainÌ16Í(void)Ö0Ïvoid -my_structÌ4096Ö0Ï__anon1 -xÌ64Î__anon1Ö0Ïint -yÌ64Î__anon1Ö0Ïfloat +my_structÌ2048Ö0 +xÌ64Îmy_structÖ0Ïint +yÌ64Îmy_structÖ0Ïfloat diff --git a/tests/ctags/bug556646.c.tags b/tests/ctags/bug556646.c.tags index 18b18bd30a..b036ba905a 100644 --- a/tests/ctags/bug556646.c.tags +++ b/tests/ctags/bug556646.c.tags @@ -1,22 +1,21 @@ # format=tagmanager -AÌ4Î__anon1Ö0 -INDX_C1Ì4Î__anon1Ö0 -INDX_C2Ì4Î__anon1Ö0 -INDX_IM1Ì4Î__anon1Ö0 -INDX_IM2Ì4Î__anon1Ö0 -INDX_LÌ4Î__anon1Ö0 -INDX_L2Ì4Î__anon1Ö0 -INDX_MÌ4Î__anon1Ö0 -INDX_NILÌ4Î__anon1Ö0 -INDX_PÌ4Î__anon1Ö0 -INDX_RÌ4Î__anon1Ö0 -INDX_R2Ì4Î__anon1Ö0 -INDX_SÌ4Î__anon1Ö0 -INDX_S1Ì4Î__anon1Ö0 -INDX_S2Ì4Î__anon1Ö0 -INDX_S3Ì4Î__anon1Ö0 -INDX_S4Ì4Î__anon1Ö0 -INDX_TÌ4Î__anon1Ö0 -INDX_T2Ì4Î__anon1Ö0 -__anon1Ì2Ö0 -task_indx_typeÌ4096Ö0Ï__anon1 +AÌ4Îtask_indx_typeÖ0 +INDX_C1Ì4Îtask_indx_typeÖ0 +INDX_C2Ì4Îtask_indx_typeÖ0 +INDX_IM1Ì4Îtask_indx_typeÖ0 +INDX_IM2Ì4Îtask_indx_typeÖ0 +INDX_LÌ4Îtask_indx_typeÖ0 +INDX_L2Ì4Îtask_indx_typeÖ0 +INDX_MÌ4Îtask_indx_typeÖ0 +INDX_NILÌ4Îtask_indx_typeÖ0 +INDX_PÌ4Îtask_indx_typeÖ0 +INDX_RÌ4Îtask_indx_typeÖ0 +INDX_R2Ì4Îtask_indx_typeÖ0 +INDX_SÌ4Îtask_indx_typeÖ0 +INDX_S1Ì4Îtask_indx_typeÖ0 +INDX_S2Ì4Îtask_indx_typeÖ0 +INDX_S3Ì4Îtask_indx_typeÖ0 +INDX_S4Ì4Îtask_indx_typeÖ0 +INDX_TÌ4Îtask_indx_typeÖ0 +INDX_T2Ì4Îtask_indx_typeÖ0 +task_indx_typeÌ2Ö0 diff --git a/tests/ctags/bug639639.h.tags b/tests/ctags/bug639639.h.tags index 1a0526521a..2ff58b3b52 100644 --- a/tests/ctags/bug639639.h.tags +++ b/tests/ctags/bug639639.h.tags @@ -1,5 +1,5 @@ # format=tagmanager Namespace1Ì256Ö0 -__anon1Ì2Ö0 -anon2Ì4Î__anon1Ö0 +anon2Ì4Îanon_enum_1Ö0 +anon_enum_1Ì2Ö1 function2Ì1024Í(char * str)ÎNamespace1Ö0Ïint diff --git a/tests/ctags/bug639644.hpp.tags b/tests/ctags/bug639644.hpp.tags index 476a83e3dd..f208a5427d 100644 --- a/tests/ctags/bug639644.hpp.tags +++ b/tests/ctags/bug639644.hpp.tags @@ -1,3 +1,3 @@ # format=tagmanager -__anon1Ì256Ö0 -fooÌ16384Î__anon1Ö0Ïint +anon_namespace_1Ì256Ö1 +fooÌ16384Îanon_namespace_1Ö0Ïint diff --git a/tests/ctags/complex-return.js.tags b/tests/ctags/complex-return.js.tags index 0142401841..17c32cfa19 100644 --- a/tests/ctags/complex-return.js.tags +++ b/tests/ctags/complex-return.js.tags @@ -1,6 +1,6 @@ # format=tagmanager -AnonymousFunction1Ì16Í()Îclass2.c2m1Ö0 -AnonymousFunction2Ì16Í(n)Îclass3.c3m1Ö0 +anon_function_1Ì16Í()Îclass2.c2m1Ö1 +anon_function_2Ì16Í(n)Îclass3.c3m1Ö1 c2m1Ì128Í()Îclass2Ö0 c2m2Ì128Í(f)Îclass2Ö0 c2m3Ì128Í(f)Îclass2Ö0 diff --git a/tests/ctags/enum.f90.tags b/tests/ctags/enum.f90.tags index 444dfc70e3..b19130516c 100644 --- a/tests/ctags/enum.f90.tags +++ b/tests/ctags/enum.f90.tags @@ -1,8 +1,6 @@ # format=tagmanager ConstantsÌ256Ö0 E_eÌ16384ÎConstantsÖ0 -Enum#0Ì2ÎConstantsÖ0 -Enum#1Ì2ÎConstantsÖ0 Named1Ì2ÎConstantsÖ0 Named2Ì2ÎConstantsÖ0 Named3Ì2ÎConstantsÖ0 @@ -11,6 +9,8 @@ Named5 Named6Ì2ÎConstantsÖ0 Named7Ì2ÎConstantsÖ0 aÌ4ÎEnum#1Ö0 +anon_enum_1Ì2ÎConstantsÖ1 +anon_enum_2Ì2ÎConstantsÖ1 bÌ4ÎEnum#1Ö0 blackÌ4ÎEnum#0Ö0 blueÌ4ÎEnum#0Ö0 diff --git a/tests/ctags/enumerators.f90.tags b/tests/ctags/enumerators.f90.tags index 28eaf95e7d..ec3c87aabb 100644 --- a/tests/ctags/enumerators.f90.tags +++ b/tests/ctags/enumerators.f90.tags @@ -3,27 +3,27 @@ Aster_colon Aster_kindÌ2ÎEnumsÖ0 BodyPartÌ2ÎEnumsÖ0 ColonsÌ2ÎEnumsÖ0 -Enum#0Ì2ÎEnumsÖ0 -Enum#1Ì2ÎEnumsÖ0 EnumsÌ256Ö0 FuncÌ16ÎEnumsÖ0 Name_colonÌ2ÎEnumsÖ0 Paren_colonÌ2ÎEnumsÖ0 Paren_kindÌ2ÎEnumsÖ0 +anon_enum_1Ì2ÎEnumsÖ1 +anon_enum_2Ì2ÎEnumsÖ1 armÌ4ÎBodyPartÖ0 bÌ4ÎParen_kindÖ0 -blueÌ4ÎEnum#0Ö0 -bronzeÌ4ÎEnum#0Ö0 +blueÌ4Îanon_enum_1Ö0 +bronzeÌ4Îanon_enum_1Ö0 cÌ4ÎAster_kindÖ0 dÌ4ÎName_colonÖ0 dÌ4ÎParen_colonÖ0 eÌ4ÎAster_colonÖ0 -goldÌ4ÎEnum#0Ö0 +goldÌ4Îanon_enum_1Ö0 legÌ4ÎBodyPartÖ0 -no_c_bindingÌ4ÎEnum#1Ö0 +no_c_bindingÌ4Îanon_enum_2Ö0 othervarÌ16384ÎEnumsÖ0 -purpleÌ4ÎEnum#0Ö0 +purpleÌ4Îanon_enum_1Ö0 rÌ4ÎColonsÖ0 -redÌ4ÎEnum#0Ö0 -silverÌ4ÎEnum#0Ö0 +redÌ4Îanon_enum_1Ö0 +silverÌ4Îanon_enum_1Ö0 somevarÌ16384ÎEnumsÖ0 diff --git a/tests/ctags/interfaces.f90.tags b/tests/ctags/interfaces.f90.tags index 5e9e0d620d..62c94fa869 100644 --- a/tests/ctags/interfaces.f90.tags +++ b/tests/ctags/interfaces.f90.tags @@ -2,7 +2,7 @@ Func1Ì16ÎHasInterfacesÖ0 Func2Ì16ÎHasInterfacesÖ0 HasInterfacesÌ256Ö0 -Interface#0Ì32ÎHasInterfacesÖ0 MainÌ2048Ö0 MyFuncÌ32ÎHasInterfacesÖ0 MySubroutineÌ32ÎMainÖ0 +anon_interface_1Ì32ÎHasInterfacesÖ1 diff --git a/tests/ctags/namespace.cpp.tags b/tests/ctags/namespace.cpp.tags index 7bee2d66a0..da4271a3c4 100644 --- a/tests/ctags/namespace.cpp.tags +++ b/tests/ctags/namespace.cpp.tags @@ -1,7 +1,7 @@ # format=tagmanager -__anon1Ì256Ö0 aÌ256Ö0 a_b_fÌ16Í()Îa::bÖ0Ïvoid a_fÌ16Í()ÎaÖ0Ïvoid -anon_fÌ16Í()Î__anon1Ö0Ïvoid +anon_fÌ16Í()Îanon_namespace_1Ö0Ïvoid +anon_namespace_1Ì256Ö1 bÌ256ÎaÖ0 diff --git a/tests/ctags/numlib.f90.tags b/tests/ctags/numlib.f90.tags index 4e9e18a8ee..ba5154c631 100644 --- a/tests/ctags/numlib.f90.tags +++ b/tests/ctags/numlib.f90.tags @@ -1,3 +1,3 @@ # format=tagmanager -Interface#0Ì32Înumerical_librariesÖ0 +anon_interface_1Ì32Înumerical_librariesÖ1 numerical_librariesÌ256Ö0 diff --git a/tests/ctags/process_order.c.tags b/tests/ctags/process_order.c.tags index 771640cb46..4ed2113cc7 100644 --- a/tests/ctags/process_order.c.tags +++ b/tests/ctags/process_order.c.tags @@ -1,7 +1,7 @@ # format=tagmanager -I1_E1Ì4Î__anon1Ö0 -I1_E2Ì4Î__anon1Ö0 -I2_E1Ì4Î__anon2Ö0 -I2_E2Ì4Î__anon2Ö0 -__anon1Ì2Ö0 -__anon2Ì2Ö0 +I1_E1Ì4Îanon_enum_1Ö0 +I1_E2Ì4Îanon_enum_1Ö0 +I2_E1Ì4Îanon_enum_2Ö0 +I2_E2Ì4Îanon_enum_2Ö0 +anon_enum_1Ì2Ö1 +anon_enum_2Ì2Ö1 diff --git a/tests/ctags/recursive.f95.tags b/tests/ctags/recursive.f95.tags index d3aa8bc36d..f9244cf7be 100644 --- a/tests/ctags/recursive.f95.tags +++ b/tests/ctags/recursive.f95.tags @@ -1,6 +1,6 @@ # format=tagmanager -Interface#0Ì32ÎapproxÖ0 -Interface#1Ì32Îapprox2Ö0 +anon_interface_1Ì32ÎapproxÖ1 +anon_interface_2Ì32Îapprox2Ö1 approxÌ256Ö0 approx2Ì256Ö0 partsÌ16384ÎapproxÖ0 diff --git a/tests/ctags/structure.f.tags b/tests/ctags/structure.f.tags index 0852cd4fbd..479c2d9e03 100644 --- a/tests/ctags/structure.f.tags +++ b/tests/ctags/structure.f.tags @@ -1,6 +1,6 @@ # format=tagmanager -Structure#0Ì1ÎnestedÖ0 aÌ64ÎStructure#0Ö0 +anon_type_1Ì1ÎnestedÖ1 cloudsÌ64ÎweatherÖ0 dayÌ64ÎweatherÖ0 initialized_structureÌ2048Ö0