Rename pointerOrder TMtag member to flags
[geany-mirror.git] / src / tagmanager / tm_ctags.c
blobe0892cb93dcc8520a68cb5bdbd771ecbdf942f07
1 /*
2 * Copyright (c) 2016, Jiri Techet
4 * This source code is released for free distribution under the terms of the
5 * GNU General Public License version 2 or (at your option) any later version.
7 * Encapsulates ctags so it is isolated from the rest of Geany.
8 */
10 #include "tm_ctags.h"
11 #include "tm_tag.h"
13 #include "general.h" /* must always come before the rest of ctags headers */
14 #include "entry_p.h"
15 #include "error_p.h"
16 #include "field_p.h"
17 #include "options_p.h"
18 #include "parse_p.h"
19 #include "trashbox_p.h"
20 #include "writer_p.h"
21 #include "xtag_p.h"
22 #include "param_p.h"
24 #include <string.h>
27 static gint write_entry(tagWriter *writer, MIO * mio, const tagEntryInfo *const tag, void *user_data);
28 static void rescan_failed(tagWriter *writer, gulong valid_tag_num, void *user_data);
30 tagWriter geanyWriter = {
31 .writeEntry = write_entry,
32 .writePtagEntry = NULL, /* no pseudo-tags */
33 .preWriteEntry = NULL,
34 .postWriteEntry = NULL,
35 .rescanFailedEntry = rescan_failed,
36 .treatFieldAsFixed = NULL,
37 .defaultFileName = "geany_tags_file_which_should_never_appear_anywhere",
38 .private = NULL,
39 .type = WRITER_CUSTOM
43 static bool nonfatal_error_printer(const errorSelection selection,
44 const gchar *const format,
45 va_list ap, void *data CTAGS_ATTR_UNUSED)
47 g_logv(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, format, ap);
49 return false;
53 static void enable_roles(const TMParserType lang, guint kind)
55 unsigned int c = countLanguageRoles(lang, kind);
56 kindDefinition *def = getLanguageKind(lang, kind);
57 gchar kind_letter = def->letter;
59 for (unsigned int i = 0; i < c; i++)
61 roleDefinition* rdef = getLanguageRole(lang, kind, (int)i);
62 gboolean should_enable = tm_parser_enable_role(lang, kind_letter);
63 enableRole(rdef, should_enable);
68 static void enable_kinds_and_roles()
70 TMParserType lang;
72 for (lang = 0; lang < countParsers(); lang++)
74 guint kind_num = countLanguageKinds(lang);
75 guint kind;
77 for (kind = 0; kind < kind_num; kind++)
79 kindDefinition *def = getLanguageKind(lang, kind);
80 gboolean should_enable = tm_parser_enable_kind(lang, def->letter);
82 enableKind(def, should_enable);
83 if (should_enable)
84 enable_roles(lang, kind);
91 Initializes a TMTag structure with information from a ctagsTag struct
92 used by the ctags parsers. Note that the TMTag structure must be malloc()ed
93 before calling this function.
94 @param tag The TMTag structure to initialize
95 @param file Pointer to a TMSourceFile struct (it is assigned to the file member)
96 @param tag_entry Tag information gathered by the ctags parser
97 @return TRUE on success, FALSE on failure
99 static gboolean init_tag(TMTag *tag, TMSourceFile *file, const tagEntryInfo *tag_entry)
101 TMTagType type;
102 guchar kind_letter;
103 TMParserType lang;
105 if (!tag_entry)
106 return FALSE;
108 lang = tag_entry->langType;
109 kind_letter = getLanguageKind(tag_entry->langType, tag_entry->kindIndex)->letter;
110 type = tm_parser_get_tag_type(kind_letter, lang);
111 if (file->lang != lang) /* this is a tag from a subparser */
113 /* check for possible re-definition of subparser type */
114 type = tm_parser_get_subparser_type(file->lang, lang, type);
117 if (!tag_entry->name || type == tm_tag_undef_t)
118 return FALSE;
120 tag->name = g_strdup(tag_entry->name);
121 tag->type = type;
122 tag->local = tag_entry->isFileScope;
123 tag->flags = 0;
124 tag->line = tag_entry->lineNumber;
125 if (NULL != tag_entry->extensionFields.signature)
126 tag->arglist = g_strdup(tag_entry->extensionFields.signature);
127 if ((NULL != tag_entry->extensionFields.scopeName) &&
128 (0 != tag_entry->extensionFields.scopeName[0]))
129 tag->scope = g_strdup(tag_entry->extensionFields.scopeName);
130 if (tag_entry->extensionFields.inheritance != NULL)
131 tag->inheritance = g_strdup(tag_entry->extensionFields.inheritance);
132 if (tag_entry->extensionFields.typeRef[1] != NULL)
133 tag->var_type = g_strdup(tag_entry->extensionFields.typeRef[1]);
134 if (tag_entry->extensionFields.access != NULL)
135 tag->access = tm_source_file_get_tag_access(tag_entry->extensionFields.access);
136 if (tag_entry->extensionFields.implementation != NULL)
137 tag->impl = tm_source_file_get_tag_impl(tag_entry->extensionFields.implementation);
138 if ((tm_tag_macro_t == tag->type) && (NULL != tag->arglist))
139 tag->type = tm_tag_macro_with_arg_t;
140 tag->file = file;
141 /* redefine lang also for subparsers because the rest of Geany assumes that
142 * tags from a single file are from a single language */
143 tag->lang = file->lang;
144 if (tag->scope)
146 gchar *new_scope = tm_parser_update_scope(tag->lang, tag->scope);
147 if (new_scope != tag->scope)
149 g_free(tag->scope);
150 tag->scope = new_scope;
153 return TRUE;
157 static gint write_entry(tagWriter *writer, MIO * mio, const tagEntryInfo *const tag, void *user_data)
159 TMSourceFile *source_file = user_data;
160 TMTag *tm_tag = tm_tag_new();
162 getTagScopeInformation((tagEntryInfo *)tag, NULL, NULL);
164 if (!init_tag(tm_tag, source_file, tag))
166 tm_tag_unref(tm_tag);
167 return 0;
170 g_ptr_array_add(source_file->tags_array, tm_tag);
172 /* output length - we don't write anything to the MIO */
173 return 0;
177 static void rescan_failed(tagWriter *writer, gulong valid_tag_num, void *user_data)
179 TMSourceFile *source_file = user_data;
180 GPtrArray *tags_array = source_file->tags_array;
182 if (tags_array->len > valid_tag_num)
184 guint i;
185 for (i = valid_tag_num; i < tags_array->len; i++)
186 tm_tag_unref(tags_array->pdata[i]);
187 g_ptr_array_set_size(tags_array, valid_tag_num);
192 /* keep in sync with ctags main() - use only things interesting for us */
193 void tm_ctags_init(void)
195 initDefaultTrashBox();
197 setErrorPrinter(nonfatal_error_printer, NULL);
198 setTagWriter(WRITER_CUSTOM, &geanyWriter);
200 checkRegex();
201 initFieldObjects();
202 initXtagObjects();
204 initializeParsing();
205 initOptions();
206 initRegexOptscript();
208 /* make sure all parsers are initialized */
209 initializeParser(LANG_AUTO);
211 /* change default values which are false */
212 enableXtag(XTAG_TAGS_GENERATED_BY_GUEST_PARSERS, true);
213 enableXtag(XTAG_REFERENCE_TAGS, true);
215 /* some kinds we are interested in are disabled by default */
216 enable_kinds_and_roles();
220 void tm_ctags_add_ignore_symbol(const char *value)
222 langType lang = getNamedLanguage ("CPreProcessor", 0);
223 gchar *val = g_strdup(value);
225 /* make sure we don't enter empty string - passing NULL or "" clears
226 * the ignore list in ctags */
227 val = g_strstrip(val);
228 if (*val)
229 applyParameter (lang, "ignore", val);
230 g_free(val);
234 void tm_ctags_clear_ignore_symbols(void)
236 langType lang = getNamedLanguage ("CPreProcessor", 0);
237 applyParameter (lang, "ignore", NULL);
241 void tm_ctags_parse(guchar *buffer, gsize buffer_size,
242 const gchar *file_name, TMParserType language, TMSourceFile *source_file)
244 g_return_if_fail(buffer != NULL || file_name != NULL);
246 parseRawBuffer(file_name, buffer, buffer_size, language, source_file);
250 const gchar *tm_ctags_get_lang_name(TMParserType lang)
252 return getLanguageName(lang);
256 TMParserType tm_ctags_get_named_lang(const gchar *name)
258 return getNamedLanguage(name, 0);
262 const gchar *tm_ctags_get_lang_kinds(TMParserType lang)
264 guint kind_num = countLanguageKinds(lang);
265 static gchar kinds[257];
266 guint i;
268 for (i = 0; i < kind_num; i++)
269 kinds[i] = getLanguageKind(lang, i)->letter;
270 kinds[i] = '\0';
272 return kinds;
276 const gchar *tm_ctags_get_kind_name(gchar kind, TMParserType lang)
278 kindDefinition *def = getLanguageKindForLetter(lang, kind);
279 return def ? def->name : "unknown";
283 gchar tm_ctags_get_kind_from_name(const gchar *name, TMParserType lang)
285 kindDefinition *def = getLanguageKindForName(lang, name);
286 return def ? def->letter : '-';
290 guint tm_ctags_get_lang_count(void)
292 return countParsers();