[geany/geany] 71cc1e: Cleaner and safer TMWorkspace API

Jiří Techet git-noreply at xxxxx
Sun Nov 2 10:39:57 UTC 2014


Branch:      refs/heads/master
Author:      Jiří Techet <techet at gmail.com>
Committer:   Jiří Techet <techet at gmail.com>
Date:        Sun, 02 Nov 2014 10:39:57 UTC
Commit:      71cc1ecb2084deb9e3c7dd8ba1e88946a1767280
             https://github.com/geany/geany/commit/71cc1ecb2084deb9e3c7dd8ba1e88946a1767280

Log Message:
-----------
Cleaner and safer TMWorkspace API

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.


Modified Paths:
--------------
    plugins/geanyfunctions.h
    src/dialogs.c
    src/document.c
    src/plugindata.h
    src/plugins.c
    tagmanager/src/tm_source_file.c
    tagmanager/src/tm_source_file.h
    tagmanager/src/tm_workspace.c
    tagmanager/src/tm_workspace.h

Modified: plugins/geanyfunctions.h
10 lines changed, 6 insertions(+), 4 deletions(-)
===================================================================
@@ -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 \


Modified: src/dialogs.c
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -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;
 	}


Modified: src/document.c
17 lines changed, 4 insertions(+), 13 deletions(-)
===================================================================
@@ -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)
@@ -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);
@@ -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;
 		}


Modified: src/plugindata.h
9 lines changed, 5 insertions(+), 4 deletions(-)
===================================================================
@@ -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;
 


Modified: src/plugins.c
5 lines changed, 3 insertions(+), 2 deletions(-)
===================================================================
@@ -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 = {


Modified: tagmanager/src/tm_source_file.c
96 lines changed, 29 insertions(+), 67 deletions(-)
===================================================================
@@ -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)
 {
@@ -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)
@@ -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;
@@ -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;
@@ -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)
 				{
@@ -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);


Modified: tagmanager/src/tm_source_file.h
7 lines changed, 3 insertions(+), 4 deletions(-)
===================================================================
@@ -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);
@@ -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 */
 


Modified: tagmanager/src/tm_workspace.c
366 lines changed, 200 insertions(+), 166 deletions(-)
===================================================================
@@ -13,9 +13,7 @@
  wide tag information.
 
  The workspace is intended to contain a list of global tags
- and a set of individual source files. You need not use the
- workspace, though, to use tag manager, unless you need things like global tags
- and a place to store all current open files.
+ and a set of individual source files.
 */
 
 #include "general.h"
@@ -37,6 +35,7 @@
 
 static TMWorkspace *theWorkspace = NULL;
 
+
 static gboolean tm_create_workspace(void)
 {
 	theWorkspace = g_new(TMWorkspace, 1);
@@ -48,6 +47,7 @@ static gboolean tm_create_workspace(void)
 	return TRUE;
 }
 
+
 /* Frees the workspace structure and all child source files. Use only when
  exiting from the main program.
 */
@@ -69,6 +69,7 @@ void tm_workspace_free(void)
 	theWorkspace = NULL;
 }
 
