Skip to content

Commit

Permalink
Cleaner and safer TMWorkspace API
Browse files Browse the repository at this point in the history
With the previous TMWorkspace API it was possible to make the workspace
inconsistent by e.g. removing source files and forgetting to update
workspace. This could lead to non-obvious and not immediately visible
crashes.

The new set of the public (but also Geany private) API calls always
updates the workspace accordingly and neither of the calls can lead
to an inconsistent state of the workspace.

In addition, perform some minor cleanups and simplifications - unify
parsing from buffer and from file, support "parsing" of 0-sized buffers
and improve documentation.
  • Loading branch information
techee committed Nov 2, 2014
1 parent 48718f4 commit 71cc1ec
Show file tree
Hide file tree
Showing 9 changed files with 259 additions and 266 deletions.
10 changes: 6 additions & 4 deletions plugins/geanyfunctions.h
Expand Up @@ -346,16 +346,18 @@
geany_functions->p_tm->tm_get_real_path
#define tm_source_file_new \
geany_functions->p_tm->tm_source_file_new
#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_update_source_file \
geany_functions->p_tm->tm_workspace_update_source_file
#define tm_source_file_free \
geany_functions->p_tm->tm_source_file_free
#define tm_workspace_remove_source_file \
geany_functions->p_tm->tm_workspace_remove_source_file
#define tm_workspace_update \
geany_functions->p_tm->tm_workspace_update
#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 \
Expand Down
2 changes: 1 addition & 1 deletion src/dialogs.c
Expand Up @@ -502,7 +502,7 @@ 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_source_file(doc->tm_file, TRUE);
tm_workspace_remove_source_file(doc->tm_file);
tm_source_file_free(doc->tm_file);
doc->tm_file = NULL;
}
Expand Down
17 changes: 4 additions & 13 deletions src/document.c
Expand Up @@ -714,7 +714,7 @@ 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_source_file(doc->tm_file, !main_status.quitting);
tm_workspace_remove_source_file(doc->tm_file);
tm_source_file_free(doc->tm_file);

