Don't use temporary file when creating tag files without running preprocessor
The tm_workspace_create_global_tags() function generates tags for
two cases:
1. Source files pre-processed by C pre-processor. It first generates
a file combining the parsed header files by creating a temporary
file in which all the header files are included and this file is passed
to the pre-processor. The result of the pre-processed file is then
parsed by the ctags parser.
2. Source files directly parsed by the ctags parser. In this case all
the source files are concatenated to a single file which is then parsed
by the ctags parser.
This patch leaves (1) more or less unchanged; however, the creation of
the temporary file in (2) is unnecessary - the individual files can
be parsed directly, the tags from all the parses can be combined, sorted
and pruned without creating the temporary file.
The temporary file is a problem for unit tests where some languages
use the file name as the name of module in which the tags are defined
and by using a different name, the unit test generates a different tag
file every time it's run.
Note the changed output of the process_order unit test caused by this
change. The test parses two files, one containing
enum {
I1_E1,
I1_E2,
};
the other contining
enum {
I2_E1,
I2_E2,
};
Previously, because the files were concatenated the enums were different
tags and the anonnymous tag renaming function renamed them to anon_enum_1
and anon_enum_2. Because now the files are parsed separately, the
enum from the first file gets renamed to anon_enum_1 and when parsing
the second file, we get the name anon_enum_1 as well for the second enum.
This however isn't a problem - we don't display global tags in the
symbol tree, autocompletion, and they are also ignored in scope completion
so this shouldn't matter much.
This commit is contained in:
parent
30f5514465
commit
8c7081c652
@ -387,40 +387,6 @@ static gboolean write_includes_file(const gchar *outf, GList *includes_files)
|
||||
return fclose(fp) == 0;
|
||||
}
|
||||
|
||||
|
||||
static gboolean combine_source_files(const gchar *outf, GList *file_list)
|
||||
{
|
||||
FILE *fp = g_fopen(outf, "w");
|
||||
GList *node = file_list;
|
||||
|
||||
if (!fp)
|
||||
return FALSE;
|
||||
|
||||
while (node)
|
||||
{
|
||||
const char *fname = node->data;
|
||||
char *contents;
|
||||
size_t length;
|
||||
GError *err = NULL;
|
||||
|
||||
if (! g_file_get_contents(fname, &contents, &length, &err))
|
||||
{
|
||||
fprintf(stderr, "Unable to read file: %s\n", err->message);
|
||||
g_error_free(err);
|
||||
}
|
||||
else
|
||||
{
|
||||
fwrite(contents, length, 1, fp);
|
||||
fwrite("\n", 1, 1, fp); /* in case file doesn't end in newline (e.g. windows). */
|
||||
g_free(contents);
|
||||
}
|
||||
node = g_list_next (node);
|
||||
}
|
||||
|
||||
return fclose(fp) == 0;
|
||||
}
|
||||
|
||||
|
||||
static gchar *create_temp_file(const gchar *tpl)
|
||||
{
|
||||
gchar *name;
|
||||
@ -503,57 +469,35 @@ static gchar *pre_process_file(const gchar *cmd, const gchar *inf)
|
||||
return outf;
|
||||
}
|
||||
|
||||
/* Creates a list of global tags. Ideally, this should be created once during
|
||||
installations so that all users can use the same file. This is because a full
|
||||
scale global tag list can occupy several megabytes of disk space.
|
||||
@param pre_process_cmd The pre-processing command. This is executed via system(),
|
||||
so you can pass stuff like 'gcc -E -dD -P `gnome-config --cflags gnome`'.
|
||||
@param sources Source files to process. Wildcards such as '/usr/include/a*.h'
|
||||
are allowed.
|
||||
@param tags_file The file where the tags will be stored.
|
||||
@param lang The language to use for the tags file.
|
||||
@return TRUE on success, FALSE on failure.
|
||||
*/
|
||||
gboolean tm_workspace_create_global_tags(const char *pre_process_cmd, const char **sources,
|
||||
int sources_count, const char *tags_file, TMParserType lang)
|
||||
static gboolean create_global_tags_preprocessed(const char *pre_process_cmd,
|
||||
GList *source_files, const char *tags_file, TMParserType lang)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
TMSourceFile *source_file;
|
||||
GList *source_files;
|
||||
gboolean ret = FALSE;
|
||||
gchar *temp_file2;
|
||||
gchar *temp_file = create_temp_file("tmp_XXXXXX.cpp");
|
||||
GPtrArray *filtered_tags;
|
||||
|
||||
if (!temp_file)
|
||||
return FALSE;
|
||||
|
||||
source_files = lookup_sources(sources, sources_count);
|
||||
|
||||
#ifdef TM_DEBUG
|
||||
g_message ("writing out files to %s\n", temp_file);
|
||||
#endif
|
||||
if (pre_process_cmd)
|
||||
ret = write_includes_file(temp_file, source_files);
|
||||
else
|
||||
ret = combine_source_files(temp_file, source_files);
|
||||
|
||||
g_list_free_full(source_files, g_free);
|
||||
if (!ret)
|
||||
if (!temp_file)
|
||||
return FALSE;
|
||||
|
||||
if (!write_includes_file(temp_file, source_files))
|
||||
goto cleanup;
|
||||
ret = FALSE;
|
||||
|
||||
if (pre_process_cmd)
|
||||
temp_file2 = pre_process_file(pre_process_cmd, temp_file);
|
||||
|
||||
if (temp_file2)
|
||||
{
|
||||
gchar *temp_file2 = pre_process_file(pre_process_cmd, temp_file);
|
||||
|
||||
if (temp_file2)
|
||||
{
|
||||
g_unlink(temp_file);
|
||||
g_free(temp_file);
|
||||
temp_file = temp_file2;
|
||||
}
|
||||
else
|
||||
goto cleanup;
|
||||
g_unlink(temp_file);
|
||||
g_free(temp_file);
|
||||
temp_file = temp_file2;
|
||||
}
|
||||
else
|
||||
goto cleanup;
|
||||
|
||||
source_file = tm_source_file_new(temp_file, tm_source_file_get_lang_name(lang));
|
||||
if (!source_file)
|
||||
@ -577,6 +521,66 @@ cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean create_global_tags_direct(GList *source_files, const char *tags_file,
|
||||
TMParserType lang)
|
||||
{
|
||||
GList *node;
|
||||
GPtrArray *filtered_tags;
|
||||
GPtrArray *tags = g_ptr_array_new();
|
||||
GSList *tm_source_files = NULL;
|
||||
gboolean ret = FALSE;
|
||||
|
||||
for (node = source_files; node; node = node->next)
|
||||
{
|
||||
TMSourceFile *source_file = tm_source_file_new(node->data, tm_source_file_get_lang_name(lang));
|
||||
if (source_file)
|
||||
{
|
||||
guint i;
|
||||
tm_source_files = g_slist_prepend(tm_source_files, source_file);
|
||||
tm_source_file_parse(source_file, NULL, 0, FALSE);
|
||||
for (i = 0; i < source_file->tags_array->len; i++)
|
||||
g_ptr_array_add(tags, source_file->tags_array->pdata[i]);
|
||||
}
|
||||
}
|
||||
|
||||
filtered_tags = tm_tags_extract(tags, ~tm_tag_local_var_t);
|
||||
tm_tags_sort(filtered_tags, global_tags_sort_attrs, TRUE, FALSE);
|
||||
|
||||
if (filtered_tags->len > 0)
|
||||
ret = tm_source_file_write_tags_file(tags_file, filtered_tags);
|
||||
|
||||
g_ptr_array_free(tags, TRUE);
|
||||
g_ptr_array_free(filtered_tags, TRUE);
|
||||
g_slist_free_full(tm_source_files, (GDestroyNotify)tm_source_file_free);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Creates a list of global tags. Ideally, this should be created once during
|
||||
installations so that all users can use the same file. This is because a full
|
||||
scale global tag list can occupy several megabytes of disk space.
|
||||
@param pre_process_cmd The pre-processing command. This is executed via system(),
|
||||
so you can pass stuff like 'gcc -E -dD -P `gnome-config --cflags gnome`'.
|
||||
@param sources Source files to process. Wildcards such as '/usr/include/a*.h'
|
||||
are allowed.
|
||||
@param tags_file The file where the tags will be stored.
|
||||
@param lang The language to use for the tags file.
|
||||
@return TRUE on success, FALSE on failure.
|
||||
*/
|
||||
gboolean tm_workspace_create_global_tags(const char *pre_process_cmd, const char **sources,
|
||||
int sources_count, const char *tags_file, TMParserType lang)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
GList *source_files = lookup_sources(sources, sources_count);
|
||||
|
||||
if (pre_process_cmd)
|
||||
ret = create_global_tags_preprocessed(pre_process_cmd, source_files, tags_file, lang);
|
||||
else
|
||||
ret = create_global_tags_direct(source_files, tags_file, lang);
|
||||
|
||||
g_list_free_full(source_files, g_free);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void fill_find_tags_array(GPtrArray *dst, const GPtrArray *src,
|
||||
const char *name, const char *scope, TMTagType type, TMParserType lang)
|
||||
|
||||
@ -2,11 +2,9 @@ I1_E1
|
||||
enumerator: anon_enum_1 :: I1_E1
|
||||
I1_E2Ì4Îanon_enum_1Ö0
|
||||
enumerator: anon_enum_1 :: I1_E2
|
||||
I2_E1Ì4Îanon_enum_2Ö0
|
||||
enumerator: anon_enum_2 :: I2_E1
|
||||
I2_E2Ì4Îanon_enum_2Ö0
|
||||
enumerator: anon_enum_2 :: I2_E2
|
||||
I2_E1Ì4Îanon_enum_1Ö0
|
||||
enumerator: anon_enum_1 :: I2_E1
|
||||
I2_E2Ì4Îanon_enum_1Ö0
|
||||
enumerator: anon_enum_1 :: I2_E2
|
||||
anon_enum_1Ì2Ö1
|
||||
enum: anon_enum_1 flags: 1
|
||||
anon_enum_2Ì2Ö1
|
||||
enum: anon_enum_2 flags: 1
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user