+
 /* 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 source file is added to the workspace,
@@ -82,8 +83,60 @@ const TMWorkspace *tm_get_workspace(void)
 	return theWorkspace;
 }
 
+
+static void tm_workspace_merge_tags(GPtrArray **big_array, GPtrArray *small_array)
+{
+	TMTagAttrType sort_attrs[] = { tm_tag_attr_name_t, tm_tag_attr_file_t,
+		tm_tag_attr_scope_t, tm_tag_attr_type_t, tm_tag_attr_arglist_t, 0};
+
+	GPtrArray *new_tags = tm_tags_merge(*big_array, small_array, sort_attrs, FALSE);
+	/* tags owned by TMSourceFile - free just the pointer array */
+	g_ptr_array_free(*big_array, TRUE);
+	*big_array = new_tags;
+}
+
+
+static void update_source_file(TMSourceFile *source_file, guchar* text_buf,
+	gint buf_size, gboolean use_buffer, gboolean update_workspace)
+{
+#ifdef TM_DEBUG
+	g_message("Source file updating based on source file %s", source_file->file_name);
+#endif
+
+	if (update_workspace)
+	{
+		/* tm_source_file_parse() deletes the tag objects - remove the tags from
+		 * workspace while they exist and can be scanned */
+		tm_tags_remove_file_tags(source_file, theWorkspace->tags_array);
+		tm_tags_remove_file_tags(source_file, theWorkspace->typename_array);
+	}
+	tm_source_file_parse(source_file, text_buf, buf_size, use_buffer);
+	tm_tags_sort(source_file->tags_array, NULL, FALSE, TRUE);
+	if (update_workspace)
+	{
+		GPtrArray *sf_typedefs;
+
+#ifdef TM_DEBUG
+		g_message("Updating workspace from source file");
+#endif
+		tm_workspace_merge_tags(&theWorkspace->tags_array, source_file->tags_array);
+		
+		sf_typedefs = tm_tags_extract(source_file->tags_array, TM_GLOBAL_TYPE_MASK);
+		tm_workspace_merge_tags(&theWorkspace->typename_array, sf_typedefs);
+		g_ptr_array_free(sf_typedefs, TRUE);
+	}
+#ifdef TM_DEBUG
+	else
+		g_message("Skipping workspace update because update_workspace is %s",
+			update_workspace?"TRUE":"FALSE");
+
+#endif
+}
+
+
 /** Adds a source file to the workspace. At some point, tm_workspace_update_source_file()
- has to be called to create the source file's tag array.
+ has to be called to parse the source file, create the source file's tag array
+ and update the workspace tag arrays.
  @param source_file The source file to add to the workspace.
 */
 void tm_workspace_add_source_file(TMSourceFile *source_file)
@@ -93,12 +146,42 @@ void tm_workspace_add_source_file(TMSourceFile *source_file)
 	g_ptr_array_add(theWorkspace->source_files, source_file);
 }
 
-/** Removes a source file from the workspace if it exists.
+
+/** Parses the source file, updates its tag array and the workspace tag arrays.
+ @param source_file The source file to update.
+*/
+void tm_workspace_update_source_file(TMSourceFile *source_file)
+{
+	update_source_file(source_file, NULL, 0, FALSE, TRUE);
+}
+
+
+/* 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.
+*/
+void tm_workspace_update_source_file_buffer(TMSourceFile *source_file, guchar* text_buf,
+	gint buf_size)
+{
+	update_source_file(source_file, text_buf, buf_size, TRUE, TRUE);
+}
+
+
+/** Removes a source file from the workspace if it exists. This function also removes
+ the tags belonging to this file from the workspace. To completely free the TMSourceFile 
+ pointer call tm_source_file_free() on it.
  @param source_file Pointer to the source file to be removed.
- @param update_workspace Whether to update workspace objects. Has to be TRUE unless
-	tm_workspace_update() is called later.
 */