if (doc->priv->tag_tree)
Expand Down Expand Up @@ -2501,20 +2501,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_workspace_update_source_file_buffer(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);
Expand Down Expand Up @@ -2614,7 +2605,7 @@ 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_source_file(doc->tm_file, TRUE);
tm_workspace_remove_source_file(doc->tm_file);
tm_source_file_free(doc->tm_file);
doc->tm_file = NULL;
}
Expand Down
9 changes: 5 additions & 4 deletions src/plugindata.h
Expand Up @@ -600,11 +600,12 @@ typedef struct TagManagerFuncs
{
gchar* (*tm_get_real_path) (const gchar *file_name);
TMSourceFile* (*tm_source_file_new) (const char *file_name, const char *name);
void (*tm_workspace_add_source_file) (TMSourceFile *source_file);
void (*tm_workspace_update_source_file) (TMSourceFile *source_file, gboolean update_workspace);
void (*tm_source_file_free) (TMSourceFile *source_file);
void (*tm_workspace_remove_source_file) (TMSourceFile *source_file, gboolean update_workspace);
void (*tm_workspace_update) (void);
void (*tm_workspace_add_source_file) (TMSourceFile *source_file);
void (*tm_workspace_update_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;

Expand Down
5 changes: 3 additions & 2 deletions src/plugins.c
Expand Up @@ -290,11 +290,12 @@ static KeybindingFuncs keybindings_funcs = {
static TagManagerFuncs tagmanager_funcs = {
&tm_get_real_path,
&tm_source_file_new,
&tm_source_file_free,
&tm_workspace_add_source_file,
&tm_workspace_update_source_file,
&tm_source_file_free,
&tm_workspace_remove_source_file,
&tm_workspace_update
&tm_workspace_add_source_files,
&tm_workspace_remove_source_files
};

static SearchFuncs search_funcs = {
Expand Down
96 changes: 29 additions & 67 deletions tagmanager/src/tm_source_file.c
Expand Up @@ -189,10 +189,11 @@ static gboolean tm_source_file_init(TMSourceFile *source_file, const char *file_
return TRUE;
}

/** Initializes a TMSourceFile structure and returns a pointer to it.
/** 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 TMSourceFile object.
* @return The created unparsed TMSourceFile object.
* */
TMSourceFile *tm_source_file_new(const char *file_name, const char *name)
{
Expand Down Expand Up @@ -220,7 +221,10 @@ static void tm_source_file_destroy(TMSourceFile *source_file)
source_file->tags_array = NULL;
}

/** Frees a TMSourceFile structure, including all contents */
/** 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)
Expand All @@ -230,72 +234,16 @@ void tm_source_file_free(TMSourceFile *source_file)
}
}

/* Parses the source file and regenarates the tags.
@param source_file The source file to parse
@return TRUE on success, FALSE on failure
*/
gboolean tm_source_file_parse(TMSourceFile *source_file)
{
const char *file_name;
gboolean status = TRUE;
guint passCount = 0;

if ((NULL == source_file) || (NULL == source_file->file_name))
{
g_warning("Attempt to parse NULL file");
return FALSE;
}

file_name = source_file->file_name;
if (NULL == LanguageTable)
{
initializeParsing();
installLanguageMapDefaults();
if (NULL == TagEntryFunction)
TagEntryFunction = tm_source_file_tags;
if (NULL == TagEntrySetArglistFunction)
TagEntrySetArglistFunction = tm_source_file_set_tag_arglist;
}
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))
{
tm_tags_array_free(source_file->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 ();
}
else
{
g_warning("%s: Unable to open %s", G_STRFUNC, file_name);
return FALSE;
}
++ passCount;
}
return status;
}

/* Parses the text-buffer and regenarates the tags.
/* 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_buffer_parse(TMSourceFile *source_file, guchar* text_buf, gint buf_size)
gboolean tm_source_file_parse(TMSourceFile *source_file, guchar* text_buf, gint buf_size,
gboolean use_buffer)
{
const char *file_name;
gboolean status = TRUE;
Expand All @@ -306,9 +254,11 @@ gboolean tm_source_file_buffer_parse(TMSourceFile *source_file, guchar* text_buf
return FALSE;
}

if ((NULL == text_buf) || (0 == buf_size))
if (use_buffer && (NULL == text_buf || 0 == buf_size))
{
g_warning("Attempt to parse a NULL text buffer");
/* Empty buffer, "parse" by setting empty tag array */
tm_tags_array_free(source_file->tags_array, FALSE);
return TRUE;
}

file_name = source_file->file_name;
Expand Down Expand Up @@ -342,7 +292,7 @@ gboolean tm_source_file_buffer_parse(TMSourceFile *source_file, guchar* text_buf
while ((TRUE == status) && (passCount < 3))
{
tm_tags_array_free(source_file->tags_array, FALSE);
if (bufferOpen (text_buf, buf_size, file_name, source_file->lang))
if (use_buffer && bufferOpen (text_buf, buf_size, file_name, source_file->lang))
{
if (LanguageTable [source_file->lang]->parser != NULL)
{
Expand All @@ -354,6 +304,18 @@ gboolean tm_source_file_buffer_parse(TMSourceFile *source_file, guchar* text_buf
status = LanguageTable [source_file->lang]->parser2 (passCount);
bufferClose ();
}
else if (!use_buffer && 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 ();
}
else
{
g_warning("Unable to open %s", file_name);
Expand Down
7 changes: 3 additions & 4 deletions tagmanager/src/tm_source_file.h
Expand Up @@ -41,7 +41,7 @@ typedef struct
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; /**< Tags obtained by parsing the object */
GPtrArray *tags_array; /**< Sorted tag array obtained by parsing the object */
} TMSourceFile;

TMSourceFile *tm_source_file_new(const char *file_name, const char *name);
Expand All @@ -57,9 +57,8 @@ const gchar *tm_source_file_get_lang_name(gint lang);

gint tm_source_file_get_named_lang(const gchar *name);

gboolean tm_source_file_parse(TMSourceFile *source_file);

gboolean tm_source_file_buffer_parse(TMSourceFile *source_file, guchar* text_buf, gint buf_size);
gboolean tm_source_file_parse(TMSourceFile *source_file, guchar* text_buf, gint buf_size,
gboolean use_buffer);

#endif /* GEANY_PRIVATE */

Expand Down

0 comments on commit 71cc1ec

Please sign in to comment.