/* scope can be NULL. * lang can be -1 */ static int fill_find_tags_array (GPtrArray *dst, const GPtrArray *src, const char *name, const char *scope, int type, gboolean partial, gint lang, gboolean first) { TMTag **match; int tagIter, count; if ((!src) || (!dst) || (!name) || (!*name)) return 0; match = tm_tags_find (src, name, partial, &count); if (count && match && *match) { for (tagIter = 0; tagIter < count; ++tagIter) { if (! scope || (match[tagIter]->atts.entry.scope && 0 == strcmp(match[tagIter]->atts.entry.scope, scope))) { if (type & match[tagIter]->type) if (lang == -1 || match_langs(lang, match[tagIter])) { g_ptr_array_add (dst, match[tagIter]); if (first) break; } } } } return dst->len; }
static void fill_find_tags_array(GPtrArray *dst, const GPtrArray *src, const char *name, const char *scope, TMTagType type, TMParserType lang) { TMTag **tag; guint i, num; if (!src || !dst || !name || !*name) return; tag = tm_tags_find(src, name, FALSE, &num); for (i = 0; i < num; ++i) { if ((type & (*tag)->type) && tm_tag_langs_compatible(lang, (*tag)->lang) && (!scope || g_strcmp0((*tag)->scope, scope) == 0)) { g_ptr_array_add(dst, *tag); } tag++; } }
void tm_source_file_set_tag_arglist(const char *tag_name, const char *arglist) { int count; TMTag **tags, *tag; if (NULL == arglist || NULL == tag_name || NULL == current_source_file || NULL == current_source_file->work_object.tags_array) { return; } tags = tm_tags_find(current_source_file->work_object.tags_array, tag_name, FALSE, FALSE, &count); if (tags != NULL && count == 1) { tag = tags[0]; g_free(tag->atts.entry.arglist); tag->atts.entry.arglist = g_strdup(arglist); } }
static void fill_find_tags_array_prefix(GPtrArray *dst, const GPtrArray *src, const char *name, TMParserType lang, guint max_num) { TMTag **tag, *last = NULL; guint i, count, num; if (!src || !dst || !name || !*name) return; num = 0; tag = tm_tags_find(src, name, TRUE, &count); for (i = 0; i < count && num < max_num; ++i) { if (tm_tag_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++; } }
void tm_tags_remove_file_tags(TMSourceFile *source_file, GPtrArray *tags_array) { guint i; /* Now we choose between an algorithm with complexity O(tags_array->len) and * O(source_file->tags_array->len * log(tags_array->len)). The latter algorithm * is better when tags_array contains many times more tags than * source_file->tags_array so instead of trying to find the removed tags * linearly, binary search is used. The constant 20 is more or less random * but seems to work well. It's exact value isn't so critical because it's * the extremes where the difference is the biggest: when * source_file->tags_array->len == tags_array->len (single file open) and * source_file->tags_array->len << tags_array->len (the number of tags * from the file is a small fraction of all tags). */ if (source_file->tags_array->len != 0 && tags_array->len / source_file->tags_array->len < 20) { for (i = 0; i < tags_array->len; i++) { TMTag *tag = tags_array->pdata[i]; if (tag->file == source_file) tags_array->pdata[i] = NULL; } } else { GPtrArray *to_delete = g_ptr_array_sized_new(source_file->tags_array->len); for (i = 0; i < source_file->tags_array->len; i++) { guint j; guint tag_count; TMTag **found; TMTag *tag = source_file->tags_array->pdata[i]; found = tm_tags_find(tags_array, tag->name, FALSE, TRUE, &tag_count); for (j = 0; j < tag_count; j++) { if (*found != NULL && (*found)->file == source_file) { /* we cannot set the pointer to NULL now because the search wouldn't work */ g_ptr_array_add(to_delete, found); /* no break - if there are multiple tags of the same name, we would * always find the first instance and wouldn't remove others; duplicates * in the to_delete list aren't a problem */ } found++; } } for (i = 0; i < to_delete->len; i++) { TMTag **tag = to_delete->pdata[i]; *tag = NULL; } g_ptr_array_free(to_delete, TRUE); } tm_tags_prune(tags_array); }
const GPtrArray *tm_workspace_find(const char *name, int type, TMTagAttrType *attrs , gboolean partial, langType lang) { static GPtrArray *tags = NULL; TMTag **matches[2]; int len, tagCount[2]={0,0}, tagIter; gint tags_lang; if ((!theWorkspace) || (!name)) return NULL; len = strlen(name); if (!len) return NULL; if (tags) g_ptr_array_set_size(tags, 0); else tags = g_ptr_array_new(); matches[0] = tm_tags_find(theWorkspace->work_object.tags_array, name, partial, &tagCount[0]); matches[1] = tm_tags_find(theWorkspace->global_tags, name, partial, &tagCount[1]); /* file tags */ if (matches[0] && *matches[0]) { /* tag->atts.file.lang contains the line of the tag and * tags->atts.entry.file->lang contains the language */ tags_lang = (*matches[0])->atts.entry.file->lang; for (tagIter=0;tagIter<tagCount[0];++tagIter) { if ((type & (*matches[0])->type) && (lang == -1 || tags_lang == lang)) g_ptr_array_add(tags, *matches[0]); if (partial) { if (0 != strncmp((*matches[0])->name, name, len)) break; } else { if (0 != strcmp((*matches[0])->name, name)) break; } ++ matches[0]; } } /* global tags */ if (matches[1] && *matches[1]) { int tags_lang_alt = 0; /* tag->atts.file.lang contains the language and * tags->atts.entry.file is NULL */ tags_lang = (*matches[1])->atts.file.lang; /* tags_lang_alt is used to load C global tags only once for C and C++ * lang = 1 is C++, lang = 0 is C * if we have lang 0, than accept also lang 1 for C++ */ if (tags_lang == 0) /* C or C++ */ tags_lang_alt = 1; else tags_lang_alt = tags_lang; /* otherwise just ignore it */ for (tagIter=0;tagIter<tagCount[1];++tagIter) { if ((type & (*matches[1])->type) && (lang == -1 || tags_lang == lang || tags_lang_alt == lang)) g_ptr_array_add(tags, *matches[1]); if (partial) { if (0 != strncmp((*matches[1])->name, name, len)) break; } else { if (0 != strcmp((*matches[1])->name, name)) break; } ++ matches[1]; } } if (attrs) tm_tags_sort(tags, attrs, TRUE); return tags; }