-void tm_workspace_remove_source_file(TMSourceFile *source_file, gboolean update_workspace)
+void tm_workspace_remove_source_file(TMSourceFile *source_file)
 {
 	guint i;
 	
@@ -109,23 +192,117 @@ void tm_workspace_remove_source_file(TMSourceFile *source_file, gboolean update_
 	{
 		if (theWorkspace->source_files->pdata[i] == source_file)
 		{
-			if (update_workspace)
-			{
-				tm_tags_remove_file_tags(source_file, theWorkspace->tags_array);
-				tm_tags_remove_file_tags(source_file, theWorkspace->typename_array);
-			}
+			tm_tags_remove_file_tags(source_file, theWorkspace->tags_array);
+			tm_tags_remove_file_tags(source_file, theWorkspace->typename_array);
 			g_ptr_array_remove_index_fast(theWorkspace->source_files, i);
 			return;
 		}
 	}
 }
 
+
+/* Recreates workspace tag array from all member TMSourceFile objects. Use if you 
+ want to globally refresh the workspace. This function does not call tm_source_file_update()
+ which should be called before this function on source files which need to be
+ reparsed.
+*/
+static void tm_workspace_update(void)
+{
+	guint i, j;
+	TMSourceFile *source_file;
+	TMTagAttrType sort_attrs[] = { tm_tag_attr_name_t, tm_tag_attr_file_t
+		, tm_tag_attr_scope_t, tm_tag_attr_type_t, tm_tag_attr_arglist_t, 0};
+
+#ifdef TM_DEBUG
+	g_message("Recreating workspace tags array");
+#endif
+
+	g_ptr_array_set_size(theWorkspace->tags_array, 0);
+
+#ifdef TM_DEBUG
+	g_message("Total %d objects", theWorkspace->source_files->len);
+#endif
+	for (i=0; i < theWorkspace->source_files->len; ++i)
+	{
+		source_file = theWorkspace->source_files->pdata[i];
+#ifdef TM_DEBUG
+		g_message("Adding tags of %s", source_file->file_name);
+#endif
+		if (source_file->tags_array->len > 0)
+		{
+			for (j = 0; j < source_file->tags_array->len; ++j)
+			{
+				g_ptr_array_add(theWorkspace->tags_array,
+					source_file->tags_array->pdata[j]);
+			}
+		}
+	}
+#ifdef TM_DEBUG
+	g_message("Total: %d tags", theWorkspace->tags_array->len);
+#endif
+	tm_tags_sort(theWorkspace->tags_array, sort_attrs, TRUE, FALSE);
+	
+	theWorkspace->typename_array = tm_tags_extract(theWorkspace->tags_array, TM_GLOBAL_TYPE_MASK);
+}
+
+
+/** Adds multiple source files to the workspace and updates the workspace tag arrays.
+ This is more efficient than calling tm_workspace_add_source_file() and
+ tm_workspace_update_source_file() separately for each of the files.
+ @param source_files The source files to be added to the workspace.
+*/
+void tm_workspace_add_source_files(GPtrArray *source_files)
+{
+	guint i;
+	
+	for (i = 0; i < source_files->len; i++)
+	{
+		TMSourceFile *source_file = source_files->pdata[i];
+		
+		tm_workspace_add_source_file(source_file);
+		update_source_file(source_file, NULL, 0, FALSE, FALSE);
+	}
+	
+	tm_workspace_update();
+}
+
+
+/** Removes multiple source files from the workspace and updates the workspace tag
+ arrays. This is more efficient than calling tm_workspace_remove_source_file()
+ separately for each of the files. To completely free the TMSourceFile pointers
+ call tm_source_file_free() on each of them.
+ @param source_files The source files to be removed from the workspace.
+*/
+void tm_workspace_remove_source_files(GPtrArray *source_files)
+{
+	guint i, j;
+	
+	//TODO: sort both arrays by pointer value and remove in single pass
+	for (i = 0; i < source_files->len; i++)
+	{
+		TMSourceFile *source_file = source_files->pdata[i];
+		
+		for (j = 0; j < theWorkspace->source_files->len; j++)
+		{
+			if (theWorkspace->source_files->pdata[j] == source_file)
+			{
+				g_ptr_array_remove_index_fast(theWorkspace->source_files, j);
+				break;
+			}
+		}
+	}
+	
+	tm_workspace_update();
+}
+
+
 static TMTagAttrType global_tags_sort_attrs[] =
 {
 	tm_tag_attr_name_t, tm_tag_attr_scope_t,
 	tm_tag_attr_type_t, tm_tag_attr_arglist_t, 0
 };
 
+
 /* 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.
@@ -194,6 +371,7 @@ gboolean tm_workspace_load_global_tags(const char *tags_file, gint mode)
 	return TRUE;
 }
 
+
 static guint tm_file_inode_hash(gconstpointer key)
 {
 	struct stat file_stat;
@@ -209,6 +387,7 @@ static guint tm_file_inode_hash(gconstpointer key)
 	}
 }
 
+
 static void tm_move_entries_to_g_list(gpointer key, gpointer value, gpointer user_data)
 {
 	GList **pp_list = (GList**)user_data;
@@ -219,6 +398,7 @@ static void tm_move_entries_to_g_list(gpointer key, gpointer value, gpointer use
 	*pp_list = g_list_prepend(*pp_list, value);
 }
 
+
 static void write_includes_file(FILE *fp, GList *includes_files)
 {
 	GList *node;
@@ -263,6 +443,7 @@ static void append_to_temp_file(FILE *fp, GList *file_list)
 	}
 }
 
+
 static gchar *create_temp_file(const gchar *tpl)
 {
 	gchar *name;
@@ -277,6 +458,7 @@ static gchar *create_temp_file(const gchar *tpl)
 	return name;
 }
 
+
 /* 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.
@@ -427,7 +609,7 @@ gboolean tm_workspace_create_global_tags(const char *pre_process, const char **i
 		temp_file = NULL;
 	}
 	source_file = tm_source_file_new(temp_file2, tm_source_file_get_lang_name(lang));
-	tm_workspace_update_source_file(source_file, FALSE);
+	update_source_file(source_file, NULL, 0, FALSE, FALSE);
 	if (NULL == source_file)
 	{
 		g_unlink(temp_file2);
@@ -471,158 +653,6 @@ gboolean tm_workspace_create_global_tags(const char *pre_process, const char **i
 	return TRUE;
 }
 
-/** Recreates workspace tag array from all member TMSourceFile objects. Use if you 
- want to globally refresh the workspace. This function does not call tm_source_file_update()
- which should be called before this function on source files which need to be
- reparsed.
-*/
-void tm_workspace_update(void)
-{
-	guint i, j;
-	TMSourceFile *source_file;
-	TMTagAttrType sort_attrs[] = { tm_tag_attr_name_t, tm_tag_attr_file_t
-		, tm_tag_attr_scope_t, tm_tag_attr_type_t, tm_tag_attr_arglist_t, 0};
-
-#ifdef TM_DEBUG
-	g_message("Recreating workspace tags array");
-#endif
-
-	g_ptr_array_set_size(theWorkspace->tags_array, 0);
-
-#ifdef TM_DEBUG
-	g_message("Total %d objects", theWorkspace->source_files->len);
-#endif
-	for (i=0; i < theWorkspace->source_files->len; ++i)
-	{
-		source_file = theWorkspace->source_files->pdata[i];
-#ifdef TM_DEBUG
-		g_message("Adding tags of %s", source_file->file_name);
-#endif
-		if (source_file->tags_array->len > 0)
-		{
-			for (j = 0; j < source_file->tags_array->len; ++j)
-			{
-				g_ptr_array_add(theWorkspace->tags_array,
-					source_file->tags_array->pdata[j]);
-			}
-		}
-	}
-#ifdef TM_DEBUG
-	g_message("Total: %d tags", theWorkspace->tags_array->len);
-#endif
-	tm_tags_sort(theWorkspace->tags_array, sort_attrs, TRUE, FALSE);
-	
-	theWorkspace->typename_array = tm_tags_extract(theWorkspace->tags_array, TM_GLOBAL_TYPE_MASK);
-}
-
-static void tm_workspace_merge_tags(GPtrArray **big_array, GPtrArray *small_array)
-{
-	TMTagAttrType sort_attrs[] = { tm_tag_attr_name_t, tm_tag_attr_file_t,
-		tm_tag_attr_scope_t, tm_tag_attr_type_t, tm_tag_attr_arglist_t, 0};
-
-	GPtrArray *new_tags = tm_tags_merge(*big_array, small_array, sort_attrs, FALSE);
-	/* tags owned by TMSourceFile - free just the pointer array */
-	g_ptr_array_free(*big_array, TRUE);
-	*big_array = new_tags;
-}
-
-/** Updates the source file by reparsing. 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 update_workspace Whether to update workspace objects. Has to be TRUE unless
-	tm_workspace_update() is called later.
-*/
-void tm_workspace_update_source_file(TMSourceFile *source_file, gboolean update_workspace)
-{
-#ifdef TM_DEBUG
-	g_message("Source file updating based on source file %s", source_file->file_name);
-#endif
-
-	if (update_workspace)
-	{
-		/* tm_source_file_parse() deletes the tag objects - remove the tags from
-		 * workspace while they exist and can be scanned */
-		tm_tags_remove_file_tags(source_file, theWorkspace->tags_array);
-		tm_tags_remove_file_tags(source_file, theWorkspace->typename_array);
-	}
-	tm_source_file_parse(source_file);
-	tm_tags_sort(source_file->tags_array, NULL, FALSE, TRUE);
-	if (update_workspace)
-	{
-		GPtrArray *sf_typedefs;
-
-#ifdef TM_DEBUG
-		g_message("Updating workspace from source file");
-#endif
-		tm_workspace_merge_tags(&theWorkspace->tags_array, source_file->tags_array);
-		
-		sf_typedefs = tm_tags_extract(source_file->tags_array, TM_GLOBAL_TYPE_MASK);
-		tm_workspace_merge_tags(&theWorkspace->typename_array, sf_typedefs);
-		g_ptr_array_free(sf_typedefs, TRUE);
-	}
-#ifdef TM_DEBUG
-	else
-		g_message("Skipping workspace update because update_workspace is %s",
-			update_workspace?"TRUE":"FALSE");
-
-#endif
-}
-
-
-/* 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_workspace If set to TRUE, sends an update signal to the workspace 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.
-*/
-void tm_workspace_update_source_file_buffer(TMSourceFile *source_file, guchar* text_buf,
-			gint buf_size, gboolean update_workspace)
-{
-#ifdef TM_DEBUG
-	g_message("Buffer updating based on source file %s", source_file->file_name);
-#endif
-
-	if (update_workspace)
-	{
-		/* tm_source_file_parse() deletes the tag objects - remove the tags from
-		 * workspace while they exist and can be scanned */
-		tm_tags_remove_file_tags(source_file, theWorkspace->tags_array);
-	}
-	tm_source_file_buffer_parse (source_file, text_buf, buf_size);
-	tm_tags_sort(source_file->tags_array, NULL, FALSE, TRUE);
-	if (update_workspace)
-	{
-		GPtrArray *sf_typedefs;
-
-#ifdef TM_DEBUG
-		g_message("Updating workspace from buffer..");
-#endif
-		tm_workspace_merge_tags(&theWorkspace->tags_array, source_file->tags_array);
-
-		sf_typedefs = tm_tags_extract(source_file->tags_array, TM_GLOBAL_TYPE_MASK);
-		tm_workspace_merge_tags(&theWorkspace->typename_array, sf_typedefs);
-		g_ptr_array_free(sf_typedefs, TRUE);
-	}
-#ifdef TM_DEBUG
-	else
-		g_message("Skipping workspace update because update_workspace is %s",
-			update_workspace?"TRUE":"FALSE");
-
-#endif
-}
 
 /* Returns all matching tags found in the workspace.
  @param name The name of the tag to find.
@@ -717,6 +747,7 @@ const GPtrArray *tm_workspace_find(const char *name, TMTagType type, TMTagAttrTy
 	return tags;
 }
 
+
 static gboolean match_langs(gint lang, const TMTag *tag)
 {
 	if (tag->file)
@@ -732,6 +763,7 @@ static gboolean match_langs(gint lang, const TMTag *tag)
 	return FALSE;
 }
 
+
 /* scope can be NULL.
  * lang can be -1 */
 static guint
@@ -946,6 +978,7 @@ find_scope_members_tags (const GPtrArray * all, GPtrArray * tags,
 	return (int) tags->len;
 }
 
+
 /* 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).
@@ -1322,6 +1355,7 @@ tm_workspace_find_namespace_members (const GPtrArray * file_tags, const char *na
 	return tags;
 }
 
+
 /* 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) */


Modified: tagmanager/src/tm_workspace.h
13 lines changed, 8 insertions(+), 5 deletions(-)
===================================================================
@@ -32,16 +32,19 @@ typedef struct
 	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) */
