Merge PR#356 from 'b4n/techee/tm'
Huge TagManager improvements
This commit is contained in:
commit
8c77accfd0
@ -778,8 +778,6 @@ INPUT = @top_srcdir@/src/ \
|
||||
@top_srcdir@/plugins/geanyfunctions.h \
|
||||
@top_srcdir@/tagmanager/src/tm_source_file.c \
|
||||
@top_srcdir@/tagmanager/src/tm_source_file.h \
|
||||
@top_srcdir@/tagmanager/src/tm_work_object.c \
|
||||
@top_srcdir@/tagmanager/src/tm_work_object.h \
|
||||
@top_srcdir@/tagmanager/src/tm_workspace.c \
|
||||
@top_srcdir@/tagmanager/src/tm_workspace.h
|
||||
|
||||
|
||||
@ -98,7 +98,6 @@ doxygen_sources = \
|
||||
$(top_srcdir)/plugins/geanyplugin.h \
|
||||
$(top_srcdir)/plugins/geanyfunctions.h \
|
||||
$(top_srcdir)/tagmanager/src/tm_source_file.[ch] \
|
||||
$(top_srcdir)/tagmanager/src/tm_work_object.[ch] \
|
||||
$(top_srcdir)/tagmanager/src/tm_workspace.[ch]
|
||||
|
||||
Doxyfile.stamp: Doxyfile $(doxygen_sources)
|
||||
|
||||
@ -346,14 +346,16 @@
|
||||
geany_functions->p_tm->tm_get_real_path
|
||||
#define tm_source_file_new \
|
||||
geany_functions->p_tm->tm_source_file_new
|
||||
#define tm_workspace_add_object \
|
||||
geany_functions->p_tm->tm_workspace_add_object
|
||||
#define tm_source_file_update \
|
||||
geany_functions->p_tm->tm_source_file_update
|
||||
#define tm_work_object_free \
|
||||
geany_functions->p_tm->tm_work_object_free
|
||||
#define tm_workspace_remove_object \
|
||||
geany_functions->p_tm->tm_workspace_remove_object
|
||||
#define tm_source_file_free \
|
||||
geany_functions->p_tm->tm_source_file_free
|
||||
#define tm_workspace_add_source_file \
|
||||
geany_functions->p_tm->tm_workspace_add_source_file
|
||||
#define tm_workspace_remove_source_file \
|
||||
geany_functions->p_tm->tm_workspace_remove_source_file
|
||||
#define tm_workspace_add_source_files \
|
||||
geany_functions->p_tm->tm_workspace_add_source_files
|
||||
#define tm_workspace_remove_source_files \
|
||||
geany_functions->p_tm->tm_workspace_remove_source_files
|
||||
#define search_show_find_in_files_dialog \
|
||||
geany_functions->p_search->search_show_find_in_files_dialog
|
||||
#define highlighting_get_style \
|
||||
|
||||
@ -501,9 +501,13 @@ static gboolean handle_save_as(const gchar *utf8_filename, gboolean rename_file)
|
||||
{
|
||||
document_rename_file(doc, utf8_filename);
|
||||
}
|
||||
/* create a new tm_source_file object otherwise tagmanager won't work correctly */
|
||||
tm_workspace_remove_object(doc->tm_file, TRUE, TRUE);
|
||||
doc->tm_file = NULL;
|
||||
if (doc->tm_file)
|
||||
{
|
||||
/* create a new tm_source_file object otherwise tagmanager won't work correctly */
|
||||
tm_workspace_remove_source_file(doc->tm_file);
|
||||
tm_source_file_free(doc->tm_file);
|
||||
doc->tm_file = NULL;
|
||||
}
|
||||
}
|
||||
success = document_save_file_as(doc, utf8_filename);
|
||||
|
||||
|
||||
@ -140,7 +140,7 @@ static GtkWidget* document_show_message(GeanyDocument *doc, GtkMessageType msgty
|
||||
* string returned by @c tm_get_real_path().
|
||||
*
|
||||
* @return The matching document, or @c NULL.
|
||||
* @note This is only really useful when passing a @c TMWorkObject::file_name.
|
||||
* @note This is only really useful when passing a @c TMSourceFile::file_name.
|
||||
* @see GeanyDocument::real_path.
|
||||
* @see document_find_by_filename().
|
||||
*
|
||||
@ -714,7 +714,11 @@ static gboolean remove_page(guint page_num)
|
||||
g_free(doc->priv->saved_encoding.encoding);
|
||||
g_free(doc->file_name);
|
||||
g_free(doc->real_path);
|
||||
tm_workspace_remove_object(doc->tm_file, TRUE, !main_status.quitting);
|
||||
if (doc->tm_file)
|
||||
{
|
||||
tm_workspace_remove_source_file(doc->tm_file);
|
||||
tm_source_file_free(doc->tm_file);
|
||||
}
|
||||
|
||||
if (doc->priv->tag_tree)
|
||||
gtk_widget_destroy(doc->priv->tag_tree);
|
||||
@ -2483,17 +2487,14 @@ void document_update_tags(GeanyDocument *doc)
|
||||
|
||||
/* lookup the name rather than using filetype name to support custom filetypes */
|
||||
name = tm_source_file_get_lang_name(doc->file_type->lang);
|
||||
doc->tm_file = tm_source_file_new(locale_filename, FALSE, name);
|
||||
doc->tm_file = tm_source_file_new(locale_filename, name);
|
||||
g_free(locale_filename);
|
||||
|
||||
if (doc->tm_file && !tm_workspace_add_object(doc->tm_file))
|
||||
{
|
||||
tm_work_object_free(doc->tm_file);
|
||||
doc->tm_file = NULL;
|
||||
}
|
||||
if (doc->tm_file)
|
||||
tm_workspace_add_source_file_noupdate(doc->tm_file);
|
||||
}
|
||||
|
||||
/* early out if there's no work object and we couldn't create one */
|
||||
/* early out if there's no tm source file and we couldn't create one */
|
||||
if (doc->tm_file == NULL)
|
||||
{
|
||||
/* We must call sidebar_update_tag_list() before returning,
|
||||
@ -2503,20 +2504,11 @@ void document_update_tags(GeanyDocument *doc)
|
||||
return;
|
||||
}
|
||||
|
||||
len = sci_get_length(doc->editor->sci);
|
||||
/* tm_source_file_buffer_update() below don't support 0-length data,
|
||||
* so just empty the tags array and leave */
|
||||
if (len < 1)
|
||||
{
|
||||
tm_tags_array_free(doc->tm_file->tags_array, FALSE);
|
||||
sidebar_update_tag_list(doc, FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Parse Scintilla's buffer directly using TagManager
|
||||
* Note: this buffer *MUST NOT* be modified */
|
||||
len = sci_get_length(doc->editor->sci);
|
||||
buffer_ptr = (guchar *) scintilla_send_message(doc->editor->sci, SCI_GETCHARACTERPOINTER, 0, 0);
|
||||
tm_source_file_buffer_update(doc->tm_file, buffer_ptr, len, TRUE);
|
||||
tm_workspace_update_source_file_buffer(doc->tm_file, buffer_ptr, len);
|
||||
|
||||
sidebar_update_tag_list(doc, TRUE);
|
||||
document_highlight_tags(doc);
|
||||
@ -2555,13 +2547,12 @@ void document_highlight_tags(GeanyDocument *doc)
|
||||
default:
|
||||
return; /* early out if type keywords are not supported */
|
||||
}
|
||||
if (!app->tm_workspace->work_object.tags_array)
|
||||
if (!app->tm_workspace->tags_array)
|
||||
return;
|
||||
|
||||
/* get any type keywords and tell scintilla about them
|
||||
* this will cause the type keywords to be colourized in scintilla */
|
||||
keywords_str = symbols_find_tags_as_string(app->tm_workspace->work_object.tags_array,
|
||||
TM_GLOBAL_TYPE_MASK, doc->file_type->lang);
|
||||
keywords_str = symbols_find_typenames_as_string(doc->file_type->lang, FALSE);
|
||||
if (keywords_str)
|
||||
{
|
||||
keywords = g_string_free(keywords_str, FALSE);
|
||||
@ -2617,7 +2608,8 @@ static void document_load_config(GeanyDocument *doc, GeanyFiletype *type,
|
||||
/* delete tm file object to force creation of a new one */
|
||||
if (doc->tm_file != NULL)
|
||||
{
|
||||
tm_workspace_remove_object(doc->tm_file, TRUE, TRUE);
|
||||
tm_workspace_remove_source_file(doc->tm_file);
|
||||
tm_source_file_free(doc->tm_file);
|
||||
doc->tm_file = NULL;
|
||||
}
|
||||
/* load tags files before highlighting (some lexers highlight global typenames) */
|
||||
|
||||
@ -93,8 +93,8 @@ typedef struct GeanyDocument
|
||||
/** The filetype for this document, it's only a reference to one of the elements of the global
|
||||
* filetypes array. */
|
||||
GeanyFiletype *file_type;
|
||||
/** TMWorkObject object for this document, or @c NULL. */
|
||||
TMWorkObject *tm_file;
|
||||
/** TMSourceFile object for this document, or @c NULL. */
|
||||
TMSourceFile *tm_file;
|
||||
/** Whether this document is read-only. */
|
||||
gboolean readonly;
|
||||
/** Whether this document has been changed since it was last saved. */
|
||||
|
||||
32
src/editor.c
32
src/editor.c
@ -639,7 +639,7 @@ static void show_tags_list(GeanyEditor *editor, const GPtrArray *tags, gsize roo
|
||||
g_string_append(words, tag->name);
|
||||
|
||||
/* for now, tag types don't all follow C, so just look at arglist */
|
||||
if (!EMPTY(tag->atts.entry.arglist))
|
||||
if (!EMPTY(tag->arglist))
|
||||
g_string_append(words, "?2");
|
||||
else
|
||||
g_string_append(words, "?1");
|
||||
@ -732,10 +732,10 @@ static void autocomplete_scope(GeanyEditor *editor)
|
||||
return;
|
||||
|
||||
tag = g_ptr_array_index(tags, 0);
|
||||
name = tag->atts.entry.var_type;
|
||||
name = tag->var_type;
|
||||
if (name)
|
||||
{
|
||||
TMWorkObject *obj = editor->document->tm_file;
|
||||
TMSourceFile *obj = editor->document->tm_file;
|
||||
|
||||
tags = tm_workspace_find_scope_members(obj ? obj->tags_array : NULL,
|
||||
name, TRUE, FALSE);
|
||||
@ -1784,43 +1784,43 @@ static gint find_start_bracket(ScintillaObject *sci, gint pos)
|
||||
|
||||
static gboolean append_calltip(GString *str, const TMTag *tag, filetype_id ft_id)
|
||||
{
|
||||
if (! tag->atts.entry.arglist)
|
||||
if (! tag->arglist)
|
||||
return FALSE;
|
||||
|
||||
if (ft_id != GEANY_FILETYPES_PASCAL)
|
||||
{ /* usual calltips: "retval tagname (arglist)" */
|
||||
if (tag->atts.entry.var_type)
|
||||
if (tag->var_type)
|
||||
{
|
||||
guint i;
|
||||
|
||||
g_string_append(str, tag->atts.entry.var_type);
|
||||
for (i = 0; i < tag->atts.entry.pointerOrder; i++)
|
||||
g_string_append(str, tag->var_type);
|
||||
for (i = 0; i < tag->pointerOrder; i++)
|
||||
{
|
||||
g_string_append_c(str, '*');
|
||||
}
|
||||
g_string_append_c(str, ' ');
|
||||
}
|
||||
if (tag->atts.entry.scope)
|
||||
if (tag->scope)
|
||||
{
|
||||
const gchar *cosep = symbols_get_context_separator(ft_id);
|
||||
|
||||
g_string_append(str, tag->atts.entry.scope);
|
||||
g_string_append(str, tag->scope);
|
||||
g_string_append(str, cosep);
|
||||
}
|
||||
g_string_append(str, tag->name);
|
||||
g_string_append_c(str, ' ');
|
||||
g_string_append(str, tag->atts.entry.arglist);
|
||||
g_string_append(str, tag->arglist);
|
||||
}
|
||||
else
|
||||
{ /* special case Pascal calltips: "tagname (arglist) : retval" */
|
||||
g_string_append(str, tag->name);
|
||||
g_string_append_c(str, ' ');
|
||||
g_string_append(str, tag->atts.entry.arglist);
|
||||
g_string_append(str, tag->arglist);
|
||||
|
||||
if (!EMPTY(tag->atts.entry.var_type))
|
||||
if (!EMPTY(tag->var_type))
|
||||
{
|
||||
g_string_append(str, " : ");
|
||||
g_string_append(str, tag->atts.entry.var_type);
|
||||
g_string_append(str, tag->var_type);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1831,7 +1831,7 @@ static gboolean append_calltip(GString *str, const TMTag *tag, filetype_id ft_id
|
||||
static gchar *find_calltip(const gchar *word, GeanyFiletype *ft)
|
||||
{
|
||||
const GPtrArray *tags;
|
||||
const gint arg_types = tm_tag_function_t | tm_tag_prototype_t |
|
||||
const TMTagType arg_types = tm_tag_function_t | tm_tag_prototype_t |
|
||||
tm_tag_method_t | tm_tag_macro_with_arg_t;
|
||||
TMTagAttrType *attrs = NULL;
|
||||
TMTag *tag;
|
||||
@ -1862,7 +1862,7 @@ static gchar *find_calltip(const gchar *word, GeanyFiletype *ft)
|
||||
{
|
||||
tag = TM_TAG(tags->pdata[i]);
|
||||
|
||||
if (! tag->atts.entry.arglist)
|
||||
if (! tag->arglist)
|
||||
tags->pdata[i] = NULL;
|
||||
}
|
||||
tm_tags_prune((GPtrArray *) tags);
|
||||
@ -1873,7 +1873,7 @@ static gchar *find_calltip(const gchar *word, GeanyFiletype *ft)
|
||||
TMTagAttrType sort_attr[] = {tm_tag_attr_name_t, tm_tag_attr_scope_t,
|
||||
tm_tag_attr_arglist_t, 0};
|
||||
|
||||
tm_tags_sort((GPtrArray *) tags, sort_attr, TRUE);
|
||||
tm_tags_sort((GPtrArray *) tags, sort_attr, TRUE, FALSE);
|
||||
}
|
||||
|
||||
/* if the current word has changed since last time, start with the first tag match */
|
||||
|
||||
@ -433,23 +433,6 @@ void highlighting_free_styles(void)
|
||||
}
|
||||
|
||||
|
||||
static GString *get_global_typenames(gint lang)
|
||||
{
|
||||
GString *s = NULL;
|
||||
|
||||
if (app->tm_workspace)
|
||||
{
|
||||
GPtrArray *tags_array = app->tm_workspace->global_tags;
|
||||
|
||||
if (tags_array)
|
||||
{
|
||||
s = symbols_find_tags_as_string(tags_array, TM_GLOBAL_TYPE_MASK, lang);
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
static gchar*
|
||||
get_keyfile_whitespace_chars(GKeyFile *config, GKeyFile *configh)
|
||||
{
|
||||
@ -823,7 +806,7 @@ static void merge_type_keywords(ScintillaObject *sci, guint ft_id, guint keyword
|
||||
const gchar *user_words = style_sets[ft_id].keywords[keyword_idx];
|
||||
GString *s;
|
||||
|
||||
s = get_global_typenames(filetypes[ft_id]->lang);
|
||||
s = symbols_find_typenames_as_string(filetypes[ft_id]->lang, TRUE);
|
||||
if (G_UNLIKELY(s == NULL))
|
||||
s = g_string_sized_new(200);
|
||||
else
|
||||
|
||||
@ -1289,7 +1289,7 @@ static void do_main_quit(void)
|
||||
filetypes_free_types();
|
||||
log_finalize();
|
||||
|
||||
tm_workspace_free(TM_WORK_OBJECT(app->tm_workspace));
|
||||
tm_workspace_free();
|
||||
g_free(app->configdir);
|
||||
g_free(app->datadir);
|
||||
g_free(app->docdir);
|
||||
|
||||
@ -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 220
|
||||
#define GEANY_API_VERSION 221
|
||||
|
||||
/* hack to have a different ABI when built with GTK3 because loading GTK2-linked plugins
|
||||
* with GTK3-linked Geany leads to crash */
|
||||
@ -72,7 +72,7 @@ G_BEGIN_DECLS
|
||||
* Changing this forces all plugins to be recompiled before Geany can load them. */
|
||||
/* This should usually stay the same if fields are only appended, assuming only pointers to
|
||||
* structs and not structs themselves are declared by plugins. */
|
||||
#define GEANY_ABI_VERSION (69 << GEANY_ABI_SHIFT)
|
||||
#define GEANY_ABI_VERSION (70 << GEANY_ABI_SHIFT)
|
||||
|
||||
|
||||
/** Defines a function to check the plugin is safe to load.
|
||||
@ -599,12 +599,12 @@ SearchFuncs;
|
||||
typedef struct TagManagerFuncs
|
||||
{
|
||||
gchar* (*tm_get_real_path) (const gchar *file_name);
|
||||
TMWorkObject* (*tm_source_file_new) (const char *file_name, gboolean update, const char *name);
|
||||
gboolean (*tm_workspace_add_object) (TMWorkObject *work_object);
|
||||
gboolean (*tm_source_file_update) (TMWorkObject *source_file, gboolean force,
|
||||
gboolean recurse, gboolean update_parent);
|
||||
void (*tm_work_object_free) (gpointer work_object);
|
||||
gboolean (*tm_workspace_remove_object) (TMWorkObject *w, gboolean do_free, gboolean update);
|
||||
TMSourceFile* (*tm_source_file_new) (const char *file_name, const char *name);
|
||||
void (*tm_source_file_free) (TMSourceFile *source_file);
|
||||
void (*tm_workspace_add_source_file) (TMSourceFile *source_file);
|
||||
void (*tm_workspace_remove_source_file) (TMSourceFile *source_file);
|
||||
void (*tm_workspace_add_source_files) (GPtrArray *source_files);
|
||||
void (*tm_workspace_remove_source_files) (GPtrArray *source_files);
|
||||
}
|
||||
TagManagerFuncs;
|
||||
|
||||
|
||||
@ -290,10 +290,11 @@ static KeybindingFuncs keybindings_funcs = {
|
||||
static TagManagerFuncs tagmanager_funcs = {
|
||||
&tm_get_real_path,
|
||||
&tm_source_file_new,
|
||||
&tm_workspace_add_object,
|
||||
&tm_source_file_update,
|
||||
&tm_work_object_free,
|
||||
&tm_workspace_remove_object
|
||||
&tm_source_file_free,
|
||||
&tm_workspace_add_source_file,
|
||||
&tm_workspace_remove_source_file,
|
||||
&tm_workspace_add_source_files,
|
||||
&tm_workspace_remove_source_files
|
||||
};
|
||||
|
||||
static SearchFuncs search_funcs = {
|
||||
|
||||
@ -904,7 +904,7 @@ static gboolean taglist_go_to_selection(GtkTreeSelection *selection, guint keyva
|
||||
if (! tag)
|
||||
return FALSE;
|
||||
|
||||
line = tag->atts.entry.line;
|
||||
line = tag->line;
|
||||
if (line > 0)
|
||||
{
|
||||
GeanyDocument *doc = document_get_current();
|
||||
|
||||
129
src/symbols.c
129
src/symbols.c
@ -64,11 +64,6 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
const guint TM_GLOBAL_TYPE_MASK =
|
||||
tm_tag_class_t | tm_tag_enum_t | tm_tag_interface_t |
|
||||
tm_tag_struct_t | tm_tag_typedef_t | tm_tag_union_t | tm_tag_namespace_t;
|
||||
|
||||
|
||||
static gchar **html_entities = NULL;
|
||||
|
||||
typedef struct
|
||||
@ -248,7 +243,7 @@ static void html_tags_loaded(void)
|
||||
}
|
||||
|
||||
|
||||
GString *symbols_find_tags_as_string(GPtrArray *tags_array, guint tag_types, gint lang)
|
||||
GString *symbols_find_typenames_as_string(gint lang, gboolean global)
|
||||
{
|
||||
guint j;
|
||||
TMTag *tag;
|
||||
@ -256,9 +251,10 @@ GString *symbols_find_tags_as_string(GPtrArray *tags_array, guint tag_types, gin
|
||||
GPtrArray *typedefs;
|
||||
gint tag_lang;
|
||||
|
||||
g_return_val_if_fail(tags_array != NULL, NULL);
|
||||
|
||||
typedefs = tm_tags_extract(tags_array, tag_types);
|
||||
if (global)
|
||||
typedefs = tm_tags_extract(app->tm_workspace->global_tags, TM_GLOBAL_TYPE_MASK);
|
||||
else
|
||||
typedefs = app->tm_workspace->typename_array;
|
||||
|
||||
if ((typedefs) && (typedefs->len > 0))
|
||||
{
|
||||
@ -266,9 +262,7 @@ GString *symbols_find_tags_as_string(GPtrArray *tags_array, guint tag_types, gin
|
||||
for (j = 0; j < typedefs->len; ++j)
|
||||
{
|
||||
tag = TM_TAG(typedefs->pdata[j]);
|
||||
/* tag->atts.file.lang contains (for some reason) the line of the tag if
|
||||
* tag->atts.entry.file is not NULL */
|
||||
tag_lang = (tag->atts.entry.file) ? tag->atts.entry.file->lang : tag->atts.file.lang;
|
||||
tag_lang = tag->lang;
|
||||
|
||||
/* the check for tag_lang == lang is necessary to avoid wrong type colouring of
|
||||
* e.g. PHP classes in C++ files
|
||||
@ -282,7 +276,7 @@ GString *symbols_find_tags_as_string(GPtrArray *tags_array, guint tag_types, gin
|
||||
}
|
||||
}
|
||||
}
|
||||
if (typedefs)
|
||||
if (typedefs && global)
|
||||
g_ptr_array_free(typedefs, TRUE);
|
||||
return s;
|
||||
}
|
||||
@ -333,25 +327,25 @@ GString *symbols_get_macro_list(gint lang)
|
||||
gint tag_lang;
|
||||
TMTag *tag;
|
||||
|
||||
if (app->tm_workspace->work_objects == NULL)
|
||||
if (app->tm_workspace->source_files == NULL)
|
||||
return NULL;
|
||||
|
||||
ftags = g_ptr_array_sized_new(50);
|
||||
words = g_string_sized_new(200);
|
||||
|
||||
for (j = 0; j < app->tm_workspace->work_objects->len; j++)
|
||||
for (j = 0; j < app->tm_workspace->source_files->len; j++)
|
||||
{
|
||||
GPtrArray *tags;
|
||||
|
||||
tags = tm_tags_extract(TM_WORK_OBJECT(app->tm_workspace->work_objects->pdata[j])->tags_array,
|
||||
tags = tm_tags_extract(TM_SOURCE_FILE(app->tm_workspace->source_files->pdata[j])->tags_array,
|
||||
tm_tag_enum_t | tm_tag_variable_t | tm_tag_macro_t | tm_tag_macro_with_arg_t);
|
||||
if (NULL != tags)
|
||||
{
|
||||
for (i = 0; ((i < tags->len) && (i < editor_prefs.autocompletion_max_entries)); ++i)
|
||||
{
|
||||
tag = TM_TAG(tags->pdata[i]);
|
||||
tag_lang = (tag->atts.entry.file) ?
|
||||
tag->atts.entry.file->lang : tag->atts.file.lang;
|
||||
tag_lang = (tag->file) ?
|
||||
tag->file->lang : tag->lang;
|
||||
|
||||
if (tag_lang == lang)
|
||||
g_ptr_array_add(ftags, (gpointer) tags->pdata[i]);
|
||||
@ -367,7 +361,7 @@ GString *symbols_get_macro_list(gint lang)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tm_tags_sort(ftags, NULL, FALSE);
|
||||
tm_tags_sort(ftags, NULL, FALSE, FALSE);
|
||||
for (j = 0; j < ftags->len; j++)
|
||||
{
|
||||
if (j > 0)
|
||||
@ -395,24 +389,21 @@ symbols_find_tm_tag(const GPtrArray *tags, const gchar *tag_name)
|
||||
}
|
||||
|
||||
|
||||
static TMTag *find_work_object_tag(const TMWorkObject *workobj,
|
||||
static TMTag *find_source_file_tag(GPtrArray *tags_array,
|
||||
const gchar *tag_name, guint type)
|
||||
{
|
||||
GPtrArray *tags;
|
||||
TMTag *tmtag;
|
||||
|
||||
if (G_LIKELY(workobj != NULL))
|
||||
tags = tm_tags_extract(tags_array, type);
|
||||
if (tags != NULL)
|
||||
{
|
||||
tags = tm_tags_extract(workobj->tags_array, type);
|
||||
if (tags != NULL)
|
||||
{
|
||||
tmtag = symbols_find_tm_tag(tags, tag_name);
|
||||
tmtag = symbols_find_tm_tag(tags, tag_name);
|
||||
|
||||
g_ptr_array_free(tags, TRUE);
|
||||
g_ptr_array_free(tags, TRUE);
|
||||
|
||||
if (tmtag != NULL)
|
||||
return tmtag;
|
||||
}
|
||||
if (tmtag != NULL)
|
||||
return tmtag;
|
||||
}
|
||||
return NULL; /* not found */
|
||||
}
|
||||
@ -421,19 +412,19 @@ static TMTag *find_work_object_tag(const TMWorkObject *workobj,
|
||||
static TMTag *find_workspace_tag(const gchar *tag_name, guint type)
|
||||
{
|
||||
guint j;
|
||||
const GPtrArray *work_objects = NULL;
|
||||
const GPtrArray *source_files = NULL;
|
||||
|
||||
if (app->tm_workspace != NULL)
|
||||
work_objects = app->tm_workspace->work_objects;
|
||||
source_files = app->tm_workspace->source_files;
|
||||
|
||||
if (work_objects != NULL)
|
||||
if (source_files != NULL)
|
||||
{
|
||||
for (j = 0; j < work_objects->len; j++)
|
||||
for (j = 0; j < source_files->len; j++)
|
||||
{
|
||||
TMWorkObject *workobj = TM_WORK_OBJECT(work_objects->pdata[j]);
|
||||
TMSourceFile *srcfile = source_files->pdata[j];
|
||||
TMTag *tmtag;
|
||||
|
||||
tmtag = find_work_object_tag(workobj, tag_name, type);
|
||||
tmtag = find_source_file_tag(srcfile->tags_array, tag_name, type);
|
||||
if (tmtag != NULL)
|
||||
return tmtag;
|
||||
}
|
||||
@ -468,7 +459,7 @@ static gint compare_symbol(const TMTag *tag_a, const TMTag *tag_b)
|
||||
ret = strcmp(tag_a->name, tag_b->name);
|
||||
if (ret == 0)
|
||||
{
|
||||
return tag_a->atts.entry.line - tag_b->atts.entry.line;
|
||||
return tag_a->line - tag_b->line;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -484,21 +475,21 @@ static gint compare_symbol_lines(gconstpointer a, gconstpointer b)
|
||||
if (a == NULL || b == NULL)
|
||||
return 0;
|
||||
|
||||
ret = tag_a->atts.entry.line - tag_b->atts.entry.line;
|
||||
ret = tag_a->line - tag_b->line;
|
||||
if (ret == 0)
|
||||
{
|
||||
if (tag_a->atts.entry.scope == NULL)
|
||||
return -(tag_a->atts.entry.scope != tag_b->atts.entry.scope);
|
||||
if (tag_b->atts.entry.scope == NULL)
|
||||
return tag_a->atts.entry.scope != tag_b->atts.entry.scope;
|
||||
if (tag_a->scope == NULL)
|
||||
return -(tag_a->scope != tag_b->scope);
|
||||
if (tag_b->scope == NULL)
|
||||
return tag_a->scope != tag_b->scope;
|
||||
else
|
||||
return strcmp(tag_a->atts.entry.scope, tag_b->atts.entry.scope);
|
||||
return strcmp(tag_a->scope, tag_b->scope);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static GList *get_tag_list(GeanyDocument *doc, guint tag_types)
|
||||
static GList *get_tag_list(GeanyDocument *doc, TMTagType tag_types)
|
||||
{
|
||||
GList *tag_names = NULL;
|
||||
TMTag *tag;
|
||||
@ -1037,7 +1028,7 @@ static void hide_empty_rows(GtkTreeStore *store)
|
||||
static const gchar *get_symbol_name(GeanyDocument *doc, const TMTag *tag, gboolean found_parent)
|
||||
{
|
||||
gchar *utf8_name;
|
||||
const gchar *scope = tag->atts.entry.scope;
|
||||
const gchar *scope = tag->scope;
|
||||
static GString *buffer = NULL; /* buffer will be small so we can keep it for reuse */
|
||||
gboolean doc_is_utf8 = FALSE;
|
||||
|
||||
@ -1078,7 +1069,7 @@ static const gchar *get_symbol_name(GeanyDocument *doc, const TMTag *tag, gboole
|
||||
if (! doc_is_utf8)
|
||||
g_free(utf8_name);
|
||||
|
||||
g_string_append_printf(buffer, " [%lu]", tag->atts.entry.line);
|
||||
g_string_append_printf(buffer, " [%lu]", tag->line);
|
||||
|
||||
return buffer->str;
|
||||
}
|
||||
@ -1108,7 +1099,7 @@ static gchar *get_symbol_tooltip(GeanyDocument *doc, const TMTag *tag)
|
||||
/* find the last word in "foo::bar::blah", e.g. "blah" */
|
||||
static const gchar *get_parent_name(const TMTag *tag, filetype_id ft_id)
|
||||
{
|
||||
const gchar *scope = tag->atts.entry.scope;
|
||||
const gchar *scope = tag->scope;
|
||||
const gchar *separator = symbols_get_context_separator(ft_id);
|
||||
const gchar *str, *ptr;
|
||||
|
||||
@ -1226,9 +1217,9 @@ static gboolean tag_equal(gconstpointer v1, gconstpointer v2)
|
||||
const TMTag *t2 = v2;
|
||||
|
||||
return (t1->type == t2->type && strcmp(t1->name, t2->name) == 0 &&
|
||||
utils_str_equal(t1->atts.entry.scope, t2->atts.entry.scope) &&
|
||||
utils_str_equal(t1->scope, t2->scope) &&
|
||||
/* include arglist in match to support e.g. C++ overloading */
|
||||
utils_str_equal(t1->atts.entry.arglist, t2->atts.entry.arglist));
|
||||
utils_str_equal(t1->arglist, t2->arglist));
|
||||
}
|
||||
|
||||
|
||||
@ -1242,15 +1233,15 @@ static guint tag_hash(gconstpointer v)
|
||||
h = (h << 5) + h + tag->type;
|
||||
for (p = tag->name; *p != '\0'; p++)
|
||||
h = (h << 5) + h + *p;
|
||||
if (tag->atts.entry.scope)
|
||||
if (tag->scope)
|
||||
{
|
||||
for (p = tag->atts.entry.scope; *p != '\0'; p++)
|
||||
for (p = tag->scope; *p != '\0'; p++)
|
||||
h = (h << 5) + h + *p;
|
||||
}
|
||||
/* for e.g. C++ overloading */
|
||||
if (tag->atts.entry.arglist)
|
||||
if (tag->arglist)
|
||||
{
|
||||
for (p = tag->atts.entry.arglist; *p != '\0'; p++)
|
||||
for (p = tag->arglist; *p != '\0'; p++)
|
||||
h = (h << 5) + h + *p;
|
||||
}
|
||||
|
||||
@ -1348,7 +1339,7 @@ static GList *tags_table_lookup(GHashTable *table, TMTag *tag)
|
||||
glong delta;
|
||||
data = node->data;
|
||||
|
||||
#define TAG_DELTA(a, b) ABS((glong) TM_TAG(a)->atts.entry.line - (glong) TM_TAG(b)->atts.entry.line)
|
||||
#define TAG_DELTA(a, b) ABS((glong) TM_TAG(a)->line - (glong) TM_TAG(b)->line)
|
||||
|
||||
delta = TAG_DELTA(((GList *) node->data)->data, tag);
|
||||
for (node = node->next; node; node = node->next)
|
||||
@ -1542,7 +1533,7 @@ static void update_tree_tags(GeanyDocument *doc, GList **tags)
|
||||
gtk_tree_model_get(GTK_TREE_MODEL(store), node->data,
|
||||
SYMBOLS_COLUMN_TAG, &parent_tag, -1);
|
||||
|
||||
d = tag->atts.entry.line - parent_tag->atts.entry.line;
|
||||
d = tag->line - parent_tag->line;
|
||||
if (! parent_search || (d >= 0 && d < delta))
|
||||
{
|
||||
delta = d;
|
||||
@ -1616,7 +1607,7 @@ static gboolean tag_has_missing_parent(const TMTag *tag, GtkTreeStore *store,
|
||||
GtkTreeIter *iter)
|
||||
{
|
||||
/* if the tag has a parent tag, it should be at depth >= 2 */
|
||||
return !EMPTY(tag->atts.entry.scope) &&
|
||||
return !EMPTY(tag->scope) &&
|
||||
gtk_tree_store_iter_depth(store, iter) == 1;
|
||||
}
|
||||
|
||||
@ -1666,7 +1657,7 @@ static gint tree_sort_func(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b,
|
||||
if (tag_a && tag_b)
|
||||
if (!sort_by_name ||
|
||||
(utils_str_equal(tag_a->name, tag_b->name) &&
|
||||
utils_str_equal(tag_a->atts.entry.scope, tag_b->atts.entry.scope)))
|
||||
utils_str_equal(tag_a->scope, tag_b->scope)))
|
||||
cmp = compare_symbol_lines(tag_a, tag_b);
|
||||
}
|
||||
}
|
||||
@ -1931,8 +1922,8 @@ static void load_user_tags(filetype_id ft_id)
|
||||
|
||||
static gboolean goto_tag(const gchar *name, gboolean definition)
|
||||
{
|
||||
const gint forward_types = tm_tag_prototype_t | tm_tag_externvar_t;
|
||||
guint type;
|
||||
const TMTagType forward_types = tm_tag_prototype_t | tm_tag_externvar_t;
|
||||
TMTagType type;
|
||||
TMTag *tmtag = NULL;
|
||||
GeanyDocument *old_doc = document_get_current();
|
||||
|
||||
@ -1941,7 +1932,7 @@ static gboolean goto_tag(const gchar *name, gboolean definition)
|
||||
|
||||
/* first look in the current document */
|
||||
if (old_doc != NULL && old_doc->tm_file)
|
||||
tmtag = find_work_object_tag(old_doc->tm_file, name, type);
|
||||
tmtag = find_source_file_tag(old_doc->tm_file->tags_array, name, type);
|
||||
|
||||
/* if not found, look in the workspace */
|
||||
if (tmtag == NULL)
|
||||
@ -1950,13 +1941,13 @@ static gboolean goto_tag(const gchar *name, gboolean definition)
|
||||
if (tmtag != NULL)
|
||||
{
|
||||
GeanyDocument *new_doc = document_find_by_real_path(
|
||||
tmtag->atts.entry.file->work_object.file_name);
|
||||
tmtag->file->file_name);
|
||||
|
||||
if (new_doc)
|
||||
{
|
||||
/* If we are already on the tag line, swap definition/declaration */
|
||||
if (new_doc == old_doc &&
|
||||
tmtag->atts.entry.line == (guint)sci_get_current_line(old_doc->editor->sci) + 1)
|
||||
tmtag->line == (guint)sci_get_current_line(old_doc->editor->sci) + 1)
|
||||
{
|
||||
if (goto_tag(name, !definition))
|
||||
return TRUE;
|
||||
@ -1965,10 +1956,10 @@ static gboolean goto_tag(const gchar *name, gboolean definition)
|
||||
else
|
||||
{
|
||||
/* not found in opened document, should open */
|
||||
new_doc = document_open_file(tmtag->atts.entry.file->work_object.file_name, FALSE, NULL, NULL);
|
||||
new_doc = document_open_file(tmtag->file->file_name, FALSE, NULL, NULL);
|
||||
}
|
||||
|
||||
if (navqueue_goto_line(old_doc, new_doc, tmtag->atts.entry.line))
|
||||
if (navqueue_goto_line(old_doc, new_doc, tmtag->line))
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
@ -2122,7 +2113,7 @@ static gint get_fold_header_after(ScintillaObject *sci, gint line)
|
||||
}
|
||||
|
||||
|
||||
static gint get_current_tag_name(GeanyDocument *doc, gchar **tagname, guint tag_types)
|
||||
static gint get_current_tag_name(GeanyDocument *doc, gchar **tagname, TMTagType tag_types)
|
||||
{
|
||||
gint line;
|
||||
gint parent;
|
||||
@ -2137,7 +2128,7 @@ static gint get_current_tag_name(GeanyDocument *doc, gchar **tagname, guint tag_
|
||||
|
||||
if (tag)
|
||||
{
|
||||
gint tag_line = tag->atts.entry.line - 1;
|
||||
gint tag_line = tag->line - 1;
|
||||
gint last_child = line + 1;
|
||||
|
||||
/* if it may be a false positive because we're inside a fold level not inside anything
|
||||
@ -2152,8 +2143,8 @@ static gint get_current_tag_name(GeanyDocument *doc, gchar **tagname, guint tag_
|
||||
|
||||
if (line <= last_child)
|
||||
{
|
||||
if (tag->atts.entry.scope)
|
||||
*tagname = g_strconcat(tag->atts.entry.scope,
|
||||
if (tag->scope)
|
||||
*tagname = g_strconcat(tag->scope,
|
||||
symbols_get_context_separator(doc->file_type->id), tag->name, NULL);
|
||||
else
|
||||
*tagname = g_strdup(tag->name);
|
||||
@ -2199,7 +2190,7 @@ static gint get_current_tag_name(GeanyDocument *doc, gchar **tagname, guint tag_
|
||||
}
|
||||
|
||||
|
||||
static gint get_current_tag_name_cached(GeanyDocument *doc, const gchar **tagname, guint tag_types)
|
||||
static gint get_current_tag_name_cached(GeanyDocument *doc, const gchar **tagname, TMTagType tag_types)
|
||||
{
|
||||
static gint tag_line = -1;
|
||||
static gchar *cur_tag = NULL;
|
||||
@ -2245,7 +2236,7 @@ gint symbols_get_current_function(GeanyDocument *doc, const gchar **tagname)
|
||||
/* same as symbols_get_current_function() but finds class, namespaces and more */
|
||||
gint symbols_get_current_scope(GeanyDocument *doc, const gchar **tagname)
|
||||
{
|
||||
guint tag_types = (tm_tag_function_t | tm_tag_method_t | tm_tag_class_t |
|
||||
TMTagType tag_types = (tm_tag_function_t | tm_tag_method_t | tm_tag_class_t |
|
||||
tm_tag_struct_t | tm_tag_enum_t | tm_tag_union_t);
|
||||
|
||||
/* Python parser reports imports as namespaces which confuses the scope detection */
|
||||
|
||||
@ -34,8 +34,6 @@ const gchar *symbols_get_context_separator(gint ft_id);
|
||||
|
||||
#ifdef GEANY_PRIVATE
|
||||
|
||||
extern const guint TM_GLOBAL_TYPE_MASK;
|
||||
|
||||
enum
|
||||
{
|
||||
SYMBOLS_SORT_BY_NAME,
|
||||
@ -52,7 +50,7 @@ void symbols_reload_config_files(void);
|
||||
|
||||
void symbols_global_tags_loaded(guint file_type_idx);
|
||||
|
||||
GString *symbols_find_tags_as_string(GPtrArray *tags_array, guint tag_types, gint lang);
|
||||
GString *symbols_find_typenames_as_string(gint lang, gboolean global);
|
||||
|
||||
const GList *symbols_get_tag_list(GeanyDocument *doc, guint tag_types);
|
||||
|
||||
|
||||
@ -298,7 +298,7 @@ extern boolean fileOpen (const char *const fileName, const langType language)
|
||||
* This func is NOT THREAD SAFE.
|
||||
* The user should not tamper with the buffer while this func is executing.
|
||||
*/
|
||||
extern boolean bufferOpen (unsigned char *buffer, int buffer_size,
|
||||
extern boolean bufferOpen (unsigned char *buffer, size_t buffer_size,
|
||||
const char *const fileName, const langType language )
|
||||
{
|
||||
boolean opened = FALSE;
|
||||
|
||||
@ -106,7 +106,7 @@ extern void fileUngetc (int c);
|
||||
extern const unsigned char *fileReadLine (void);
|
||||
extern char *readLine (vString *const vLine, MIO *const mio);
|
||||
extern char *readSourceLine (vString *const vLine, MIOPos location, long *const pSeekValue);
|
||||
extern boolean bufferOpen (unsigned char *buffer, int buffer_size,
|
||||
extern boolean bufferOpen (unsigned char *buffer, size_t buffer_size,
|
||||
const char *const fileName, const langType language );
|
||||
#define bufferClose fileClose
|
||||
|
||||
|
||||
@ -17,20 +17,15 @@ tagmanager_include_HEADERS = \
|
||||
tm_source_file.h \
|
||||
tm_tag.h \
|
||||
tm_tagmanager.h \
|
||||
tm_work_object.h \
|
||||
tm_workspace.h
|
||||
|
||||
|
||||
libtagmanager_a_SOURCES =\
|
||||
tm_tagmanager.h \
|
||||
tm_parser.h \
|
||||
tm_file_entry.h \
|
||||
tm_file_entry.c \
|
||||
tm_source_file.h \
|
||||
tm_source_file.c \
|
||||
tm_tag.h \
|
||||
tm_tag.c \
|
||||
tm_work_object.c \
|
||||
tm_work_object.h \
|
||||
tm_workspace.h \
|
||||
tm_workspace.c
|
||||
|
||||
@ -44,8 +44,7 @@ all: $(COMPLIB)
|
||||
clean:
|
||||
-$(RM) deps.mak *.o $(COMPLIB)
|
||||
|
||||
$(COMPLIB): tm_workspace.o tm_work_object.o tm_source_file.o tm_tag.o \
|
||||
tm_file_entry.o
|
||||
$(COMPLIB): tm_workspace.o tm_source_file.o tm_tag.o
|
||||
$(AR) rc $@ $^
|
||||
$(RANLIB) $@
|
||||
|
||||
|
||||
@ -1,282 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2001-2002, Biswapesh Chattopadhyay
|
||||
*
|
||||
* This source code is released for free distribution under the terms of the
|
||||
* GNU General Public License.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "general.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#ifdef HAVE_FCNTL_H
|
||||
# include <fcntl.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef HAVE_FNMATCH_H
|
||||
# include <fnmatch.h>
|
||||
#endif
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
#include "tm_work_object.h"
|
||||
#include "tm_file_entry.h"
|
||||
|
||||
|
||||
#define FILE_NEW(T) ((T) = g_slice_new0(TMFileEntry))
|
||||
#define FILE_FREE(T) g_slice_free(TMFileEntry, (T))
|
||||
|
||||
|
||||
void tm_file_entry_print(TMFileEntry *entry, gpointer UNUSED user_data
|
||||
, guint level)
|
||||
{
|
||||
guint i;
|
||||
|
||||
g_return_if_fail(entry);
|
||||
for (i=0; i < level; ++i)
|
||||
fputc('\t', stderr);
|
||||
fprintf(stderr, "%s\n", entry->name);
|
||||
}
|
||||
|
||||
gint tm_file_entry_compare(TMFileEntry *e1, TMFileEntry *e2)
|
||||
{
|
||||
g_return_val_if_fail(e1 && e2 && e1->name && e2->name, 0);
|
||||
#ifdef TM_DEBUG
|
||||
g_message("Comparing %s and %s", e1->name, e2->name);
|
||||
#endif
|
||||
return strcmp(e1->name, e2->name);
|
||||
}
|
||||
|
||||
/* TTimo - modified to handle symlinks */
|
||||
static TMFileType tm_file_entry_type(const char *path)
|
||||
{
|
||||
struct stat s;
|
||||
|
||||
#ifndef G_OS_WIN32
|
||||
if (0 != g_lstat(path, &s))
|
||||
return tm_file_unknown_t;
|
||||
#endif
|
||||
if (S_ISDIR(s.st_mode))
|
||||
return tm_file_dir_t;
|
||||
#ifndef G_OS_WIN32
|
||||
else if (S_ISLNK(s.st_mode))
|
||||
return tm_file_link_t;
|
||||
#endif
|
||||
else if (S_ISREG(s.st_mode))
|
||||
return tm_file_regular_t;
|
||||
else
|
||||
return tm_file_unknown_t;
|
||||
}
|
||||
|
||||
static gboolean apply_filter(const char *name, GList *match, GList *unmatch
|
||||
, gboolean ignore_hidden)
|
||||
{
|
||||
GList *tmp;
|
||||
gboolean matched = (match == NULL);
|
||||
g_return_val_if_fail(name, FALSE);
|
||||
if (ignore_hidden && ('.' == name[0]))
|
||||
return FALSE;
|
||||
/* TTimo - ignore .svn directories */
|
||||
if (!strcmp(name, ".svn"))
|
||||
return FALSE;
|
||||
for (tmp = match; tmp; tmp = g_list_next(tmp))
|
||||
{
|
||||
if (0 == fnmatch((char *) tmp->data, name, 0))
|
||||
{
|
||||
matched = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!matched)
|
||||
return FALSE;
|
||||
for (tmp = unmatch; tmp; tmp = g_list_next(tmp))
|
||||
{
|
||||
if (0 == fnmatch((char *) tmp->data, name, 0))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return matched;
|
||||
}
|
||||
|
||||
TMFileEntry *tm_file_entry_new(const char *path, TMFileEntry *parent
|
||||
, gboolean recurse, GList *file_match, GList *file_unmatch
|
||||
, GList *dir_match, GList *dir_unmatch, gboolean ignore_hidden_files
|
||||
, gboolean ignore_hidden_dirs)
|
||||
{
|
||||
TMFileEntry *entry;
|
||||
/* GList *tmp; */
|
||||
char *real_path;
|
||||
DIR *dir;
|
||||
struct dirent *dir_entry;
|
||||
TMFileEntry *new_entry;
|
||||
char *file_name;
|
||||
struct stat s;
|
||||
char *entries = NULL;
|
||||
|
||||
g_return_val_if_fail (path != NULL, NULL);
|
||||
|
||||
/* TTimo - don't follow symlinks */
|
||||
if (tm_file_entry_type(path) == tm_file_link_t)
|
||||
return NULL;
|
||||
real_path = tm_get_real_path(path);
|
||||
if (!real_path)
|
||||
return NULL;
|
||||
FILE_NEW(entry);
|
||||
entry->type = tm_file_entry_type(real_path);
|
||||
entry->parent = parent;
|
||||
entry->path = real_path;
|
||||
entry->name = strrchr(entry->path, '/');
|
||||
if (entry->name)
|
||||
++ (entry->name);
|
||||
else
|
||||
entry->name = entry->path;
|
||||
switch(entry->type)
|
||||
{
|
||||
case tm_file_unknown_t:
|
||||
g_free(real_path);
|
||||
FILE_FREE(entry);
|
||||
return NULL;
|
||||
case tm_file_link_t:
|
||||
case tm_file_regular_t:
|
||||
if (parent && !apply_filter(entry->name, file_match, file_unmatch
|
||||
, ignore_hidden_files))
|
||||
{
|
||||
tm_file_entry_free(entry);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
case tm_file_dir_t:
|
||||
if (parent && !(recurse && apply_filter(entry->name, dir_match
|
||||
, dir_unmatch, ignore_hidden_dirs)))
|
||||
{
|
||||
tm_file_entry_free(entry);
|
||||
return NULL;
|
||||
}
|
||||
file_name = g_strdup_printf("%s/CVS/Entries", entry->path);
|
||||
if (0 == g_stat(file_name, &s))
|
||||
{
|
||||
if (S_ISREG(s.st_mode))
|
||||
{
|
||||
int fd;
|
||||
entries = g_new(char, s.st_size + 2);
|
||||
if (0 > (fd = open(file_name, O_RDONLY)))
|
||||
{
|
||||
g_free(entries);
|
||||
entries = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
off_t n =0;
|
||||
off_t total_read = 1;
|
||||
while (0 < (n = read(fd, entries + total_read, s.st_size - total_read)))
|
||||
total_read += n;
|
||||
entries[s.st_size] = '\0';
|
||||
entries[0] = '\n';
|
||||
close(fd);
|
||||
entry->version = g_strdup("D");
|
||||
}
|
||||
}
|
||||
}
|
||||
g_free(file_name);
|
||||
if (NULL != (dir = opendir(entry->path)))
|
||||
{
|
||||
while (NULL != (dir_entry = readdir(dir)))
|
||||
{
|
||||
if ((0 == strcmp(dir_entry->d_name, "."))
|
||||
|| (0 == strcmp(dir_entry->d_name, "..")))
|
||||
continue;
|
||||
file_name = g_strdup_printf("%s/%s", entry->path, dir_entry->d_name);
|
||||
new_entry = tm_file_entry_new(file_name, entry, recurse
|
||||
, file_match, file_unmatch, dir_match, dir_unmatch
|
||||
, ignore_hidden_files, ignore_hidden_dirs);
|
||||
g_free(file_name);
|
||||
if (new_entry)
|
||||
{
|
||||
if (entries)
|
||||
{
|
||||
char *str = g_strconcat("\n/", new_entry->name, "/", NULL);
|
||||
char *name_pos = strstr(entries, str);
|
||||
if (NULL != name_pos)
|
||||
{
|
||||
int len = strlen(str);
|
||||
char *version_pos = strchr(name_pos + len, '/');
|
||||
if (NULL != version_pos)
|
||||
{
|
||||
*version_pos = '\0';
|
||||
new_entry->version = g_strdup(name_pos + len);
|
||||
*version_pos = '/';
|
||||
}
|
||||
}
|
||||
g_free(str);
|
||||
}
|
||||
entry->children = g_slist_prepend(entry->children, new_entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
entry->children = g_slist_sort(entry->children, (GCompareFunc) tm_file_entry_compare);
|
||||
g_free(entries);
|
||||
break;
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
void tm_file_entry_free(gpointer entry)
|
||||
{
|
||||
if (entry)
|
||||
{
|
||||
TMFileEntry *file_entry = TM_FILE_ENTRY(entry);
|
||||
if (file_entry->children)
|
||||
{
|
||||
GSList *tmp;
|
||||
for (tmp = file_entry->children; tmp; tmp = g_slist_next(tmp))
|
||||
tm_file_entry_free(tmp->data);
|
||||
g_slist_free(file_entry->children);
|
||||
}
|
||||
g_free(file_entry->version);
|
||||
g_free(file_entry->path);
|
||||
FILE_FREE(file_entry);
|
||||
}
|
||||
}
|
||||
|
||||
void tm_file_entry_foreach(TMFileEntry *entry, TMFileEntryFunc func
|
||||
, gpointer user_data, guint level, gboolean reverse)
|
||||
{
|
||||
g_return_if_fail (entry != NULL);
|
||||
g_return_if_fail (func != NULL);
|
||||
|
||||
if ((reverse) && (entry->children))
|
||||
{
|
||||
GSList *tmp;
|
||||
for (tmp = entry->children; tmp; tmp = g_slist_next(tmp))
|
||||
tm_file_entry_foreach(TM_FILE_ENTRY(tmp->data), func
|
||||
, user_data, level + 1, TRUE);
|
||||
}
|
||||
func(entry, user_data, level);
|
||||
if ((!reverse) && (entry->children))
|
||||
{
|
||||
GSList *tmp;
|
||||
for (tmp = entry->children; tmp; tmp = g_slist_next(tmp))
|
||||
tm_file_entry_foreach(TM_FILE_ENTRY(tmp->data), func
|
||||
, user_data, level + 1, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
GList *tm_file_entry_list(TMFileEntry *entry, GList *files)
|
||||
{
|
||||
GSList *tmp;
|
||||
files = g_list_prepend(files, g_strdup(entry->path));
|
||||
for (tmp = entry->children; tmp; tmp = g_slist_next(tmp))
|
||||
{
|
||||
files = tm_file_entry_list((TMFileEntry *) tmp->data, files);
|
||||
}
|
||||
if (!files)
|
||||
files = g_list_reverse(files);
|
||||
return files;
|
||||
}
|
||||
@ -1,124 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2001-2002, Biswapesh Chattopadhyay
|
||||
*
|
||||
* This source code is released for free distribution under the terms of the
|
||||
* GNU General Public License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TM_FILE_ENTRY_H
|
||||
#define TM_FILE_ENTRY_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
/* \file
|
||||
The TMFileEntry structure and associated functions can be used
|
||||
for file and directory traversal. The following example demonstrates
|
||||
the use of TMFileEntry.
|
||||
\include tm_file_tree_dump.c
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* Enum defining file types */
|
||||
typedef enum
|
||||
{
|
||||
tm_file_unknown_t, /* Unknown file type/file does not exist */
|
||||
tm_file_regular_t, /* Is a regular file */
|
||||
tm_file_dir_t, /* Is a directory */
|
||||
tm_file_link_t /* Is a symbolic link */
|
||||
} TMFileType;
|
||||
|
||||
/*
|
||||
This example demonstrates the use of TMFileEntry and associated functions
|
||||
for managing file hierarchies in a project.
|
||||
|
||||
\example tm_file_tree_dump.c
|
||||
*/
|
||||
|
||||
/* This structure stores the file tree */
|
||||
typedef struct _TMFileEntry
|
||||
{
|
||||
TMFileType type; /* File type */
|
||||
char *path; /* Full path to the file (incl. dir and name) */
|
||||
char *name; /* Just the file name (path minus the directory) */
|
||||
char *version; /* CVS version in case there is a CVS entry for this file */
|
||||
struct _TMFileEntry *parent; /* The parent directory file entry */
|
||||
GSList *children; /* List of children (for directory) */
|
||||
} TMFileEntry;
|
||||
|
||||
/* Prototype for the function that gets called for each entry when
|
||||
tm_file_entry_foreach() is called.
|
||||
*/
|
||||
typedef void (*TMFileEntryFunc) (TMFileEntry *entry, gpointer user_data
|
||||
, guint level);
|
||||
|
||||
/* Convinience casting macro */
|
||||
#define TM_FILE_ENTRY(E) ((TMFileEntry *) (E))
|
||||
|
||||
/* Function that compares two file entries on name and returns the
|
||||
difference
|
||||
*/
|
||||
gint tm_file_entry_compare(TMFileEntry *e1, TMFileEntry *e2);
|
||||
|
||||
/* Function to create a new file entry structure.
|
||||
\param path Path to the file for which the entry is to be created.
|
||||
\param parent Should be NULL for the first call. Since the function calls
|
||||
itself recursively, this parameter is required to build the hierarchy.
|
||||
\param recurse Whether the entry is to be recursively scanned (for
|
||||
directories only)
|
||||
\param file_match List of file name patterns to match. If set to NULL,
|
||||
all files match. You can use wildcards like '*.c'. See the example program
|
||||
for usage.
|
||||
\param file_unmatch Opposite of file_match. All files matching any of the patterns
|
||||
supplied are ignored. If set to NULL, no file is ignored.
|
||||
\param dir_match List of directory name patterns to match. If set to NULL,
|
||||
all directories match. You can use wildcards like '\.*'.
|
||||
\param dir_unmatch Opposite of dir_match. All directories matching any of the
|
||||
patterns supplied are ignored. If set to NULL, no directory is ignored.
|
||||
\param ignore_hidden_files If set to TRUE, hidden files (starting with '.')
|
||||
are ignored.
|
||||
\param ignore_hidden_dirs If set to TRUE, hidden directories (starting with '.')
|
||||
are ignored.
|
||||
\return Populated TMFileEntry structure on success, NULL on failure.
|
||||
*/
|
||||
TMFileEntry *tm_file_entry_new(const char *path, TMFileEntry *parent
|
||||
, gboolean recurse, GList *file_match, GList *file_unmatch
|
||||
, GList *dir_match, GList *dir_unmatch, gboolean ignore_hidden_files
|
||||
, gboolean ignore_hidden_dirs);
|
||||
|
||||
/* Frees a TMFileEntry structure. Freeing is recursive, so all child
|
||||
entries are freed as well.
|
||||
\param entry The TMFileEntry structure to be freed.
|
||||
*/
|
||||
void tm_file_entry_free(gpointer entry);
|
||||
|
||||
/* This will call the function func() for each file entry.
|
||||
\param entry The root file entry.
|
||||
\param func The function to be called.
|
||||
\param user_data Extra information to be passed to the function.
|
||||
\param level The recursion level. You should set this to 0 initially.
|
||||
\param reverse If set to TRUE, traversal is in reverse hierarchical order
|
||||
*/
|
||||
void tm_file_entry_foreach(TMFileEntry *entry, TMFileEntryFunc func
|
||||
, gpointer user_data, guint level, gboolean reverse);
|
||||
|
||||
/* This is a sample function to show the use of tm_file_entry_foreach().
|
||||
*/
|
||||
void tm_file_entry_print(TMFileEntry *entry, gpointer user_data, guint level);
|
||||
|
||||
/* Creates a list of path names from a TMFileEntry structure.
|
||||
\param entry The TMFileEntry structure.
|
||||
\files Current file list. Should be NULL.
|
||||
*/
|
||||
GList *tm_file_entry_list(TMFileEntry *entry, GList *files);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* TM_FILE_ENTRY_H */
|
||||
@ -18,37 +18,159 @@
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <glib/gstdio.h>
|
||||
#ifdef G_OS_WIN32
|
||||
# define VC_EXTRALEAN
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h> /* for GetFullPathName */
|
||||
#endif
|
||||
|
||||
#include "general.h"
|
||||
#include "entry.h"
|
||||
#include "parse.h"
|
||||
#include "read.h"
|
||||
#define LIBCTAGS_DEFINED
|
||||
#include "tm_work_object.h"
|
||||
|
||||
#define LIBCTAGS_DEFINED
|
||||
#include "tm_source_file.h"
|
||||
#include "tm_tag.h"
|
||||
|
||||
|
||||
guint source_file_class_id = 0;
|
||||
static TMSourceFile *current_source_file = NULL;
|
||||
|
||||
gboolean tm_source_file_init(TMSourceFile *source_file, const char *file_name
|
||||
, gboolean update, const char* name)
|
||||
static int get_path_max(const char *path)
|
||||
{
|
||||
if (0 == source_file_class_id)
|
||||
source_file_class_id = tm_work_object_register(tm_source_file_free
|
||||
, tm_source_file_update, NULL);
|
||||
#ifdef PATH_MAX
|
||||
return PATH_MAX;
|
||||
#else
|
||||
int path_max = pathconf(path, _PC_PATH_MAX);
|
||||
if (path_max <= 0)
|
||||
path_max = 4096;
|
||||
return path_max;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
/* realpath implementation for Windows found at http://bugzilla.gnome.org/show_bug.cgi?id=342926
|
||||
* this one is better than e.g. liberty's lrealpath because this one uses Win32 API and works
|
||||
* with special chars within the filename */
|
||||
static char *realpath (const char *pathname, char *resolved_path)
|
||||
{
|
||||
int size;
|
||||
|
||||
if (resolved_path != NULL)
|
||||
{
|
||||
int path_max = get_path_max(pathname);
|
||||
size = GetFullPathNameA (pathname, path_max, resolved_path, NULL);
|
||||
if (size > path_max)
|
||||
return NULL;
|
||||
else
|
||||
return resolved_path;
|
||||
}
|
||||
else
|
||||
{
|
||||
size = GetFullPathNameA (pathname, 0, NULL, NULL);
|
||||
resolved_path = g_new0 (char, size);
|
||||
GetFullPathNameA (pathname, size, resolved_path, NULL);
|
||||
return resolved_path;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
Given a file name, returns a newly allocated string containing the realpath()
|
||||
of the file.
|
||||
@param file_name The original file_name
|
||||
@return A newly allocated string containing the real path to the file. NULL if none is available.
|
||||
*/
|
||||
gchar *tm_get_real_path(const gchar *file_name)
|
||||
{
|
||||
if (file_name)
|
||||
{
|
||||
gsize len = get_path_max(file_name) + 1;
|
||||
gchar *path = g_malloc0(len);
|
||||
|
||||
if (realpath(file_name, path))
|
||||
return path;
|
||||
else
|
||||
g_free(path);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
This function is registered into the ctags parser when a file is parsed for
|
||||
the first time. The function is then called by the ctags parser each time
|
||||
it finds a new tag. You should not have to use this function.
|
||||
@see tm_source_file_parse()
|
||||
*/
|
||||
static int tm_source_file_tags(const tagEntryInfo *tag)
|
||||
{
|
||||
if (NULL == current_source_file)
|
||||
return 0;
|
||||
g_ptr_array_add(current_source_file->tags_array,
|
||||
tm_tag_new(current_source_file, tag));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Set the argument list of tag identified by its name */
|
||||
static void tm_source_file_set_tag_arglist(const char *tag_name, const char *arglist)
|
||||
{
|
||||
guint count;
|
||||
TMTag **tags, *tag;
|
||||
|
||||
if (NULL == arglist ||
|
||||
NULL == tag_name ||
|
||||
NULL == current_source_file)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tags = tm_tags_find(current_source_file->tags_array, tag_name, FALSE, FALSE,
|
||||
&count);
|
||||
if (tags != NULL && count == 1)
|
||||
{
|
||||
tag = tags[0];
|
||||
g_free(tag->arglist);
|
||||
tag->arglist = g_strdup(arglist);
|
||||
}
|
||||
}
|
||||
|
||||
/* Initializes a TMSourceFile structure from a file name. */
|
||||
static gboolean tm_source_file_init(TMSourceFile *source_file, const char *file_name,
|
||||
const char* name)
|
||||
{
|
||||
struct stat s;
|
||||
int status;
|
||||
|
||||
#ifdef TM_DEBUG
|
||||
g_message("Source File init: %s", file_name);
|
||||
#endif
|
||||
|
||||
if (FALSE == tm_work_object_init(&(source_file->work_object),
|
||||
source_file_class_id, file_name, FALSE))
|
||||
return FALSE;
|
||||
if (file_name != NULL)
|
||||
{
|
||||
status = g_stat(file_name, &s);
|
||||
if (0 != status)
|
||||
{
|
||||
/* g_warning("Unable to stat %s", file_name);*/
|
||||
return FALSE;
|
||||
}
|
||||
if (!S_ISREG(s.st_mode))
|
||||
{
|
||||
g_warning("%s: Not a regular file", file_name);
|
||||
return FALSE;
|
||||
}
|
||||
source_file->file_name = tm_get_real_path(file_name);
|
||||
source_file->short_name = strrchr(source_file->file_name, '/');
|
||||
if (source_file->short_name)
|
||||
++ source_file->short_name;
|
||||
else
|
||||
source_file->short_name = source_file->file_name;
|
||||
}
|
||||
|
||||
source_file->tags_array = g_ptr_array_new();
|
||||
|
||||
source_file->inactive = FALSE;
|
||||
if (NULL == LanguageTable)
|
||||
{
|
||||
initializeParsing();
|
||||
@ -64,37 +186,46 @@ gboolean tm_source_file_init(TMSourceFile *source_file, const char *file_name
|
||||
else
|
||||
source_file->lang = getNamedLanguage(name);
|
||||
|
||||
if (update)
|
||||
tm_source_file_update(TM_WORK_OBJECT(source_file), TRUE, FALSE, FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
TMWorkObject *tm_source_file_new(const char *file_name, gboolean update, const char *name)
|
||||
/** Initializes a TMSourceFile structure and returns a pointer to it. The
|
||||
* TMSourceFile has to be added to TMWorkspace to start its parsing.
|
||||
* @param file_name The file name.
|
||||
* @param name Name of the used programming language, NULL for autodetection.
|
||||
* @return The created unparsed TMSourceFile object.
|
||||
* */
|
||||
TMSourceFile *tm_source_file_new(const char *file_name, const char *name)
|
||||
{
|
||||
TMSourceFile *source_file = g_new(TMSourceFile, 1);
|
||||
if (TRUE != tm_source_file_init(source_file, file_name, update, name))
|
||||
if (TRUE != tm_source_file_init(source_file, file_name, name))
|
||||
{
|
||||
g_free(source_file);
|
||||
return NULL;
|
||||
}
|
||||
return (TMWorkObject *) source_file;
|
||||
return source_file;
|
||||
}
|
||||
|
||||
void tm_source_file_destroy(TMSourceFile *source_file)
|
||||
/* Destroys the contents of the source file. Note that the tags are owned by the
|
||||
source file and are also destroyed when the source file is destroyed. If pointers
|
||||
to these tags are used elsewhere, then those tag arrays should be rebuilt.
|
||||
*/
|
||||
static void tm_source_file_destroy(TMSourceFile *source_file)
|
||||
{
|
||||
#ifdef TM_DEBUG
|
||||
g_message("Destroying source file: %s", source_file->work_object.file_name);
|
||||
g_message("Destroying source file: %s", source_file->file_name);
|
||||
#endif
|
||||
|
||||
if (NULL != TM_WORK_OBJECT(source_file)->tags_array)
|
||||
{
|
||||
tm_tags_array_free(TM_WORK_OBJECT(source_file)->tags_array, TRUE);
|
||||
TM_WORK_OBJECT(source_file)->tags_array = NULL;
|
||||
}
|
||||
tm_work_object_destroy(&(source_file->work_object));
|
||||
g_free(source_file->file_name);
|
||||
tm_tags_array_free(source_file->tags_array, TRUE);
|
||||
source_file->tags_array = NULL;
|
||||
}
|
||||
|
||||
void tm_source_file_free(gpointer source_file)
|
||||
/** Frees a TMSourceFile structure, including all contents. Before calling this
|
||||
function the TMSourceFile has to be removed from the TMWorkspace.
|
||||
@param source_file The source file to free.
|
||||
*/
|
||||
void tm_source_file_free(TMSourceFile *source_file)
|
||||
{
|
||||
if (NULL != source_file)
|
||||
{
|
||||
@ -103,79 +234,63 @@ void tm_source_file_free(gpointer source_file)
|
||||
}
|
||||
}
|
||||
|
||||
gboolean tm_source_file_parse(TMSourceFile *source_file)
|
||||
/* Parses the text-buffer or source file and regenarates the tags.
|
||||
@param source_file The source file to parse
|
||||
@param text_buf The text buffer to parse
|
||||
@param buf_size The size of text_buf.
|
||||
@param use_buffer Set FALSE to ignore the buffer and parse the file directly or
|
||||
TRUE to parse the buffer and ignore the file content.
|
||||
@return TRUE on success, FALSE on failure
|
||||
*/
|
||||
gboolean tm_source_file_parse(TMSourceFile *source_file, guchar* text_buf, gsize buf_size,
|
||||
gboolean use_buffer)
|
||||
{
|
||||
const char *file_name;
|
||||
gboolean status = TRUE;
|
||||
int passCount = 0;
|
||||
gboolean retry = TRUE;
|
||||
gboolean parse_file = FALSE;
|
||||
gboolean free_buf = FALSE;
|
||||
|
||||
if ((NULL == source_file) || (NULL == source_file->work_object.file_name))
|
||||
if ((NULL == source_file) || (NULL == source_file->file_name))
|
||||
{
|
||||
g_warning("Attempt to parse NULL file");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
file_name = source_file->work_object.file_name;
|
||||
if (NULL == LanguageTable)
|
||||
|
||||
if (source_file->lang == LANG_IGNORE)
|
||||
{
|
||||
initializeParsing();
|
||||
installLanguageMapDefaults();
|
||||
if (NULL == TagEntryFunction)
|
||||
TagEntryFunction = tm_source_file_tags;
|
||||
if (NULL == TagEntrySetArglistFunction)
|
||||
TagEntrySetArglistFunction = tm_source_file_set_tag_arglist;
|
||||
tm_tags_array_free(source_file->tags_array, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
current_source_file = source_file;
|
||||
|
||||
if (LANG_AUTO == source_file->lang)
|
||||
source_file->lang = getFileLanguage (file_name);
|
||||
|
||||
if (source_file->lang < 0 || ! LanguageTable [source_file->lang]->enabled)
|
||||
return status;
|
||||
|
||||
while ((TRUE == status) && (passCount < 3))
|
||||
|
||||
file_name = source_file->file_name;
|
||||
|
||||
if (!use_buffer)
|
||||
{
|
||||
if (source_file->work_object.tags_array)
|
||||
tm_tags_array_free(source_file->work_object.tags_array, FALSE);
|
||||
if (fileOpen (file_name, source_file->lang))
|
||||
{
|
||||
if (LanguageTable [source_file->lang]->parser != NULL)
|
||||
{
|
||||
LanguageTable [source_file->lang]->parser ();
|
||||
fileClose ();
|
||||
break;
|
||||
}
|
||||
else if (LanguageTable [source_file->lang]->parser2 != NULL)
|
||||
status = LanguageTable [source_file->lang]->parser2 (passCount);
|
||||
fileClose ();
|
||||
}
|
||||
struct stat s;
|
||||
|
||||
/* load file to memory and parse it from memory unless the file is too big */
|
||||
if (g_stat(file_name, &s) != 0 || s.st_size > 10*1024*1024)
|
||||
parse_file = TRUE;
|
||||
else
|
||||
{
|
||||
g_warning("%s: Unable to open %s", G_STRFUNC, file_name);
|
||||
return FALSE;
|
||||
if (!g_file_get_contents(file_name, (gchar**)&text_buf, (gsize*)&buf_size, NULL))
|
||||
{
|
||||
g_warning("Unable to open %s", file_name);
|
||||
return FALSE;
|
||||
}
|
||||
free_buf = TRUE;
|
||||
}
|
||||
++ passCount;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
gboolean tm_source_file_buffer_parse(TMSourceFile *source_file, guchar* text_buf, gint buf_size)
|
||||
{
|
||||
const char *file_name;
|
||||
gboolean status = TRUE;
|
||||
|
||||
if ((NULL == source_file) || (NULL == source_file->work_object.file_name))
|
||||
if (!parse_file && (NULL == text_buf || 0 == buf_size))
|
||||
{
|
||||
g_warning("Attempt to parse NULL file");
|
||||
return FALSE;
|
||||
/* Empty buffer, "parse" by setting empty tag array */
|
||||
tm_tags_array_free(source_file->tags_array, FALSE);
|
||||
if (free_buf)
|
||||
g_free(text_buf);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if ((NULL == text_buf) || (0 == buf_size))
|
||||
{
|
||||
g_warning("Attempt to parse a NULL text buffer");
|
||||
}
|
||||
|
||||
file_name = source_file->work_object.file_name;
|
||||
if (NULL == LanguageTable)
|
||||
{
|
||||
initializeParsing();
|
||||
@ -202,21 +317,34 @@ gboolean tm_source_file_buffer_parse(TMSourceFile *source_file, guchar* text_buf
|
||||
}
|
||||
else
|
||||
{
|
||||
int passCount = 0;
|
||||
while ((TRUE == status) && (passCount < 3))
|
||||
guint passCount = 0;
|
||||
while (retry && passCount < 3)
|
||||
{
|
||||
if (source_file->work_object.tags_array)
|
||||
tm_tags_array_free(source_file->work_object.tags_array, FALSE);
|
||||
if (bufferOpen (text_buf, buf_size, file_name, source_file->lang))
|
||||
tm_tags_array_free(source_file->tags_array, FALSE);
|
||||
if (parse_file && fileOpen (file_name, source_file->lang))
|
||||
{
|
||||
if (LanguageTable [source_file->lang]->parser != NULL)
|
||||
{
|
||||
LanguageTable [source_file->lang]->parser ();
|
||||
fileClose ();
|
||||
retry = FALSE;
|
||||
break;
|
||||
}
|
||||
else if (LanguageTable [source_file->lang]->parser2 != NULL)
|
||||
retry = LanguageTable [source_file->lang]->parser2 (passCount);
|
||||
fileClose ();
|
||||
}
|
||||
else if (!parse_file && bufferOpen (text_buf, buf_size, file_name, source_file->lang))
|
||||
{
|
||||
if (LanguageTable [source_file->lang]->parser != NULL)
|
||||
{
|
||||
LanguageTable [source_file->lang]->parser ();
|
||||
bufferClose ();
|
||||
retry = FALSE;
|
||||
break;
|
||||
}
|
||||
else if (LanguageTable [source_file->lang]->parser2 != NULL)
|
||||
status = LanguageTable [source_file->lang]->parser2 (passCount);
|
||||
retry = LanguageTable [source_file->lang]->parser2 (passCount);
|
||||
bufferClose ();
|
||||
}
|
||||
else
|
||||
@ -226,103 +354,66 @@ gboolean tm_source_file_buffer_parse(TMSourceFile *source_file, guchar* text_buf
|
||||
}
|
||||
++ passCount;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
return status;
|
||||
|
||||
if (free_buf)
|
||||
g_free(text_buf);
|
||||
return !retry;
|
||||
}
|
||||
|
||||
void tm_source_file_set_tag_arglist(const char *tag_name, const char *arglist)
|
||||
/* Gets the name associated with the language index.
|
||||
@param lang The language index.
|
||||
@return The language name, or NULL.
|
||||
*/
|
||||
const gchar *tm_source_file_get_lang_name(gint lang)
|
||||
{
|
||||
int count;
|
||||
TMTag **tags, *tag;
|
||||
|
||||
if (NULL == arglist ||
|
||||
NULL == tag_name ||
|
||||
NULL == current_source_file ||
|
||||
NULL == current_source_file->work_object.tags_array)
|
||||
if (NULL == LanguageTable)
|
||||
{
|
||||
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);
|
||||
initializeParsing();
|
||||
installLanguageMapDefaults();
|
||||
if (NULL == TagEntryFunction)
|
||||
TagEntryFunction = tm_source_file_tags;
|
||||
if (NULL == TagEntrySetArglistFunction)
|
||||
TagEntrySetArglistFunction = tm_source_file_set_tag_arglist;
|
||||
}
|
||||
return getLanguageName(lang);
|
||||
}
|
||||
|
||||
int tm_source_file_tags(const tagEntryInfo *tag)
|
||||
/* Gets the language index for \a name.
|
||||
@param name The language name.
|
||||
@return The language index, or -2.
|
||||
*/
|
||||
gint tm_source_file_get_named_lang(const gchar *name)
|
||||
{
|
||||
if (NULL == current_source_file)
|
||||
return 0;
|
||||
if (NULL == current_source_file->work_object.tags_array)
|
||||
current_source_file->work_object.tags_array = g_ptr_array_new();
|
||||
g_ptr_array_add(current_source_file->work_object.tags_array,
|
||||
tm_tag_new(current_source_file, tag));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean tm_source_file_update(TMWorkObject *source_file, gboolean force
|
||||
, gboolean UNUSED recurse, gboolean update_parent)
|
||||
{
|
||||
if (force)
|
||||
if (NULL == LanguageTable)
|
||||
{
|
||||
tm_source_file_parse(TM_SOURCE_FILE(source_file));
|
||||
tm_tags_sort(source_file->tags_array, NULL, FALSE);
|
||||
/* source_file->analyze_time = tm_get_file_timestamp(source_file->file_name); */
|
||||
if ((source_file->parent) && update_parent)
|
||||
{
|
||||
tm_work_object_update(source_file->parent, TRUE, FALSE, TRUE);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
else {
|
||||
#ifdef TM_DEBUG
|
||||
g_message ("no parsing of %s has been done", source_file->file_name);
|
||||
#endif
|
||||
return FALSE;
|
||||
initializeParsing();
|
||||
installLanguageMapDefaults();
|
||||
if (NULL == TagEntryFunction)
|
||||
TagEntryFunction = tm_source_file_tags;
|
||||
if (NULL == TagEntrySetArglistFunction)
|
||||
TagEntrySetArglistFunction = tm_source_file_set_tag_arglist;
|
||||
}
|
||||
return getNamedLanguage(name);
|
||||
}
|
||||
|
||||
|
||||
gboolean tm_source_file_buffer_update(TMWorkObject *source_file, guchar* text_buf,
|
||||
gint buf_size, gboolean update_parent)
|
||||
{
|
||||
#ifdef TM_DEBUG
|
||||
g_message("Buffer updating based on source file %s", source_file->file_name);
|
||||
#endif
|
||||
|
||||
tm_source_file_buffer_parse (TM_SOURCE_FILE(source_file), text_buf, buf_size);
|
||||
tm_tags_sort(source_file->tags_array, NULL, FALSE);
|
||||
/* source_file->analyze_time = time(NULL); */
|
||||
if ((source_file->parent) && update_parent)
|
||||
{
|
||||
#ifdef TM_DEBUG
|
||||
g_message("Updating parent from buffer..");
|
||||
#endif
|
||||
tm_work_object_update(source_file->parent, TRUE, FALSE, TRUE);
|
||||
}
|
||||
#ifdef TM_DEBUG
|
||||
else
|
||||
g_message("Skipping parent update because parent is %s and update_parent is %s"
|
||||
, source_file->parent?"NOT NULL":"NULL", update_parent?"TRUE":"FALSE");
|
||||
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
gboolean tm_source_file_write(TMWorkObject *source_file, FILE *fp, guint attrs)
|
||||
#if 0
|
||||
/*
|
||||
Writes all tags of a source file (including the file tag itself) to the passed
|
||||
file pointer.
|
||||
@param source_file The source file to write.
|
||||
@param fp The file pointer to write to.
|
||||
@param attrs The attributes to write.
|
||||
@return TRUE on success, FALSE on failure.
|
||||
*/
|
||||
static gboolean tm_source_file_write(TMSourceFile *source_file, FILE *fp, guint attrs)
|
||||
{
|
||||
TMTag *tag;
|
||||
guint i;
|
||||
|
||||
if (NULL != source_file)
|
||||
{
|
||||
if (NULL != (tag = tm_tag_new(TM_SOURCE_FILE(source_file), NULL)))
|
||||
if (NULL != (tag = tm_tag_new(source_file, NULL)))
|
||||
{
|
||||
tm_tag_write(tag, fp, tm_tag_attr_max_t);
|
||||
tm_tag_unref(tag);
|
||||
@ -339,32 +430,4 @@ gboolean tm_source_file_write(TMWorkObject *source_file, FILE *fp, guint attrs)
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
const gchar *tm_source_file_get_lang_name(gint lang)
|
||||
{
|
||||
if (NULL == LanguageTable)
|
||||
{
|
||||
initializeParsing();
|
||||
installLanguageMapDefaults();
|
||||
if (NULL == TagEntryFunction)
|
||||
TagEntryFunction = tm_source_file_tags;
|
||||
if (NULL == TagEntrySetArglistFunction)
|
||||
TagEntrySetArglistFunction = tm_source_file_set_tag_arglist;
|
||||
}
|
||||
return getLanguageName(lang);
|
||||
}
|
||||
|
||||
gint tm_source_file_get_named_lang(const gchar *name)
|
||||
{
|
||||
if (NULL == LanguageTable)
|
||||
{
|
||||
initializeParsing();
|
||||
installLanguageMapDefaults();
|
||||
if (NULL == TagEntryFunction)
|
||||
TagEntryFunction = tm_source_file_tags;
|
||||
if (NULL == TagEntrySetArglistFunction)
|
||||
TagEntrySetArglistFunction = tm_source_file_set_tag_arglist;
|
||||
}
|
||||
return getNamedLanguage(name);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -10,8 +10,8 @@
|
||||
#ifndef TM_SOURCE_FILE_H
|
||||
#define TM_SOURCE_FILE_H
|
||||
|
||||
#include "tm_work_object.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <glib.h>
|
||||
|
||||
#ifndef LIBCTAGS_DEFINED
|
||||
typedef int langType;
|
||||
@ -27,138 +27,38 @@ extern "C"
|
||||
#endif
|
||||
|
||||
/* Casts a pointer to a pointer to a TMSourceFile structure */
|
||||
#define TM_SOURCE_FILE(work_object) ((TMSourceFile *) work_object)
|
||||
#define TM_SOURCE_FILE(source_file) ((TMSourceFile *) source_file)
|
||||
|
||||
/* Checks whether the object is a TMSourceFile */
|
||||
#define IS_TM_SOURCE_FILE(source_file) (((TMWorkObject *) (source_file))->type \
|
||||
== source_file_class_id)
|
||||
/* Evaluates to X is X is defined, else evaluates to Y */
|
||||
#define FALLBACK(X,Y) (X)?(X):(Y)
|
||||
|
||||
/*!
|
||||
The TMSourceFile structure is derived from TMWorkObject and contains all it's
|
||||
attributes, plus an integer representing the language of the file.
|
||||
|
||||
/**
|
||||
The TMSourceFile structure represents the source file and its tags in the tag manager.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
TMWorkObject work_object; /*!< The base work object */
|
||||
langType lang; /*!< Programming language used */
|
||||
gboolean inactive; /*!< Whether this file should be scanned for tags */
|
||||
langType lang; /**< Programming language used */
|
||||
char *file_name; /**< Full file name (inc. path) */
|
||||
char *short_name; /**< Just the name of the file (without the path) */
|
||||
GPtrArray *tags_array; /**< Sorted tag array obtained by parsing the object */
|
||||
} TMSourceFile;
|
||||
|
||||
/*! Initializes a TMSourceFile structure and returns a pointer to it.
|
||||
* \param file_name The file name.
|
||||
* \param update Update the tag array of the file.
|
||||
* \param name Name of the used programming language, NULL for autodetection.
|
||||
* \return The created TMSourceFile object.
|
||||
* */
|
||||
TMWorkObject *tm_source_file_new(const char *file_name, gboolean update, const char *name);
|
||||
TMSourceFile *tm_source_file_new(const char *file_name, const char *name);
|
||||
|
||||
/*! Updates the source file by reparsing if the modification time is greater
|
||||
than the timestamp in the structure, or if force is TRUE. The tags array and
|
||||
the tags themselves are destroyed and re-created, hence any other tag arrays
|
||||
pointing to these tags should be rebuilt as well. All sorting information is
|
||||
also lost. The language parameter is automatically set the first time the file
|
||||
is parsed.
|
||||
\param source_file The source file to update.
|
||||
\param force Ignored. The source file is always updated.
|
||||
\param recurse This parameter is ignored for source files and is only there for consistency.
|
||||
\param update_parent If set to TRUE, sends an update signal to parent if required. You should
|
||||
always set this to TRUE if you are calling this function directly.
|
||||
\return TRUE if the file was parsed, FALSE otherwise.
|
||||
\sa tm_work_object_update(), tm_workspace_update()
|
||||
*/
|
||||
gboolean tm_source_file_update(TMWorkObject *source_file, gboolean force
|
||||
, gboolean recurse, gboolean update_parent);
|
||||
void tm_source_file_free(TMSourceFile *source_file);
|
||||
|
||||
gchar *tm_get_real_path(const gchar *file_name);
|
||||
|
||||
|
||||
#ifdef GEANY_PRIVATE
|
||||
|
||||
/* Initializes a TMSourceFile structure from a file name. */
|
||||
gboolean tm_source_file_init(TMSourceFile *source_file, const char *file_name,
|
||||
gboolean update, const char *name);
|
||||
|
||||
/* Destroys the contents of the source file. Note that the tags are owned by the
|
||||
source file and are also destroyed when the source file is destroyed. If pointers
|
||||
to these tags are used elsewhere, then those tag arrays should be rebuilt.
|
||||
*/
|
||||
void tm_source_file_destroy(TMSourceFile *source_file);
|
||||
|
||||
/* Frees a TMSourceFile structure, including all contents */
|
||||
void tm_source_file_free(gpointer source_file);
|
||||
|
||||
/* Updates the source file by reparsing the text-buffer passed as parameter.
|
||||
Ctags will use a parsing based on buffer instead of on files.
|
||||
You should call this function when you don't want a previous saving of the file
|
||||
you're editing. It's useful for a "real-time" updating of the tags.
|
||||
The tags array and the tags themselves are destroyed and re-created, hence any
|
||||
other tag arrays pointing to these tags should be rebuilt as well. All sorting
|
||||
information is also lost. The language parameter is automatically set the first
|
||||
time the file is parsed.
|
||||
\param source_file The source file to update with a buffer.
|
||||
\param text_buf A text buffer. The user should take care of allocate and free it after
|
||||
the use here.
|
||||
\param buf_size The size of text_buf.
|
||||
\param update_parent If set to TRUE, sends an update signal to parent if required. You should
|
||||
always set this to TRUE if you are calling this function directly.
|
||||
\return TRUE if the file was parsed, FALSE otherwise.
|
||||
\sa tm_work_object_update(), tm_workspace_update()
|
||||
*/
|
||||
gboolean tm_source_file_buffer_update(TMWorkObject *source_file, guchar* text_buf,
|
||||
gint buf_size, gboolean update_parent);
|
||||
|
||||
/* Parses the source file and regenarates the tags.
|
||||
\param source_file The source file to parse
|
||||
\return TRUE on success, FALSE on failure
|
||||
\sa tm_source_file_update()
|
||||
*/
|
||||
gboolean tm_source_file_parse(TMSourceFile *source_file);
|
||||
|
||||
/* Parses the text-buffer and regenarates the tags.
|
||||
\param source_file The source file to parse
|
||||
\param text_buf The text buffer to parse
|
||||
\param buf_size The size of text_buf.
|
||||
\return TRUE on success, FALSE on failure
|
||||
\sa tm_source_file_update()
|
||||
*/
|
||||
gboolean tm_source_file_buffer_parse(TMSourceFile *source_file, guchar* text_buf, gint buf_size);
|
||||
|
||||
/*
|
||||
This function is registered into the ctags parser when a file is parsed for
|
||||
the first time. The function is then called by the ctags parser each time
|
||||
it finds a new tag. You should not have to use this function.
|
||||
\sa tm_source_file_parse()
|
||||
*/
|
||||
int tm_source_file_tags(const tagEntryInfo *tag);
|
||||
|
||||
/*
|
||||
Writes all tags of a source file (including the file tag itself) to the passed
|
||||
file pointer.
|
||||
\param source_file The source file to write.
|
||||
\param fp The file pointer to write to.
|
||||
\param attrs The attributes to write.
|
||||
\return TRUE on success, FALSE on failure.
|
||||
*/
|
||||
gboolean tm_source_file_write(TMWorkObject *source_file, FILE *fp, guint attrs);
|
||||
|
||||
/* Contains the id obtained by registering the TMSourceFile class as a child of
|
||||
TMWorkObject.
|
||||
\sa tm_work_object_register()
|
||||
*/
|
||||
extern guint source_file_class_id;
|
||||
|
||||
/* Gets the name associated with the language index.
|
||||
\param lang The language index.
|
||||
\return The language name, or NULL.
|
||||
*/
|
||||
const gchar *tm_source_file_get_lang_name(gint lang);
|
||||
|
||||
/* Gets the language index for \a name.
|
||||
\param name The language name.
|
||||
\return The language index, or -2.
|
||||
*/
|
||||
gint tm_source_file_get_named_lang(const gchar *name);
|
||||
|
||||
/* Set the argument list of tag identified by its name */
|
||||
void tm_source_file_set_tag_arglist(const char *tag_name, const char *arglist);
|
||||
gboolean tm_source_file_parse(TMSourceFile *source_file, guchar* text_buf, gsize buf_size,
|
||||
gboolean use_buffer);
|
||||
|
||||
#endif /* GEANY_PRIVATE */
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -10,15 +10,15 @@
|
||||
#ifndef TM_TAG_H
|
||||
#define TM_TAG_H
|
||||
|
||||
/* \file
|
||||
/* @file
|
||||
The TMTag structure and the associated functions are used to manipulate
|
||||
tags and arrays of tags. Normally, you should not create tags individually
|
||||
but through an external interface such as tm_source_file_parse(), which generates
|
||||
an array of tags for the given source file. Once the tag list is generated,
|
||||
you can do various operations such as:
|
||||
-# Extract relevant tags using tm_tags_extract()
|
||||
-# Sort an array of tags using tm_tags_sort() or tm_tags_custom_sort()
|
||||
-# Deduplicate an array of tags using tm_tags_dedup() or tm_tags_dedup_custom().
|
||||
-# Sort an array of tags using tm_tags_sort()
|
||||
-# Deduplicate an array of tags using tm_tags_dedup().
|
||||
|
||||
An important thing to remember here is that the tags operations such as extraction,
|
||||
sorting and deduplication do not change the tag itself in any way, but rather,
|
||||
@ -37,41 +37,41 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/*! Use the TM_TAG() macro to cast a pointer to (TMTag *) */
|
||||
/** Use the TM_TAG() macro to cast a pointer to (TMTag *) */
|
||||
#define TM_TAG(tag) ((TMTag *) tag)
|
||||
|
||||
/*!
|
||||
/**
|
||||
Types of tags. It is a bitmask so that multiple tag types can
|
||||
be used simultaneously by 'OR'-ing them bitwise.
|
||||
e.g. tm_tag_class_t | tm_tag_struct_t
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
tm_tag_undef_t = 0, /*!< Unknown type */
|
||||
tm_tag_class_t = 1, /*!< Class declaration */
|
||||
tm_tag_enum_t = 2, /*!< Enum declaration */
|
||||
tm_tag_enumerator_t = 4, /*!< Enumerator value */
|
||||
tm_tag_field_t = 8, /*!< Field (Java only) */
|
||||
tm_tag_function_t = 16, /*!< Function definition */
|
||||
tm_tag_interface_t = 32, /*!< Interface (Java only) */
|
||||
tm_tag_member_t = 64, /*!< Member variable of class/struct */
|
||||
tm_tag_method_t = 128, /*!< Class method (Java only) */
|
||||
tm_tag_namespace_t = 256, /*!< Namespace declaration */
|
||||
tm_tag_package_t = 512, /*!< Package (Java only) */
|
||||
tm_tag_prototype_t = 1024, /*!< Function prototype */
|
||||
tm_tag_struct_t = 2048, /*!< Struct declaration */
|
||||
tm_tag_typedef_t = 4096, /*!< Typedef */
|
||||
tm_tag_union_t = 8192, /*!< Union */
|
||||
tm_tag_variable_t = 16384, /*!< Variable */
|
||||
tm_tag_externvar_t = 32768, /*!< Extern or forward declaration */
|
||||
tm_tag_macro_t = 65536, /*!< Macro (without arguments) */
|
||||
tm_tag_macro_with_arg_t = 131072, /*!< Parameterized macro */
|
||||
tm_tag_file_t = 262144, /*!< File (Pseudo tag) */
|
||||
tm_tag_other_t = 524288, /*!< Other (non C/C++/Java tag) */
|
||||
tm_tag_max_t = 1048575 /*!< Maximum value of TMTagType */
|
||||
tm_tag_undef_t = 0, /**< Unknown type */
|
||||
tm_tag_class_t = 1, /**< Class declaration */
|
||||
tm_tag_enum_t = 2, /**< Enum declaration */
|
||||
tm_tag_enumerator_t = 4, /**< Enumerator value */
|
||||
tm_tag_field_t = 8, /**< Field (Java only) */
|
||||
tm_tag_function_t = 16, /**< Function definition */
|
||||
tm_tag_interface_t = 32, /**< Interface (Java only) */
|
||||
tm_tag_member_t = 64, /**< Member variable of class/struct */
|
||||
tm_tag_method_t = 128, /**< Class method (Java only) */
|
||||
tm_tag_namespace_t = 256, /**< Namespace declaration */
|
||||
tm_tag_package_t = 512, /**< Package (Java only) */
|
||||
tm_tag_prototype_t = 1024, /**< Function prototype */
|
||||
tm_tag_struct_t = 2048, /**< Struct declaration */
|
||||
tm_tag_typedef_t = 4096, /**< Typedef */
|
||||
tm_tag_union_t = 8192, /**< Union */
|
||||
tm_tag_variable_t = 16384, /**< Variable */
|
||||
tm_tag_externvar_t = 32768, /**< Extern or forward declaration */
|
||||
tm_tag_macro_t = 65536, /**< Macro (without arguments) */
|
||||
tm_tag_macro_with_arg_t = 131072, /**< Parameterized macro */
|
||||
tm_tag_file_t = 262144, /**< File (Pseudo tag) - obsolete */
|
||||
tm_tag_other_t = 524288, /**< Other (non C/C++/Java tag) */
|
||||
tm_tag_max_t = 1048575 /**< Maximum value of TMTagType */
|
||||
} TMTagType;
|
||||
|
||||
/*!
|
||||
/**
|
||||
Tag Attributes. Note that some attributes are available to file
|
||||
pseudotags only. Attributes are useful for specifying as arguments
|
||||
to the builtin sort and dedup functions, and during printing or writing
|
||||
@ -81,311 +81,129 @@ typedef enum
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
tm_tag_attr_none_t = 0, /*!< Undefined */
|
||||
tm_tag_attr_name_t = 1, /*!< Tag Name */
|
||||
tm_tag_attr_type_t = 2, /*!< Tag Type */
|
||||
tm_tag_attr_file_t = 4, /*!< File in which tag exists */
|
||||
tm_tag_attr_line_t = 8, /*!< Line number of tag */
|
||||
tm_tag_attr_pos_t = 16, /*!< Byte position of tag in the file (Obsolete) */
|
||||
tm_tag_attr_scope_t = 32, /*!< Scope of the tag */
|
||||
tm_tag_attr_inheritance_t = 64, /*!< Parent classes */
|
||||
tm_tag_attr_arglist_t = 128, /*!< Argument list */
|
||||
tm_tag_attr_local_t = 256, /*!< If it has local scope */
|
||||
tm_tag_attr_time_t = 512, /*!< Modification time (File tag only) */
|
||||
tm_tag_attr_vartype_t = 1024, /*!< Variable Type */
|
||||
tm_tag_attr_access_t = 2048, /*!< Access type (public/protected/private) */
|
||||
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) */
|
||||
tm_tag_attr_pointer_t = 32768, /*!< Pointer type */
|
||||
tm_tag_attr_max_t = 65535 /*!< Maximum value */
|
||||
tm_tag_attr_none_t = 0, /**< Undefined */
|
||||
tm_tag_attr_name_t = 1, /**< Tag Name */
|
||||
tm_tag_attr_type_t = 2, /**< Tag Type */
|
||||
tm_tag_attr_file_t = 4, /**< File in which tag exists */
|
||||
tm_tag_attr_line_t = 8, /**< Line number of tag */
|
||||
tm_tag_attr_pos_t = 16, /**< Byte position of tag in the file (Obsolete) */
|
||||
tm_tag_attr_scope_t = 32, /**< Scope of the tag */
|
||||
tm_tag_attr_inheritance_t = 64, /**< Parent classes */
|
||||
tm_tag_attr_arglist_t = 128, /**< Argument list */
|
||||
tm_tag_attr_local_t = 256, /**< If it has local scope */
|
||||
tm_tag_attr_time_t = 512, /**< Modification time (File tag only) */
|
||||
tm_tag_attr_vartype_t = 1024, /**< Variable Type */
|
||||
tm_tag_attr_access_t = 2048, /**< Access type (public/protected/private) */
|
||||
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_max_t = 65535 /**< Maximum value */
|
||||
} TMTagAttrType;
|
||||
|
||||
/*! Tag access type for C++/Java member functions and variables */
|
||||
#define TAG_ACCESS_PUBLIC 'p' /*!< Public member */
|
||||
#define TAG_ACCESS_PROTECTED 'r' /*!< Protected member */
|
||||
#define TAG_ACCESS_PRIVATE 'v' /*!< Private member */
|
||||
#define TAG_ACCESS_FRIEND 'f' /*!< Friend members/functions */
|
||||
#define TAG_ACCESS_DEFAULT 'd' /*!< Default access (Java) */
|
||||
#define TAG_ACCESS_UNKNOWN 'x' /*!< Unknown access type */
|
||||
/** Tag access type for C++/Java member functions and variables */
|
||||
#define TAG_ACCESS_PUBLIC 'p' /**< Public member */
|
||||
#define TAG_ACCESS_PROTECTED 'r' /**< Protected member */
|
||||
#define TAG_ACCESS_PRIVATE 'v' /**< Private member */
|
||||
#define TAG_ACCESS_FRIEND 'f' /**< Friend members/functions */
|
||||
#define TAG_ACCESS_DEFAULT 'd' /**< Default access (Java) */
|
||||
#define TAG_ACCESS_UNKNOWN 'x' /**< Unknown access type */
|
||||
|
||||
/*! Tag implementation type for functions */
|
||||
#define TAG_IMPL_VIRTUAL 'v' /*!< Virtual implementation */
|
||||
#define TAG_IMPL_UNKNOWN 'x' /*!< Unknown implementation */
|
||||
/** Tag implementation type for functions */
|
||||
#define TAG_IMPL_VIRTUAL 'v' /**< Virtual implementation */
|
||||
#define TAG_IMPL_UNKNOWN 'x' /**< Unknown implementation */
|
||||
|
||||
/*!
|
||||
/**
|
||||
This structure holds all information about a tag, including the file
|
||||
pseudo tag. It should always be created indirectly with one of the tag
|
||||
creation functions such as tm_source_file_parse() or tm_tag_new_from_file().
|
||||
Once created, they can be sorted, deduped, etc. using functions such as
|
||||
tm_tags_custom_sort(), tm_tags_sort(), tm_tags_dedup() and tm_tags_custom_dedup()
|
||||
tm_tags_sort() or tm_tags_dedup()
|
||||
*/
|
||||
typedef struct _TMTag
|
||||
{
|
||||
char *name; /*!< Name of tag */
|
||||
TMTagType type; /*!< Tag Type */
|
||||
union
|
||||
{
|
||||
/*! These are *real* tag attributes */
|
||||
struct
|
||||
{
|
||||
TMSourceFile *file; /*!< File in which the tag occurs */
|
||||
gulong line; /*!< Line number of the tag */
|
||||
gboolean local; /*!< Is the tag of local scope */
|
||||
guint pointerOrder;
|
||||
char *arglist; /*!< Argument list (functions/prototypes/macros) */
|
||||
char *scope; /*!< Scope of tag */
|
||||
char *inheritance; /*!< Parent classes */
|
||||
char *var_type; /*!< Variable type (maps to struct for typedefs) */
|
||||
char access; /*!< Access type (public/protected/private/etc.) */
|
||||
char impl; /*!< Implementation (e.g. virtual) */
|
||||
} entry;
|
||||
/*! These are pseudo tag attributes representing a file */
|
||||
struct
|
||||
{
|
||||
time_t timestamp; /*!< Time of parsing of the file */
|
||||
langType lang; /*!< Programming language of the file */
|
||||
gboolean inactive; /*!< Whether this file is to be parsed */
|
||||
} file;
|
||||
} atts;
|
||||
gint refcount; /*!< the reference count of the tag */
|
||||
char *name; /**< Name of tag */
|
||||
TMTagType type; /**< Tag Type */
|
||||
gint refcount; /* the reference count of the tag */
|
||||
|
||||
/** These are tag attributes */
|
||||
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;
|
||||
char *arglist; /**< Argument list (functions/prototypes/macros) */
|
||||
char *scope; /**< Scope of tag */
|
||||
char *inheritance; /**< Parent classes */
|
||||
char *var_type; /**< Variable type (maps to struct for typedefs) */
|
||||
char access; /**< Access type (public/protected/private/etc.) */
|
||||
char impl; /**< Implementation (e.g. virtual) */
|
||||
langType lang; /**< Programming language of the file */
|
||||
} TMTag;
|
||||
|
||||
|
||||
#ifdef GEANY_PRIVATE
|
||||
|
||||
extern const TMTagType TM_GLOBAL_TYPE_MASK;
|
||||
|
||||
|
||||
typedef enum {
|
||||
TM_FILE_FORMAT_TAGMANAGER,
|
||||
TM_FILE_FORMAT_PIPE,
|
||||
TM_FILE_FORMAT_CTAGS
|
||||
} TMFileFormat;
|
||||
|
||||
/*
|
||||
Prototype for user-defined tag comparison function. This is the type
|
||||
of argument that needs to be passed to tm_tags_sort_custom() and
|
||||
tm_tags_dedup_custom(). The function should take two void pointers,
|
||||
cast them to (TMTag **) and return 0, 1 or -1 depending on whether the
|
||||
first tag is equal to, greater than or less than the second tag.
|
||||
*/
|
||||
typedef int (*TMTagCompareFunc) (const void *ptr1, const void *ptr2);
|
||||
|
||||
/* The GType for a TMTag */
|
||||
#define TM_TYPE_TAG (tm_tag_get_type())
|
||||
|
||||
/* Gets the GType for a TMTag */
|
||||
GType tm_tag_get_type(void) G_GNUC_CONST;
|
||||
|
||||
/*
|
||||
Initializes a TMTag structure with information from a tagEntryInfo struct
|
||||
used by the ctags parsers. Note that the TMTag structure must be malloc()ed
|
||||
before calling this function. This function is called by tm_tag_new() - you
|
||||
should not need to call this directly.
|
||||
\param tag The TMTag structure to initialize
|
||||
\param file Pointer to a TMSourceFile struct (it is assigned to the file member)
|
||||
\param tag_entry Tag information gathered by the ctags parser
|
||||
\return TRUE on success, FALSE on failure
|
||||
*/
|
||||
gboolean tm_tag_init(TMTag *tag, TMSourceFile *file, const tagEntryInfo *tag_entry);
|
||||
|
||||
/*
|
||||
Initializes an already malloc()ed TMTag structure by reading a tag entry
|
||||
line from a file. The structure should be allocated beforehand.
|
||||
\param tag The TMTag structure to populate
|
||||
\param file The TMSourceFile struct (assigned to the file member)
|
||||
\param fp FILE pointer from where the tag line is read
|
||||
\return TRUE on success, FALSE on FAILURE
|
||||
*/
|
||||
gboolean tm_tag_init_from_file(TMTag *tag, TMSourceFile *file, FILE *fp);
|
||||
|
||||
/*
|
||||
Same as tm_tag_init_from_file(), but using an alternative parser for PHP and
|
||||
LaTeX global tags files.
|
||||
*/
|
||||
gboolean tm_tag_init_from_file_alt(TMTag *tag, TMSourceFile *file, FILE *fp);
|
||||
|
||||
/*
|
||||
Same as tm_tag_init_from_file(), but parsing CTags tag file format
|
||||
*/
|
||||
gboolean tm_tag_init_from_file_ctags(TMTag *tag, TMSourceFile *file, FILE *fp);
|
||||
|
||||
/*
|
||||
Creates a new tag structure from a tagEntryInfo pointer and a TMSOurceFile pointer
|
||||
and returns a pointer to it.
|
||||
\param file - Pointer to the TMSourceFile structure containing the tag
|
||||
\param tag_entry Contains tag information generated by ctags
|
||||
\return the new TMTag structure. This should be free()-ed using tm_tag_free()
|
||||
*/
|
||||
TMTag *tm_tag_new(TMSourceFile *file, const tagEntryInfo *tag_entry);
|
||||
|
||||
/*
|
||||
Same as tm_tag_new() except that the tag attributes are read from file.
|
||||
\param mode langType to use for the tag.
|
||||
*/
|
||||
TMTag *tm_tag_new_from_file(TMSourceFile *file, FILE *fp, gint mode, TMFileFormat format);
|
||||
|
||||
/*
|
||||
Writes tag information to the given FILE *.
|
||||
\param tag The tag information to write.
|
||||
\param file FILE pointer to which the tag information is written.
|
||||
\param attrs Attributes to be written (bitmask).
|
||||
\return TRUE on success, FALSE on failure.
|
||||
*/
|
||||
gboolean tm_tag_write(TMTag *tag, FILE *file, guint attrs);
|
||||
|
||||
/*
|
||||
Inbuilt tag comparison function. Do not call directly since it needs some
|
||||
static variables to be set. Always use tm_tags_sort() and tm_tags_dedup()
|
||||
instead.
|
||||
*/
|
||||
int tm_tag_compare(const void *ptr1, const void *ptr2);
|
||||
void tm_tags_remove_file_tags(TMSourceFile *source_file, GPtrArray *tags_array);
|
||||
|
||||
gboolean tm_tags_merge(GPtrArray *tags_array, gsize orig_len,
|
||||
TMTagAttrType *sort_attributes, gboolean dedup);
|
||||
GPtrArray *tm_tags_merge(GPtrArray *big_array, GPtrArray *small_array,
|
||||
TMTagAttrType *sort_attributes, gboolean unref_duplicates);
|
||||
|
||||
/*
|
||||
Sort an array of tags on the specified attribuites using the inbuilt comparison
|
||||
function.
|
||||
\param tags_array The array of tags to be sorted
|
||||
\param sort_attributes Attributes to be sorted on (int array terminated by 0)
|
||||
\param dedup Whether to deduplicate the sorted array
|
||||
\return TRUE on success, FALSE on failure
|
||||
*/
|
||||
gboolean tm_tags_sort(GPtrArray *tags_array, TMTagAttrType *sort_attributes, gboolean dedup);
|
||||
gboolean tm_tags_sort(GPtrArray *tags_array, TMTagAttrType *sort_attributes,
|
||||
gboolean dedup, gboolean unref_duplicates);
|
||||
|
||||
/*
|
||||
This function should be used whenever more involved sorting is required. For this,
|
||||
you need to write a function as per the prototype of TMTagCompareFunc() and pass
|
||||
the function as a parameter to this function.
|
||||
\param tags_array Array of tags to be sorted
|
||||
\param compare_func A function which takes two pointers to (TMTag *)s and returns
|
||||
0, 1 or -1 depending on whether the first value is equal to, greater than or less that
|
||||
the second
|
||||
\param dedup Whether to deduplicate the sorted array. Note that the same comparison
|
||||
function will be used
|
||||
\return TRUE on success, FALSE on failure
|
||||
*/
|
||||
gboolean tm_tags_custom_sort(GPtrArray *tags_array, TMTagCompareFunc compare_func, gboolean dedup);
|
||||
|
||||
/*
|
||||
This function will extract the tags of the specified types from an array of tags.
|
||||
The returned value is a GPtrArray which should be free-d with a call to
|
||||
g_ptr_array_free(array, TRUE). However, do not free the tags themselves since they
|
||||
are not duplicated.
|
||||
\param tags_array The original array of tags
|
||||
\param tag_types - The tag types to extract. Can be a bitmask. For example, passing
|
||||
(tm_tag_typedef_t | tm_tag_struct_t) will extract all typedefs and structures from
|
||||
the original array.
|
||||
\return an array of tags (NULL on failure)
|
||||
*/
|
||||
GPtrArray *tm_tags_extract(GPtrArray *tags_array, guint tag_types);
|
||||
|
||||
/*
|
||||
Removes NULL tag entries from an array of tags. Called after tm_tags_dedup() and
|
||||
tm_tags_custom_dedup() since these functions substitute duplicate entries with NULL
|
||||
\param tags_array Array of tags to dedup
|
||||
\return TRUE on success, FALSE on failure
|
||||
*/
|
||||
gboolean tm_tags_prune(GPtrArray *tags_array);
|
||||
|
||||
/*
|
||||
Deduplicates an array on tags using the inbuilt comparison function based on
|
||||
the attributes specified. Called by tm_tags_sort() when dedup is TRUE.
|
||||
\param tags_array Array of tags to dedup.
|
||||
\param sort_attributes Attributes the array is sorted on. They will be deduped
|
||||
on the same criteria.
|
||||
\return TRUE on success, FALSE on failure
|
||||
*/
|
||||
gboolean tm_tags_dedup(GPtrArray *tags_array, TMTagAttrType *sort_attributes);
|
||||
gboolean tm_tags_dedup(GPtrArray *tags_array, TMTagAttrType *sort_attributes, gboolean unref_duplicates);
|
||||
|
||||
/*
|
||||
This is a more powerful form of tm_tags_dedup() since it can accomodate user
|
||||
defined comparison functions. Called by tm_tags_custom_sort() is dedup is TRUE.
|
||||
\param tags_array Array of tags to dedup.
|
||||
\compare_function Comparison function
|
||||
\return TRUE on success, FALSE on FAILURE
|
||||
\sa TMTagCompareFunc
|
||||
*/
|
||||
gboolean tm_tags_custom_dedup(GPtrArray *tags_array, TMTagCompareFunc compare_func);
|
||||
|
||||
/*
|
||||
Returns a pointer to the position of the first matching tag in a (sorted) tags array.
|
||||
The passed array of tags should be already sorted by name for optimal performance. If
|
||||
\c tags_array_sorted is set to FALSE, it may be unsorted but the lookup will be slower.
|
||||
\param tags_array Tag array (may be sorted on name)
|
||||
\param name Name of the tag to locate.
|
||||
\param partial If TRUE, matches the first part of the name instead of doing exact match.
|
||||
\param tags_array_sorted If TRUE, the passed \c tags_array is sorted by name so it can be
|
||||
searched with binary search. Otherwise it is searched linear which is obviously slower.
|
||||
\param tagCount Return location of the matched tags.
|
||||
*/
|
||||
TMTag **tm_tags_find(const GPtrArray *tags_array, const char *name,
|
||||
gboolean partial, gboolean tags_array_sorted, int * tagCount);
|
||||
gboolean partial, gboolean tags_array_sorted, guint * tagCount);
|
||||
|
||||
/*
|
||||
Completely frees an array of tags.
|
||||
\param tags_array Array of tags to be freed.
|
||||
\param free_array Whether the GptrArray is to be freed as well.
|
||||
*/
|
||||
void tm_tags_array_free(GPtrArray *tags_array, gboolean free_all);
|
||||
|
||||
#if 0
|
||||
/*
|
||||
Destroys a TMTag structure, i.e. frees all elements except the tag itself.
|
||||
\param tag The TMTag structure to destroy
|
||||
\sa tm_tag_free()
|
||||
*/
|
||||
void tm_tag_destroy(TMTag *tag);
|
||||
const TMTag *tm_get_current_tag(GPtrArray *file_tags, const gulong line, const TMTagType tag_types);
|
||||
|
||||
/*
|
||||
Destroys all data in the tag and frees the tag structure as well.
|
||||
\param tag Pointer to a TMTag structure
|
||||
*/
|
||||
void tm_tag_free(gpointer tag);
|
||||
#endif
|
||||
|
||||
/*
|
||||
Drops a reference from a TMTag. If the reference count reaches 0, this function
|
||||
destroys all data in the tag and frees the tag structure as well.
|
||||
\param tag Pointer to a TMTag structure
|
||||
*/
|
||||
void tm_tag_unref(TMTag *tag);
|
||||
|
||||
/*
|
||||
Adds a reference to a TMTag.
|
||||
\param tag Pointer to a TMTag structure
|
||||
\return the passed-in TMTag
|
||||
*/
|
||||
TMTag *tm_tag_ref(TMTag *tag);
|
||||
|
||||
/*
|
||||
Returns the type of tag as a string
|
||||
\param tag The tag whose type is required
|
||||
*/
|
||||
|
||||
#ifdef TM_DEBUG /* various debugging functions */
|
||||
|
||||
const char *tm_tag_type_name(const TMTag *tag);
|
||||
|
||||
/*
|
||||
Returns the TMTagType given the name of the type. Reverse of tm_tag_type_name.
|
||||
\param tag_name Name of the tag type
|
||||
*/
|
||||
TMTagType tm_tag_name_type(const char* tag_name);
|
||||
|
||||
/*
|
||||
Prints information about a tag to the given file pointer.
|
||||
\param tag The tag whose info is required.
|
||||
\fp The file pointer of teh file to print the info to.
|
||||
*/
|
||||
void tm_tag_print(TMTag *tag, FILE *fp);
|
||||
|
||||
/*
|
||||
Prints info about all tags in the array to the given file pointer.
|
||||
*/
|
||||
void tm_tags_array_print(GPtrArray *tags, FILE *fp);
|
||||
|
||||
/*
|
||||
Returns the depth of tag scope (useful for finding tag hierarchy
|
||||
*/
|
||||
gint tm_tag_scope_depth(const TMTag *t);
|
||||
|
||||
#endif /* TM_DEBUG */
|
||||
|
||||
#endif /* GEANY_PRIVATE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@ -12,27 +12,25 @@
|
||||
|
||||
#include "tm_tag.h"
|
||||
#include "tm_workspace.h"
|
||||
#include "tm_work_object.h"
|
||||
#include "tm_source_file.h"
|
||||
#ifdef GEANY_PRIVATE
|
||||
#include "tm_file_entry.h"
|
||||
#include "tm_parser.h"
|
||||
#endif /* GEANY_PRIVATE */
|
||||
|
||||
/*! \mainpage Introduction
|
||||
\section Introduction
|
||||
/** @mainpage Introduction
|
||||
@section Introduction
|
||||
TagManager is a library and a set of utility programs which can be integrated into
|
||||
Integrated Development Environments to provide features such as code completion,
|
||||
calltips, etc. Tag Manager is based on <a href="http://ctags.sourceforge.net">
|
||||
Exuberent Ctags</a> with some added features.
|
||||
\section Licence
|
||||
@section Licence
|
||||
TagManager is <a href="http://www.gnu.org/philosophy/free-sw.html">free software</a>,
|
||||
licenced under the <a href="http://www.gnu.org/licenses/gpl.html">GPL</a>. You can only
|
||||
use it with free software (GPL compatible) projects. This is chiefly because it uses
|
||||
code from ctags which is under GPL.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
/** @file
|
||||
Include this file in all programs using the tag manager library. Including this
|
||||
automatically includes all the necessary files, namely, tm_tag.h, tm_source_file.h
|
||||
and tm_workspace.h
|
||||
|
||||
@ -1,298 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2001-2002, Biswapesh Chattopadhyay
|
||||
*
|
||||
* This source code is released for free distribution under the terms of the
|
||||
* GNU General Public License.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file tm_work_object.h
|
||||
* A TMWorkObject structure is the base class for TMSourceFile.
|
||||
*/
|
||||
|
||||
#include "general.h" /* must always come first */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <glib/gstdio.h>
|
||||
#ifdef G_OS_WIN32
|
||||
# define VC_EXTRALEAN
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h> /* for GetFullPathName */
|
||||
#endif
|
||||
|
||||
#include "tm_tag.h"
|
||||
#include "tm_work_object.h"
|
||||
|
||||
static GPtrArray *s_work_object_subclasses = NULL;
|
||||
|
||||
|
||||
static int get_path_max(const char *path)
|
||||
{
|
||||
#ifdef PATH_MAX
|
||||
return PATH_MAX;
|
||||
#else
|
||||
int path_max = pathconf(path, _PC_PATH_MAX);
|
||||
if (path_max <= 0)
|
||||
path_max = 4096;
|
||||
return path_max;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
/* realpath implementation for Windows found at http://bugzilla.gnome.org/show_bug.cgi?id=342926
|
||||
* this one is better than e.g. liberty's lrealpath because this one uses Win32 API and works
|
||||
* with special chars within the filename */
|
||||
static char *realpath (const char *pathname, char *resolved_path)
|
||||
{
|
||||
int size;
|
||||
|
||||
if (resolved_path != NULL)
|
||||
{
|
||||
int path_max = get_path_max(pathname);
|
||||
size = GetFullPathNameA (pathname, path_max, resolved_path, NULL);
|
||||
if (size > path_max)
|
||||
return NULL;
|
||||
else
|
||||
return resolved_path;
|
||||
}
|
||||
else
|
||||
{
|
||||
size = GetFullPathNameA (pathname, 0, NULL, NULL);
|
||||
resolved_path = g_new0 (char, size);
|
||||
GetFullPathNameA (pathname, size, resolved_path, NULL);
|
||||
return resolved_path;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
gchar *tm_get_real_path(const gchar *file_name)
|
||||
{
|
||||
if (file_name)
|
||||
{
|
||||
gsize len = get_path_max(file_name) + 1;
|
||||
gchar *path = g_malloc0(len);
|
||||
|
||||
if (realpath(file_name, path))
|
||||
return path;
|
||||
else
|
||||
g_free(path);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
guint tm_work_object_register(GFreeFunc free_func, TMUpdateFunc update_func, TMFindFunc find_func)
|
||||
{
|
||||
TMWorkObjectClass *object_class;
|
||||
if (NULL == s_work_object_subclasses)
|
||||
{
|
||||
s_work_object_subclasses = g_ptr_array_new();
|
||||
object_class = g_new(TMWorkObjectClass, 1);
|
||||
object_class->free_func = tm_work_object_free;
|
||||
object_class->update_func = NULL;
|
||||
object_class->find_func = NULL;
|
||||
g_ptr_array_add(s_work_object_subclasses, object_class);
|
||||
}
|
||||
object_class = g_new(TMWorkObjectClass, 1);
|
||||
object_class->free_func = free_func;
|
||||
object_class->update_func = update_func;
|
||||
object_class->find_func = find_func;
|
||||
g_ptr_array_add(s_work_object_subclasses, object_class);
|
||||
return (s_work_object_subclasses->len - 1);
|
||||
}
|
||||
|
||||
gboolean tm_work_object_init(TMWorkObject *work_object, guint type, const char *file_name
|
||||
, gboolean create)
|
||||
{
|
||||
struct stat s;
|
||||
int status;
|
||||
|
||||
if (file_name != NULL)
|
||||
{
|
||||
if (0 != (status = g_stat(file_name, &s)))
|
||||
{
|
||||
if (create)
|
||||
{
|
||||
FILE *f;
|
||||
if (NULL == (f = g_fopen(file_name, "a+")))
|
||||
{
|
||||
g_warning("Unable to create file %s", file_name);
|
||||
return FALSE;
|
||||
}
|
||||
fclose(f);
|
||||
status = g_stat(file_name, &s);
|
||||
}
|
||||
}
|
||||
if (0 != status)
|
||||
{
|
||||
/* g_warning("Unable to stat %s", file_name);*/
|
||||
return FALSE;
|
||||
}
|
||||
if (!S_ISREG(s.st_mode))
|
||||
{
|
||||
g_warning("%s: Not a regular file", file_name);
|
||||
return FALSE;
|
||||
}
|
||||
work_object->file_name = tm_get_real_path(file_name);
|
||||
work_object->short_name = strrchr(work_object->file_name, '/');
|
||||
if (work_object->short_name)
|
||||
++ work_object->short_name;
|
||||
else
|
||||
work_object->short_name = work_object->file_name;
|
||||
}
|
||||
else
|
||||
{
|
||||
work_object->file_name = NULL;
|
||||
work_object->short_name = NULL;
|
||||
}
|
||||
work_object->type = type;
|
||||
work_object->parent = NULL;
|
||||
work_object->analyze_time = 0;
|
||||
work_object->tags_array = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
time_t tm_get_file_timestamp(const char *file_name)
|
||||
{
|
||||
struct stat s;
|
||||
|
||||
g_return_val_if_fail(file_name, 0);
|
||||
|
||||
if (0 != g_stat(file_name, &s))
|
||||
{
|
||||
return (time_t) 0;
|
||||
}
|
||||
else
|
||||
return s.st_mtime;
|
||||
}
|
||||
|
||||
gboolean tm_work_object_is_changed(TMWorkObject *work_object)
|
||||
{
|
||||
return (gboolean) (work_object->analyze_time < tm_get_file_timestamp(work_object->file_name));
|
||||
}
|
||||
*/
|
||||
|
||||
TMWorkObject *tm_work_object_new(guint type, const char *file_name, gboolean create)
|
||||
{
|
||||
TMWorkObject *work_object = g_new(TMWorkObject, 1);
|
||||
if (!tm_work_object_init(work_object, type, file_name, create))
|
||||
{
|
||||
g_free(work_object);
|
||||
return NULL;
|
||||
}
|
||||
return work_object;
|
||||
}
|
||||
|
||||
void tm_work_object_destroy(TMWorkObject *work_object)
|
||||
{
|
||||
if (work_object)
|
||||
{
|
||||
g_free(work_object->file_name);
|
||||
if (work_object->tags_array)
|
||||
g_ptr_array_free(work_object->tags_array, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void tm_work_object_free(gpointer work_object)
|
||||
{
|
||||
if (NULL != work_object)
|
||||
{
|
||||
TMWorkObject *w = (TMWorkObject *) work_object;
|
||||
if ((w->type > 0) && (w->type < s_work_object_subclasses->len) &&
|
||||
(s_work_object_subclasses->pdata[w->type] != NULL))
|
||||
{
|
||||
GFreeFunc free_func =
|
||||
((TMWorkObjectClass *)s_work_object_subclasses->pdata[w->type])->free_func;
|
||||
if (NULL != free_func)
|
||||
free_func(work_object);
|
||||
return;
|
||||
}
|
||||
tm_work_object_destroy(w);
|
||||
g_free(work_object);
|
||||
}
|
||||
}
|
||||
|
||||
void tm_work_object_write_tags(TMWorkObject *work_object, FILE *file, guint attrs)
|
||||
{
|
||||
if (NULL != work_object->tags_array)
|
||||
{
|
||||
guint i;
|
||||
for (i=0; i < work_object->tags_array->len; ++i)
|
||||
tm_tag_write((TMTag *) g_ptr_array_index(work_object->tags_array, i)
|
||||
, file, (TMTagAttrType) attrs);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean tm_work_object_update(TMWorkObject *work_object, gboolean force
|
||||
, gboolean recurse, gboolean update_parent)
|
||||
{
|
||||
if ((NULL != work_object) && (work_object->type > 0) &&
|
||||
(work_object->type < s_work_object_subclasses->len) &&
|
||||
(s_work_object_subclasses->pdata[work_object->type] != NULL))
|
||||
{
|
||||
TMUpdateFunc update_func =
|
||||
((TMWorkObjectClass *)s_work_object_subclasses->pdata[work_object->type])->update_func;
|
||||
if (NULL != update_func)
|
||||
return update_func(work_object, force, recurse, update_parent);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
TMWorkObject *tm_work_object_find(TMWorkObject *work_object, const char *file_name
|
||||
, gboolean name_only)
|
||||
{
|
||||
if ((NULL != work_object) && (work_object->type > 0) &&
|
||||
(work_object->type < s_work_object_subclasses->len) &&
|
||||
(s_work_object_subclasses->pdata[work_object->type] != NULL))
|
||||
{
|
||||
TMFindFunc find_func =
|
||||
((TMWorkObjectClass *)s_work_object_subclasses->pdata[work_object->type])->find_func;
|
||||
if (NULL == find_func)
|
||||
{
|
||||
if (name_only)
|
||||
{
|
||||
const char *short_name = strrchr(file_name, '/');
|
||||
if (short_name)
|
||||
++ short_name;
|
||||
else
|
||||
short_name = file_name;
|
||||
if (0 == strcmp(work_object->short_name, short_name))
|
||||
return work_object;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *path = tm_get_real_path(file_name);
|
||||
int cmp = strcmp(work_object->file_name, file_name);
|
||||
g_free(path);
|
||||
if (0 == cmp)
|
||||
return work_object;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
return find_func(work_object, file_name, name_only);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void tm_work_object_dump(const TMWorkObject *w)
|
||||
{
|
||||
if (w)
|
||||
{
|
||||
fprintf(stderr, "%s", w->file_name);
|
||||
if (w->parent)
|
||||
fprintf(stderr, " <- %s\n", w->parent->file_name);
|
||||
else
|
||||
fprintf(stderr, " <- NULL\n");
|
||||
}
|
||||
}
|
||||
@ -1,191 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2001-2002, Biswapesh Chattopadhyay
|
||||
*
|
||||
* This source code is released for free distribution under the terms of the
|
||||
* GNU General Public License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TM_WORK_OBJECT_H
|
||||
#define TM_WORK_OBJECT_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <glib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* Macro to cast a pointer to (TMWorkObject *) */
|
||||
#define TM_WORK_OBJECT(work_object) ((TMWorkObject *) work_object)
|
||||
|
||||
/*!
|
||||
A TMWorkObject structure is the base class for TMSourceFile.
|
||||
This struct contains data common to all work objects, namely, a file name,
|
||||
time when the file was analyzed (for caching) and an array of tags which
|
||||
should be populated when the object is analyzed.
|
||||
*/
|
||||
typedef struct TMWorkObject
|
||||
{
|
||||
guint type; /*!< The type of object. Can be a source file or a project */
|
||||
char *file_name; /*!< Full file name (inc. path) of the work object */
|
||||
char *short_name; /*!< Just the name of the file (without the path) */
|
||||
struct TMWorkObject *parent;
|
||||
time_t analyze_time; /*!< UNUSED Time when the object was last analyzed */
|
||||
GPtrArray *tags_array; /*!< Tags obtained by parsing the object */
|
||||
} TMWorkObject;
|
||||
|
||||
|
||||
/*!
|
||||
Given a file name, returns a newly allocated string containing the realpath()
|
||||
of the file.
|
||||
\param file_name The original file_name
|
||||
\return A newly allocated string containing the real path to the file. NULL if none is available.
|
||||
*/
|
||||
gchar *tm_get_real_path(const gchar *file_name);
|
||||
|
||||
|
||||
/*!
|
||||
Deallocates a work object and it's component structures. The user can call this
|
||||
function directly since it will automatically call the correct deallocator function
|
||||
of the derived class if required.
|
||||
\param work_object Pointer to a work object or an object derived from it.
|
||||
*/
|
||||
void tm_work_object_free(gpointer work_object);
|
||||
|
||||
|
||||
#ifdef GEANY_PRIVATE
|
||||
|
||||
/* Evaluates to X is X is defined, else evaluates to Y */
|
||||
#define FALLBACK(X,Y) (X)?(X):(Y)
|
||||
|
||||
#define TM_OBJECT_TYPE(work_object) ((TMWorkObject *) work_object)->type /*< Type of the work object */
|
||||
#define TM_OBJECT_FILE(work_object) ((TMWorkObject *) work_object)->file_name /*< File name of the work object */
|
||||
#define TM_OBJECT_TAGS(work_object) ((TMWorkObject *) work_object)->tags_array /*< Tag array of the work object */
|
||||
|
||||
/* Prototype of the update function required to be written by all classes
|
||||
derived from TMWorkObject. The function should take a pointer to the
|
||||
object and a flag indicating whether the cache should be ignored, and
|
||||
update the object's tag array accordingly.
|
||||
\sa tm_work_object_update(), tm_workspace_update(),
|
||||
tm_source_file_update().
|
||||
*/
|
||||
typedef gboolean (*TMUpdateFunc) (TMWorkObject *work_object, gboolean force
|
||||
, gboolean recurse, gboolean update_parent);
|
||||
|
||||
/* Prototype of the find function required to be written by all classed
|
||||
derived from TMWorkObject. The function should take a pointer to the work
|
||||
object and a file name and return a pointer to the work object corresponding
|
||||
to the file name if the file is part of the object, and NULL otherwise.
|
||||
\sa tm_work_object_find()
|
||||
*/
|
||||
typedef TMWorkObject *(*TMFindFunc) (TMWorkObject *work_object, const char *file_name
|
||||
, gboolean name_only);
|
||||
|
||||
/*
|
||||
Contains pointers to functions necessary to handle virtual function calls
|
||||
correctly. To create a new object derived from TMWorkObject, you
|
||||
need to write the three functions specified as the members of this class and
|
||||
register your class before first use using tm_work_object_register()
|
||||
*/
|
||||
typedef struct _TMWorkObjectClass
|
||||
{
|
||||
GFreeFunc free_func; /* Function to free the derived object */
|
||||
TMUpdateFunc update_func; /* Function to update the derived object */
|
||||
TMFindFunc find_func; /* Function to locate contained work objects */
|
||||
} TMWorkObjectClass;
|
||||
|
||||
/*
|
||||
Initializes the work object structure. This function should be called by the
|
||||
initialization routine of the derived classes to ensure that the base members
|
||||
are initialized properly. The library user should not have to call this under
|
||||
any circumstance.
|
||||
\param work_object The work object to be initialized.
|
||||
\param type The type of the work object obtained by registering the derived class.
|
||||
\param file_name The name of the file corresponding to the work object.
|
||||
\param create Whether to create the file if it doesn't exist.
|
||||
\return TRUE on success, FALSE on failure.
|
||||
\sa tm_work_object_register()
|
||||
*/
|
||||
gboolean tm_work_object_init(TMWorkObject *work_object, guint type, const char *file_name
|
||||
, gboolean create);
|
||||
|
||||
/*
|
||||
Initializes a new TMWorkObject structure and returns a pointer to it. You shouldn't
|
||||
have to call this function.
|
||||
\return NULL on failure
|
||||
\sa tm_source_file_new()
|
||||
*/
|
||||
TMWorkObject *tm_work_object_new(guint type, const char *file_name, gboolean create);
|
||||
|
||||
/*
|
||||
Utility function - Given a file name, returns the timestamp of modification.
|
||||
\param file_name Full path to the file.
|
||||
\return Timestamp of the file's modification time. 0 on failure.
|
||||
*/
|
||||
time_t tm_get_file_timestamp(const char *file_name);
|
||||
|
||||
/*
|
||||
Destroys a work object's data without freeing the structure itself. It should
|
||||
be called by the deallocator function of classes derived from TMWorkObject. The
|
||||
user shouldn't have to call this function.
|
||||
*/
|
||||
void tm_work_object_destroy(TMWorkObject *work_object);
|
||||
|
||||
/*
|
||||
This function should be called exactly once by all classes derived from TMWorkObject,
|
||||
since it supplies a unique ID on each call and stores the functions to call for
|
||||
updation and deallocation of objects of the type allocated. The user should not
|
||||
have to use this function unless he/she wants to create a new class derived from
|
||||
TMWorkObject.
|
||||
\param free_func The function to call to free the derived object.
|
||||
\param update_func The function to call to update the derived object.
|
||||
\return A unique ID for the derived class.
|
||||
\sa TMSourceFile
|
||||
*/
|
||||
guint tm_work_object_register(GFreeFunc free_func, TMUpdateFunc update_func, TMFindFunc find_func);
|
||||
|
||||
/*
|
||||
Writes the tags for the work object to the file specified.
|
||||
\param work_object The work object whose tags need to be written.
|
||||
\param file The file to which the tags are to be written.
|
||||
\param attrs The attributes to write (Can be a bitmask).
|
||||
*/
|
||||
void tm_work_object_write_tags(TMWorkObject *work_object, FILE *file, guint attrs);
|
||||
|
||||
/*
|
||||
Updates the tags array if necessary. Automatically calls the update function
|
||||
of the type to which the object belongs.
|
||||
\param work_object Pointer to a work object or an object derived from it.
|
||||
\param force Whether the cache is to be ignored.
|
||||
\param recurse Whether to recurse into child work objects (for workspace).
|
||||
\param update_parent If set to TRUE, calls the update function of the parent if required.
|
||||
If you are calling this function, you should set this to TRUE.
|
||||
\return TRUE on success, FALSE on failure.
|
||||
\sa tm_source_file_update()
|
||||
*/
|
||||
gboolean tm_work_object_update(TMWorkObject *work_object, gboolean force
|
||||
, gboolean recurse, gboolean update_parent);
|
||||
|
||||
/*
|
||||
Finds the work object corresponding to the file name passed and returns a pointer
|
||||
to it. If not found, returns NULL. This is a virtual function which automatically
|
||||
calls the registered find function of teh derived object.
|
||||
\sa TMFindFunc
|
||||
*/
|
||||
TMWorkObject *tm_work_object_find(TMWorkObject *work_object, const char *file_name
|
||||
, gboolean name_only);
|
||||
|
||||
/* Dumps the contents of a work object - useful for debugging */
|
||||
void tm_work_object_dump(const TMWorkObject *w);
|
||||
|
||||
#endif /* GEANY_PRIVATE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* TM_WORK_OBJECT_H */
|
||||
File diff suppressed because it is too large
Load Diff
@ -13,7 +13,7 @@
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "tm_work_object.h"
|
||||
#include "tm_tag.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
@ -21,166 +21,63 @@ extern "C"
|
||||
#endif
|
||||
|
||||
|
||||
/*! The Tag Manager Workspace. This is a singleton work object containing a list
|
||||
of work objects - individual source files. There is also a global tag list
|
||||
/** The Tag Manager Workspace. This is a singleton object containing a list
|
||||
of individual source files. There is also a global tag list
|
||||
which can be loaded or created. This contains global tags gleaned from
|
||||
/usr/include, etc. and should be used for autocompletion, calltips, etc.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
TMWorkObject work_object; /*!< The parent work object */
|
||||
GPtrArray *global_tags; /*!< Global tags loaded at startup */
|
||||
GPtrArray *work_objects; /*!< An array of TMWorkObject pointers */
|
||||
GPtrArray *global_tags; /**< Global tags loaded at startup */
|
||||
GPtrArray *source_files; /**< An array of TMSourceFile pointers */
|
||||
GPtrArray *tags_array; /**< Sorted tags from all source files
|
||||
(just pointers to source file tags, the tag objects are owned by the source files) */
|
||||
GPtrArray *typename_array; /* Typename tags for syntax highlighting (pointers owned by source files) */
|
||||
} TMWorkspace;
|
||||
|
||||
/*! Adds a work object (source file) to the workspace.
|
||||
\param work_object The work object to add to the workspace.
|
||||
\return TRUE on success, FALSE on failure (e.g. object already exixts).
|
||||
*/
|
||||
gboolean tm_workspace_add_object(TMWorkObject *work_object);
|
||||
|
||||
/*! Removes a member object from the workspace if it exists.
|
||||
\param work_object Pointer to the work object to be removed.
|
||||
\param do_free Whether the work object is to be freed as well.
|
||||
\param update Whether to update workspace objects.
|
||||
\return TRUE on success, FALSE on failure (e.g. the work object does not exist).
|
||||
*/
|
||||
gboolean tm_workspace_remove_object(TMWorkObject *work_object, gboolean do_free, gboolean update);
|
||||
void tm_workspace_add_source_file(TMSourceFile *source_file);
|
||||
|
||||
void tm_workspace_remove_source_file(TMSourceFile *source_file);
|
||||
|
||||
void tm_workspace_add_source_files(GPtrArray *source_files);
|
||||
|
||||
void tm_workspace_remove_source_files(GPtrArray *source_files);
|
||||
|
||||
|
||||
#ifdef GEANY_PRIVATE
|
||||
|
||||
/* Since TMWorkspace is a singleton, you should not create multiple
|
||||
workspaces, but get a pointer to the workspace whenever required. The first
|
||||
time a pointer is requested, or a work object is added to the workspace,
|
||||
a workspace is created. Subsequent calls to the function will return the
|
||||
created workspace.
|
||||
*/
|
||||
const TMWorkspace *tm_get_workspace(void);
|
||||
|
||||
/* Given a file name, returns a pointer to the object if the object's file
|
||||
name is same as the passed file name, otherwise retruns NULL. This is an
|
||||
overloaded version of tm_work_object_find().
|
||||
\param work_object Pointer to the workspace.
|
||||
\param file_name The name of the file to search.
|
||||
\param name_only If you want to match just the name and not the full path.
|
||||
\return Pointer to the work object matching the file name (NULL if not found).
|
||||
\sa tm_work_object_find().
|
||||
*/
|
||||
TMWorkObject *tm_workspace_find_object(TMWorkObject *work_object, const char *file_name
|
||||
,gboolean name_only);
|
||||
|
||||
/* Loads the global tag list from the specified file. The global tag list should
|
||||
have been first created using tm_workspace_create_global_tags().
|
||||
\param tags_file The file containing global tags.
|
||||
\return TRUE on success, FALSE on failure.
|
||||
\sa tm_workspace_create_global_tags()
|
||||
*/
|
||||
gboolean tm_workspace_load_global_tags(const char *tags_file, gint mode);
|
||||
/*gboolean tm_workspace_load_global_tags(const char *tags_file);*/
|
||||
|
||||
/* Creates a list of global tags. Ideally, this should be created once during
|
||||
installations so that all users can use the same file. Thsi is because a full
|
||||
scale global tag list can occupy several megabytes of disk space.
|
||||
\param pre_process The pre-processing command. This is executed via system(),
|
||||
so you can pass stuff like 'gcc -E -dD -P `gnome-config --cflags gnome`'.
|
||||
\param includes Include 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, const char **includes,
|
||||
int includes_count, const char *tags_file, int lang);
|
||||
int includes_count, const char *tags_file, int lang);
|
||||
|
||||
/* Recreates the tag array of the workspace by collecting the tags of
|
||||
all member work objects. You shouldn't have to call this directly since
|
||||
this is called automatically by tm_workspace_update().
|
||||
*/
|
||||
void tm_workspace_recreate_tags_array(void);
|
||||
const GPtrArray *tm_workspace_find(const char *name, TMTagType type, TMTagAttrType *attrs,
|
||||
gboolean partial, langType lang);
|
||||
|
||||
/* Calls tm_work_object_update() for all workspace member work objects.
|
||||
Use if you want to globally refresh the workspace.
|
||||
\param workspace Pointer to the workspace.
|
||||
\param force Whether the cache should be ignored.
|
||||
\param recurse If set to TRUE, updates all children before updating the tag image.
|
||||
\param update_parent This parameter is ignored for the workspace since it is at the
|
||||
top of the work object hierarchy.
|
||||
\sa tm_work_object_update(), tm_source_file_update()
|
||||
*/
|
||||
gboolean tm_workspace_update(TMWorkObject *workspace, gboolean force
|
||||
, gboolean recurse, gboolean update_parent);
|
||||
|
||||
/* Dumps the workspace tree - useful for debugging */
|
||||
void tm_workspace_dump(void);
|
||||
|
||||
/* Returns all matching tags found in the workspace.
|
||||
\param name The name of the tag to find.
|
||||
\param type The tag types to return (TMTagType). Can be a bitmask.
|
||||
\param attrs The attributes to sort and dedup on (0 terminated integer array).
|
||||
\param partial Whether partial match is allowed.
|
||||
\param lang Specifies the language(see the table in parsers.h) of the tags to be found,
|
||||
-1 for all
|
||||
\return Array of matching tags. Do not free() it since it is a static member.
|
||||
*/
|
||||
const GPtrArray *tm_workspace_find(const char *name, int type, TMTagAttrType *attrs
|
||||
, gboolean partial, langType lang);
|
||||
|
||||
/* Returns all matching tags found in the workspace.
|
||||
\param name The name of the tag to find.
|
||||
\param scope The scope name of the tag to find, or NULL.
|
||||
\param type The tag types to return (TMTagType). Can be a bitmask.
|
||||
\param attrs The attributes to sort and dedup on (0 terminated integer array).
|
||||
\param partial Whether partial match is allowed.
|
||||
\param lang Specifies the language(see the table in parsers.h) of the tags to be found,
|
||||
-1 for all
|
||||
\return Array of matching tags. Do not free() it since it is a static member.
|
||||
*/
|
||||
const GPtrArray *
|
||||
tm_workspace_find_scoped (const char *name, const char *scope, gint type,
|
||||
TMTagAttrType *attrs, gboolean partial, langType lang, gboolean global_search);
|
||||
tm_workspace_find_scoped (const char *name, const char *scope, TMTagType type,
|
||||
TMTagAttrType *attrs, gboolean partial, langType lang, gboolean global_search);
|
||||
|
||||
/* Returns all matching members tags found in given struct/union/class name.
|
||||
\param name Name of the struct/union/class.
|
||||
\param file_tags A GPtrArray of edited file TMTag pointers (for search speedup, can be NULL).
|
||||
\return A GPtrArray of TMTag pointers to struct/union/class members */
|
||||
const GPtrArray *tm_workspace_find_scope_members(const GPtrArray *file_tags,
|
||||
const char *scope_name,
|
||||
gboolean find_global,
|
||||
gboolean no_definitions);
|
||||
|
||||
const GPtrArray *
|
||||
tm_workspace_find_namespace_members (const GPtrArray * file_tags, const char *name,
|
||||
gboolean search_global);
|
||||
void tm_workspace_add_source_file_noupdate(TMSourceFile *source_file);
|
||||
|
||||
/* Returns TMTag which "own" given line
|
||||
\param line Current line in edited file.
|
||||
\param file_tags A GPtrArray of edited file TMTag pointers.
|
||||
\param tag_types the tag types to include in the match
|
||||
\return TMTag pointers to owner tag. */
|
||||
const TMTag *tm_get_current_tag(GPtrArray *file_tags, const gulong line, const guint tag_types);
|
||||
void tm_workspace_update_source_file_buffer(TMSourceFile *source_file, guchar* text_buf,
|
||||
gsize buf_size);
|
||||
|
||||
/* Returns TMTag to function or method which "own" given line
|
||||
\param line Current line in edited file.
|
||||
\param file_tags A GPtrArray of edited file TMTag pointers.
|
||||
\return TMTag pointers to owner function. */
|
||||
const TMTag *tm_get_current_function(GPtrArray *file_tags, const gulong line);
|
||||
void tm_workspace_free(void);
|
||||
|
||||
/* Returns a list of parent classes for the given class name
|
||||
\param name Name of the class
|
||||
\return A GPtrArray of TMTag pointers (includes the TMTag for the class) */
|
||||
const GPtrArray *tm_workspace_get_parents(const gchar *name);
|
||||
|
||||
/* Frees the workspace structure and all child work objects. Use only when
|
||||
exiting from the main program.
|
||||
*/
|
||||
void tm_workspace_free(gpointer workspace);
|
||||
#ifdef TM_DEBUG
|
||||
void tm_workspace_dump(void);
|
||||
#endif /* TM_DEBUG */
|
||||
|
||||
/* Contains the id obtained by registering the TMWorkspace class as a child of
|
||||
TMWorkObject.
|
||||
\sa tm_work_object_register()
|
||||
*/
|
||||
extern guint workspace_class_id;
|
||||
|
||||
#endif /* GEANY_PRIVATE */
|
||||
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
# format=tagmanager
|
||||
FOO<EFBFBD>256<EFBFBD>0
|
||||
FOOÌ128ÎFOOÖ0
|
||||
FOO<EFBFBD>256<EFBFBD>0
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# format=tagmanager
|
||||
DigitÌ2048Ö0
|
||||
DigitÌ128Í(byte value)ÎDigitÖ0
|
||||
DigitÌ2048Ö0
|
||||
MainÌ128Í()ÎTestÖ0Ïpublic void
|
||||
TestÌ1Ö0
|
||||
operator DigitÌ128Í(byte b)ÎDigitÖ0
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# format=tagmanager
|
||||
DigitÌ2048Ö0
|
||||
DigitÌ128Í(byte value)ÎDigitÖ0
|
||||
DigitÌ2048Ö0
|
||||
MainÌ128Í()ÎTestÖ0Ïpublic void
|
||||
TestÌ1Ö0
|
||||
operator byteÌ128Í(Digit d)ÎDigitÖ0Ïpublic implicit
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
DataÌ1ÎProgramÖ0
|
||||
InterfaceÌ2048Ö0
|
||||
MyFuncÌ16ÎProgramÖ0
|
||||
ProgramĚ256Ö0
|
||||
ProgramÌ32ÎProgramÖ0
|
||||
ProgramĚ256Ö0
|
||||
contentsÌ64ÎDataÖ0
|
||||
iÌ16384ÎProgramÖ0
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
# format=tagmanager
|
||||
MainÌ128Í()ÎMainClassÖ0Ïpublic void
|
||||
MainClassÌ1Ö0
|
||||
PointĚ2048Ö0
|
||||
PointÌ128Í(int p1, int p2)ÎPointÖ0
|
||||
PointĚ2048Ö0
|
||||
xÌ8ÎPointÖ0Ïint
|
||||
yÌ8ÎPointÖ0Ïint
|
||||
|
||||
4
wscript
4
wscript
@ -118,10 +118,8 @@ ctags_sources = set([
|
||||
'tagmanager/ctags/vstring.c'])
|
||||
|
||||
tagmanager_sources = set([
|
||||
'tagmanager/src/tm_file_entry.c',
|
||||
'tagmanager/src/tm_source_file.c',
|
||||
'tagmanager/src/tm_tag.c',
|
||||
'tagmanager/src/tm_work_object.c',
|
||||
'tagmanager/src/tm_workspace.c'])
|
||||
|
||||
scintilla_sources = set(['scintilla/gtk/scintilla-marshal.c'])
|
||||
@ -555,7 +553,7 @@ def build(bld):
|
||||
bld.install_files('${PREFIX}/include/geany/tagmanager', '''
|
||||
tagmanager/src/tm_source_file.h
|
||||
tagmanager/src/tm_tag.h
|
||||
tagmanager/src/tm_tagmanager.h tagmanager/src/tm_work_object.h
|
||||
tagmanager/src/tm_tagmanager.h
|
||||
tagmanager/src/tm_workspace.h ''')
|
||||
# Docs
|
||||
base_dir = '${PREFIX}' if is_win32 else '${DOCDIR}'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user