+	GPtrArray *typename_array; /* Typename tags for syntax highlighting (pointers owned by source files) */
 } TMWorkspace;
 
+
 void tm_workspace_add_source_file(TMSourceFile *source_file);
 
-void tm_workspace_remove_source_file(TMSourceFile *source_file, gboolean update_workspace);
+void tm_workspace_update_source_file(TMSourceFile *source_file);
+
+void tm_workspace_remove_source_file(TMSourceFile *source_file);
 
-void tm_workspace_update_source_file(TMSourceFile *source_file, gboolean update_workspace);
+void tm_workspace_add_source_files(GPtrArray *source_files);
 
-void tm_workspace_update(void);
+void tm_workspace_remove_source_files(GPtrArray *source_files);
 
 
 #ifdef GEANY_PRIVATE
@@ -68,7 +71,7 @@ const GPtrArray *tm_workspace_find_scope_members(const GPtrArray *file_tags,
 const TMTag *tm_get_current_tag(GPtrArray *file_tags, const gulong line, const TMTagType tag_types);
 
 void tm_workspace_update_source_file_buffer(TMSourceFile *source_file, guchar* text_buf,
-	gint buf_size, gboolean update_workspace);
+	gint buf_size);
 
 void tm_workspace_free(void);
 



--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).


More information about the Commits mailing list