[anjuta] language-support-cpp-java: Rewrite of cpp-java-assist.c



commit 6da6e4ce54845c03780676015c627fc033f829af
Author: Johannes Schmid <jhs gnome org>
Date:   Fri Mar 5 21:06:29 2010 +0100

    language-support-cpp-java: Rewrite of cpp-java-assist.c
    
    * Take async operation better into account
    * Document code (gtk-doc comments)
    * Code more solid (g_asserts, etc.)

 .../language-support-cpp-java/cpp-java-assist.c    | 1285 ++++++++------------
 1 files changed, 527 insertions(+), 758 deletions(-)
---
diff --git a/plugins/language-support-cpp-java/cpp-java-assist.c b/plugins/language-support-cpp-java/cpp-java-assist.c
index 0cc1de0..1f6464d 100644
--- a/plugins/language-support-cpp-java/cpp-java-assist.c
+++ b/plugins/language-support-cpp-java/cpp-java-assist.c
@@ -67,17 +67,14 @@ struct _CppJavaAssistPriv {
 	IAnjutaSymbolManager* isymbol_manager;
 	IAnjutaEditorAssist* iassist;
 	IAnjutaEditorTip* itip;
-	
-	/* Last used cache */
-	gchar *search_cache;
-	gchar *scope_context_cache;
-	gchar *pre_word;
-	gchar *calltip_context;
-	
+
 	GCompletion *completion_cache;
-	gboolean editor_only;
-	IAnjutaIterable* start_iter;
 	
+	gboolean member_completion;
+	gboolean autocompletion;
+	IAnjutaIterable* start_iter;
+	gchar* pre_word;
+
 	gboolean async_file;
 	gboolean async_system;
 	gboolean async_project;
@@ -87,50 +84,112 @@ struct _CppJavaAssistPriv {
 	GCancellable* cancel_project;	
 };
 
-static gchar*
-completion_function (gpointer data)
+typedef struct
 {
-	CppJavaAssistTag * tag = (CppJavaAssistTag*) data;
-	return tag->name;
-}
+	gboolean is_func;
+	gchar* name;
+} ProposalData;
 
-static gint
-completion_compare (gconstpointer a, gconstpointer b)
-{
-	CppJavaAssistTag * tag_a = (CppJavaAssistTag*) a;
-	CppJavaAssistTag * tag_b = (CppJavaAssistTag*) b;
-	gint cmp;
-	
-	cmp = strcmp (tag_a->name, tag_b->name);
-	if (cmp == 0) cmp = tag_a->type - tag_b->type;
-	
-	return cmp;
+/**
+ * cpp_java_assist_proposal_new:
+ * @symbol: IAnjutaSymbol to create the proposal for
+ *
+ * Creates a new IAnjutaEditorAssistProposal for symbol
+ *
+ * Returns: a newly allocated IAnjutaEditorAssistProposal
+ */
+static IAnjutaEditorAssistProposal*
+cpp_java_assist_proposal_new (IAnjutaSymbol* symbol)
+{
+	IAnjutaEditorAssistProposal* proposal = g_new0 (IAnjutaEditorAssistProposal, 1);
+	IAnjutaSymbolType type = ianjuta_symbol_get_sym_type (symbol, NULL);
+	ProposalData* data = g_new0 (ProposalData, 1);
+
+	data->name = g_strdup (ianjuta_symbol_get_name (symbol, NULL));
+	switch (type)
+	{
+		case IANJUTA_SYMBOL_TYPE_PROTOTYPE:
+		case IANJUTA_SYMBOL_TYPE_FUNCTION:
+		case IANJUTA_SYMBOL_TYPE_METHOD:
+		case IANJUTA_SYMBOL_TYPE_MACRO_WITH_ARG:
+			proposal->label = g_strdup_printf ("%s()", ianjuta_symbol_get_name (symbol, NULL));
+			data->is_func = TRUE;
+			break;
+		default:
+			proposal->label = g_strdup (ianjuta_symbol_get_name (symbol, NULL));
+			data->is_func = FALSE;
+	}
+	proposal->data = data;
+	/* Icons are lifetime object of the symbol-db so we can cast here */
+	proposal->icon = (GdkPixbuf*) ianjuta_symbol_get_icon (symbol, NULL);
+	return proposal;
 }
 
+/**
+ * cpp_java_assist_proposal_free:
+ * @proposal: the proposal to free
+ * 
+ * Frees the proposal
+ */
 static void
-cpp_java_assist_tag_destroy (CppJavaAssistTag *tag)
+cpp_java_assist_proposal_free (IAnjutaEditorAssistProposal* proposal)
 {
-	g_free (tag->name);
-	if (tag->icon)
-		g_object_unref (tag->icon);
-	g_free (tag);
+	ProposalData* data = proposal->data;
+	g_free (data->name);
+	g_free (data);
+	g_free (proposal->label);
+	g_free (proposal);
 }
 
-static gboolean
-is_scope_context_character (gchar ch)
+/**
+ * anjuta_propsal_completion_func:
+ * @data: an IAnjutaEditorAssistProposal
+ *
+ * Returns: the name of the completion func
+ */
+static gchar*
+anjuta_proposal_completion_func (gpointer data)
 {
-	if (g_ascii_isspace (ch))
-		return FALSE;
-	if (g_ascii_isalnum (ch))
-		return TRUE;
-	if (ch == '_' || ch == '.' || ch == ':' || ch == '>' || ch == '-')
-		return TRUE;
+	IAnjutaEditorAssistProposal* proposal = data;
+	ProposalData* prop_data = proposal->data;
 	
-	return FALSE;
-}	
+	return prop_data->name;
+}
+
+/**
+ * cpp_java_assist_create_completion_from_symbols:
+ * @symbols: Symbol iteration
+ * 
+ * Create a list of IAnjutaEditorAssistProposals from a list of symbols
+ *
+ * Returns: a newly allocated GList of newly allocated proposals. Free 
+ * with cpp_java_assist_proposal_free()
+ */
+static GList*
+cpp_java_assist_create_completion_from_symbols (IAnjutaIterable* symbols)
+{
+	GList* list = NULL;
+	do
+	{
+		IAnjutaSymbol* symbol = IANJUTA_SYMBOL (symbols);
+		IAnjutaEditorAssistProposal* proposal = cpp_java_assist_proposal_new (symbol);	
+
+		list = g_list_append (list, proposal);
+	}
+	while (ianjuta_iterable_next (symbols, NULL));
 
+	return list;
+}
+
+/**
+ * cpp_java_assist_is_word_character:
+ * @ch: character to check
+ *
+ * Returns: TRUE if ch is a valid word character, FALSE otherwise
+ */
+ 
 static gboolean
-is_word_character (gchar ch)
+cpp_java_assist_is_word_character (gchar ch)
 {
 	if (g_ascii_isspace (ch))
 		return FALSE;
@@ -143,600 +202,88 @@ is_word_character (gchar ch)
 }	
 
 /**
- * If mergeable is NULL than no merge will be made with iter elements, elsewhere
- * mergeable will be returned with iter elements.
+ * cpp_java_assist_get_pre_word:
+ * @editor: Editor object
+ * @iter: current cursor position
+ * @start_iter: return location for the start_iter (if a preword was found)
+ *
+ * Search for the current typed word
+ *
+ * Returns: The current word (needs to be freed) or NULL if no word was found
  */
-static GCompletion*
-create_completion (CppJavaAssist* assist, IAnjutaIterable* iter,
-				   GCompletion* mergeable)
-{	
-	GCompletion *completion;	
-	
-	if (mergeable == NULL)
-		completion = g_completion_new (completion_function);
-	else
-		completion = mergeable;
-	
-	GList* suggestions = NULL;
-	do
-	{
-		const gchar* name = ianjuta_symbol_get_name (IANJUTA_SYMBOL(iter), NULL);
-		if (name != NULL)
-		{
-			CppJavaAssistTag *tag = g_new0 (CppJavaAssistTag, 1);
-			const GdkPixbuf* sym_icon;
-			tag->name = g_strdup (name);			
-			tag->type = ianjuta_symbol_get_sym_type (IANJUTA_SYMBOL (iter),
-													 NULL);
-			sym_icon = ianjuta_symbol_get_icon (IANJUTA_SYMBOL(iter), NULL);
-			tag->icon = sym_icon ? gdk_pixbuf_copy (sym_icon) : NULL;
-			tag->is_func = (tag->type == IANJUTA_SYMBOL_TYPE_PROTOTYPE ||
-			                tag->type == IANJUTA_SYMBOL_TYPE_FUNCTION ||
-							tag->type == IANJUTA_SYMBOL_TYPE_METHOD ||
-							tag->type == IANJUTA_SYMBOL_TYPE_MACRO_WITH_ARG);
-			if (!g_list_find_custom (suggestions, tag, completion_compare))
-				suggestions = g_list_prepend (suggestions, tag);
-			else
-				g_free (tag);
-		}
-		else
-			break;
-	}
-	while (ianjuta_iterable_next (iter, NULL));
-	suggestions = g_list_sort (suggestions, completion_compare);
-	g_completion_add_items (completion, suggestions);
-	return completion;
-}
-
-static void cpp_java_assist_update_autocomplete(CppJavaAssist* assist);
-
-static void
-on_query_data (gint search_id, IAnjutaIterable* iter, CppJavaAssist* assist)
-{
-	assist->priv->completion_cache = create_completion (assist,
-	                                                    iter,
-	                                                    assist->priv->completion_cache);
-	cpp_java_assist_update_autocomplete(assist);	
-}
-
-static void
-system_finished (AnjutaAsyncNotify* notify, CppJavaAssist* assist)
-{
-	assist->priv->async_system = FALSE;
-}
-
-static void
-file_finished (AnjutaAsyncNotify* notify, CppJavaAssist* assist)
-{
-	assist->priv->async_file = FALSE;
-}
-
-static void
-project_finished (AnjutaAsyncNotify* notify, CppJavaAssist* assist)
-{
-	assist->priv->async_project = FALSE;
-}
-
-#define SCOPE_BRACE_JUMP_LIMIT 50
-
-static gchar*
-cpp_java_assist_get_scope_context (IAnjutaEditor* editor,
-								   const gchar *scope_operator,
-								   IAnjutaIterable *iter)
-{
-	IAnjutaIterable* end;
-	gchar ch, *scope_chars = NULL;
-	gboolean out_of_range = FALSE;
-	gboolean scope_chars_found = FALSE;
-	
-	end = ianjuta_iterable_clone (iter, NULL);
-	ianjuta_iterable_next (end, NULL);
-	
-	ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter), 0, NULL);
-	
-	while (ch)
-	{
-		if (is_scope_context_character (ch))
-		{
-			scope_chars_found = TRUE;
-		}
-		else if (ch == ')')
-		{
-			if (!cpp_java_util_jump_to_matching_brace (iter, ch, SCOPE_BRACE_JUMP_LIMIT))
-			{
-				out_of_range = TRUE;
-				break;
-			}
-		}
-		else
-			break;
-		if (!ianjuta_iterable_previous (iter, NULL))
-		{
-			out_of_range = TRUE;
-			break;
-		}		
-		ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter), 0, NULL);
-	}
-	if (scope_chars_found)
-	{
-		IAnjutaIterable* begin;
-		begin = ianjuta_iterable_clone (iter, NULL);
-		if (!out_of_range)
-			ianjuta_iterable_next (begin, NULL);
-		scope_chars = ianjuta_editor_get_text (editor, begin, end, NULL);
-		g_object_unref (begin);
-	}
-	g_object_unref (end);
-	return scope_chars;
-}
-
 static gchar*
-cpp_java_assist_get_pre_word (IAnjutaEditor* editor, IAnjutaIterable *iter)
+cpp_java_assist_get_pre_word (IAnjutaEditor* editor, IAnjutaIterable *iter, IAnjutaIterable** start_iter)
 {
-	IAnjutaIterable *end;
+	IAnjutaIterable *end = ianjuta_iterable_clone (iter, NULL);
+	IAnjutaIterable *begin = ianjuta_iterable_clone (iter, NULL);
 	gchar ch, *preword_chars = NULL;
 	gboolean out_of_range = FALSE;
 	gboolean preword_found = FALSE;
 	
-	end = ianjuta_iterable_clone (iter, NULL);
-	ianjuta_iterable_next (end, NULL);
-
-	ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter), 0, NULL);
+	/* Cursor points after the current characters, move back */
+	ianjuta_iterable_previous (begin, NULL);
 	
-	while (ch && is_word_character (ch))
+	ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (begin), 0, NULL);
+	
+	while (ch && cpp_java_assist_is_word_character (ch))
 	{
 		preword_found = TRUE;
-		if (!ianjuta_iterable_previous (iter, NULL))
+		if (!ianjuta_iterable_previous (begin, NULL))
 		{
 			out_of_range = TRUE;
 			break;
 		}
-		ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter), 0, NULL);
+		ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (begin), 0, NULL);
 	}
 	
 	if (preword_found)
 	{
-		IAnjutaIterable *begin = ianjuta_iterable_clone (iter, NULL);
 		if (!out_of_range)
 			ianjuta_iterable_next (begin, NULL);
 		preword_chars = ianjuta_editor_get_text (editor, begin, end, NULL);
-		g_object_unref (begin);
-	}
-	g_object_unref (end);
-	return preword_chars;
-}
-
-static void
-cpp_java_assist_destroy_completion_cache (CppJavaAssist *assist)
-{
-	if (assist->priv->async_file)
-	{
-		g_cancellable_cancel (assist->priv->cancel_file);
-		assist->priv->async_file = FALSE;
-	}
-	g_cancellable_reset (assist->priv->cancel_file);
-	
-	if (assist->priv->async_system)
-	{
-		g_cancellable_cancel (assist->priv->cancel_system);
-		assist->priv->async_system = FALSE;
-	}
-	g_cancellable_reset (assist->priv->cancel_system);
-	
-	if (assist->priv->async_project)
-	{
-		g_cancellable_cancel (assist->priv->cancel_project);
-		assist->priv->async_project = FALSE;
-	}
-	g_cancellable_reset (assist->priv->cancel_project);
-	
-	if (assist->priv->search_cache)
-	{
-		g_free (assist->priv->search_cache);
-		assist->priv->search_cache = NULL;
-	}
-	if (assist->priv->scope_context_cache)
-	{
-		g_free (assist->priv->scope_context_cache);
-		assist->priv->scope_context_cache = NULL;
-	} 
-	if (assist->priv->completion_cache)
-	{
-		GList* items = assist->priv->completion_cache->items;
-		if (items)
-		{
-			g_list_foreach (items, (GFunc) cpp_java_assist_tag_destroy, NULL);
-			g_completion_clear_items (assist->priv->completion_cache);
-		}
-		g_completion_free (assist->priv->completion_cache);
-		assist->priv->completion_cache = NULL;
-	}
-}
-
-static void free_proposal (IAnjutaEditorAssistProposal* proposal)
-{
-	g_free (proposal->label);
-	g_free(proposal);
-}
-
-static void
-cpp_java_assist_update_autocomplete (CppJavaAssist *assist)
-{
-	gint length;
-	GList *completion_list;
-	GList *node, *suggestions = NULL;
-
-	gboolean queries_active = (assist->priv->async_file || assist->priv->async_project || assist->priv->async_system);
-	
-	if (assist->priv->completion_cache == NULL)
-	{
-		ianjuta_editor_assist_proposals (assist->priv->iassist, IANJUTA_PROVIDER(assist),
-		                                 NULL, !queries_active, NULL);
-		return;
-	}
-
-	if (assist->priv->pre_word && strlen(assist->priv->pre_word))
-	{
-	    g_completion_complete (assist->priv->completion_cache, assist->priv->pre_word, NULL);
-
-		completion_list = assist->priv->completion_cache->cache;
+		*start_iter = begin;
 	}
 	else
 	{
-		completion_list = assist->priv->completion_cache->items;
-	}
-
-	length = g_list_length (completion_list);
-
-	DEBUG_PRINT ("Populating %d proposals", length);
-
-	/* Hide autocompletion if we only have one item */
-	if (length == 1)
-	{
-		CppJavaAssistTag* tag = completion_list->data;
-		if (tag->name && assist->priv->pre_word && g_str_equal (tag->name, assist->priv->pre_word))
-		{
-			ianjuta_editor_assist_proposals (assist->priv->iassist, IANJUTA_PROVIDER(assist),
-		                                 NULL, !queries_active, NULL);
-		}
-	}	
-	for (node = completion_list; node != NULL; node = g_list_next (node))
-	{
-		CppJavaAssistTag *tag = node->data;
-		IAnjutaEditorAssistProposal* proposal = g_new0(IAnjutaEditorAssistProposal, 1);
-
-		if (tag->is_func)
-			proposal->label = g_strdup_printf ("%s()", tag->name);
-		else
-			proposal->label = g_strdup(tag->name);
-
-		proposal->data = tag;
-		proposal->icon = tag->icon;
-		suggestions = g_list_prepend (suggestions, proposal);
-	}
-	suggestions = g_list_reverse (suggestions);
-	ianjuta_editor_assist_proposals (assist->priv->iassist, IANJUTA_PROVIDER(assist),
-	                                 suggestions, !queries_active, NULL);
-	g_list_foreach (suggestions, (GFunc) free_proposal, NULL);
-	g_list_free (suggestions);
-}
-
-static void
-cpp_java_assist_create_word_completion_cache (CppJavaAssist *assist)
-{	
-	cpp_java_assist_destroy_completion_cache (assist);
-	if (!assist->priv->pre_word || strlen(assist->priv->pre_word) < 3)
-		return;
-
-	gchar *pattern = g_strconcat (assist->priv->pre_word, "%", NULL);
-		
-	if (IANJUTA_IS_FILE (assist->priv->iassist))
-	{
-		GFile *file = ianjuta_file_get_file (IANJUTA_FILE (assist->priv->iassist), NULL);
-		if (file != NULL)
-		{
-			AnjutaAsyncNotify* notify = anjuta_async_notify_new();
-			g_signal_connect (notify, "finished", G_CALLBACK(file_finished), assist);
-			assist->priv->async_file = TRUE;
-			ianjuta_symbol_manager_search_file_async (assist->priv->isymbol_manager,
-																				 IANJUTA_SYMBOL_TYPE_UNDEF,
-																				 TRUE,
-																				 IANJUTA_SYMBOL_FIELD_SIMPLE|
-			                                          							 IANJUTA_SYMBOL_FIELD_TYPE|
-			                                          							 IANJUTA_SYMBOL_FIELD_ACCESS|
-			                                          							 IANJUTA_SYMBOL_FIELD_KIND,
-																				 pattern, file, -1, -1, 
-			    																 assist->priv->cancel_file,
-																				 notify, (IAnjutaSymbolManagerSearchCallback) on_query_data, assist,
-																				 NULL);
-			g_object_unref (file);
-		}
-	}
-	{
-		/* This will avoid duplicates of FUNCTION and PROTOTYPE */
-		IAnjutaSymbolType types = IANJUTA_SYMBOL_TYPE_MAX & ~IANJUTA_SYMBOL_TYPE_FUNCTION;
-		AnjutaAsyncNotify* notify = anjuta_async_notify_new();
-		g_signal_connect (notify, "finished", G_CALLBACK(project_finished), assist);
-		assist->priv->async_project = TRUE;
-		ianjuta_symbol_manager_search_project_async (assist->priv->isymbol_manager,
-											 types,
-											 TRUE,
-											 IANJUTA_SYMBOL_FIELD_SIMPLE|
-			                                 IANJUTA_SYMBOL_FIELD_TYPE|
-			                                 IANJUTA_SYMBOL_FIELD_ACCESS|
-			                                 IANJUTA_SYMBOL_FIELD_KIND,
-											 pattern, IANJUTA_SYMBOL_MANAGER_SEARCH_FS_PUBLIC, -1, -1, 
-											 assist->priv->cancel_project,
-											 notify, (IAnjutaSymbolManagerSearchCallback) on_query_data, assist,
-											 NULL);
-		
-	}
-	{
-		IAnjutaSymbolType types = IANJUTA_SYMBOL_TYPE_MAX & ~IANJUTA_SYMBOL_TYPE_FUNCTION;
-		AnjutaAsyncNotify* notify = anjuta_async_notify_new();
-		g_signal_connect (notify, "finished", G_CALLBACK(system_finished), assist);
-		assist->priv->async_system = TRUE;
-		ianjuta_symbol_manager_search_system_async (assist->priv->isymbol_manager,
-											 types,
-											 TRUE,
-											 IANJUTA_SYMBOL_FIELD_SIMPLE|
-			                                 IANJUTA_SYMBOL_FIELD_TYPE|
-			                                 IANJUTA_SYMBOL_FIELD_ACCESS|
-			                                 IANJUTA_SYMBOL_FIELD_KIND,
-											 pattern, IANJUTA_SYMBOL_MANAGER_SEARCH_FS_PUBLIC, -1, -1,
-											 assist->priv->cancel_system,
-											 notify, (IAnjutaSymbolManagerSearchCallback) on_query_data, assist,
-		                                            NULL);
-	}
-	g_free (pattern);
-	g_free (assist->priv->search_cache);
-	assist->priv->search_cache = g_strdup (assist->priv->pre_word);
-
-	DEBUG_PRINT ("Started async search for: %s", assist->priv->pre_word);
-}
-
-static gchar*
-cpp_java_assist_get_calltip_context (CppJavaAssist *assist,
-                                     IAnjutaIterable *iter)
-{
-	gchar ch;
-	gchar *context = NULL;	
-	
-	ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter), 0, NULL);
-	if (ch == ')')
-	{
-		if (!cpp_java_util_jump_to_matching_brace (iter, ')', -1))
-			return NULL;
-		if (!ianjuta_iterable_previous (iter, NULL))
-			return NULL;
-	}
-	if (ch != '(')
-	{
-		if (!cpp_java_util_jump_to_matching_brace (iter, ')',
-												   BRACE_SEARCH_LIMIT))
-			return NULL;
-	}
-	
-	/* Skip white spaces */
-	while (ianjuta_iterable_previous (iter, NULL)
-		&& g_ascii_isspace (ianjuta_editor_cell_get_char
-								(IANJUTA_EDITOR_CELL (iter), 0, NULL)));
-
-	context = cpp_java_assist_get_scope_context
-		(IANJUTA_EDITOR (assist->priv->itip), "(", iter);
-
-	/* Point iter to the first character of the scope to align calltip correctly */
-	ianjuta_iterable_next (iter, NULL);
-	
-	return context;
-}
-
-static GList*
-cpp_java_assist_create_calltips (IAnjutaIterable* iter)
-{
-	GList* tips = NULL;
-	if (iter)
-	{
-		do
-		{
-			IAnjutaSymbol* symbol = IANJUTA_SYMBOL(iter);
-			const gchar* name = ianjuta_symbol_get_name(symbol, NULL);
-			if (name != NULL)
-			{
-				const gchar* args = ianjuta_symbol_get_args(symbol, NULL);
-				const gchar* rettype = ianjuta_symbol_get_returntype (symbol, NULL);
-				gchar* print_args;
-				gchar* separator;
-				gchar* white_name;
-				gint white_count = 0;
-
-				if (!rettype)
-					rettype = "";
-				else
-					white_count += strlen(rettype) + 1;
-				
-				white_count += strlen(name) + 1;
-				
-				white_name = g_strnfill (white_count, ' ');
-				separator = g_strjoin (NULL, ", \n", white_name, NULL);
-				
-				gchar** argv;
-				if (!args)
-					args = "()";
-				
-				argv = g_strsplit (args, ",", -1);
-				print_args = g_strjoinv (separator, argv);
-				
-				gchar* tip = g_strdup_printf ("%s %s %s", rettype, name, print_args);
-				
-				if (!g_list_find_custom (tips, tip, (GCompareFunc) strcmp))
-					tips = g_list_append (tips, tip);
-				
-				g_strfreev (argv);
-				g_free (print_args);
-				g_free (separator);
-				g_free (white_name);
-			}
-			else
-				break;
-		}
-		while (ianjuta_iterable_next (iter, NULL));
-	}
-	return tips;
-}
-
-static gboolean
-cpp_java_assist_show_calltip (CppJavaAssist *assist, gchar *call_context,
-							  IAnjutaIterable *position_iter)
-{	
-	GList *tips = NULL;
-
-	/* Search file */
-	if (IANJUTA_IS_FILE (assist->priv->itip))
-	{
-		GFile *file = ianjuta_file_get_file (IANJUTA_FILE (assist->priv->itip), NULL);
-
-		if (file != NULL)
-		{
-			IAnjutaIterable* iter_file = 
-				ianjuta_symbol_manager_search_file (assist->priv->isymbol_manager,
-				                                    IANJUTA_SYMBOL_TYPE_PROTOTYPE|
-				                                    IANJUTA_SYMBOL_TYPE_FUNCTION|
-				                                    IANJUTA_SYMBOL_TYPE_METHOD|
-				                                    IANJUTA_SYMBOL_TYPE_MACRO_WITH_ARG,
-				                                    TRUE, 
-				                                    IANJUTA_SYMBOL_FIELD_SIMPLE|
-				                                    IANJUTA_SYMBOL_FIELD_TYPE|
-				                                    IANJUTA_SYMBOL_FIELD_ACCESS|
-				                                    IANJUTA_SYMBOL_FIELD_KIND,
-				                                    call_context, file, -1, -1, NULL);
-												 
-			if (iter_file) 
-			{
-				tips = cpp_java_assist_create_calltips (iter_file);
-				g_object_unref (iter_file);
-			}
-			g_object_unref (file);
-		}
-	}
-
-	/* Search Project */
-	IAnjutaIterable* iter_project = 
-		ianjuta_symbol_manager_search_project (assist->priv->isymbol_manager,
-									   IANJUTA_SYMBOL_TYPE_PROTOTYPE|
-									   IANJUTA_SYMBOL_TYPE_FUNCTION|
-									   IANJUTA_SYMBOL_TYPE_METHOD|
-									   IANJUTA_SYMBOL_TYPE_MACRO_WITH_ARG,
-									   TRUE, 
-									   IANJUTA_SYMBOL_FIELD_SIMPLE|
-			                           IANJUTA_SYMBOL_FIELD_TYPE|
-			                           IANJUTA_SYMBOL_FIELD_ACCESS|
-			                           IANJUTA_SYMBOL_FIELD_KIND,
-									   call_context, IANJUTA_SYMBOL_MANAGER_SEARCH_FS_PUBLIC,
-									   -1, -1, NULL);
-	if (iter_project)
-	{
-		tips = g_list_concat (tips, cpp_java_assist_create_calltips (iter_project));
-		g_object_unref (iter_project);
-	}
-	
-	/* Search global */
-	IAnjutaIterable* iter_global = 
-		ianjuta_symbol_manager_search_system (assist->priv->isymbol_manager,
-									   IANJUTA_SYMBOL_TYPE_PROTOTYPE|
-									   IANJUTA_SYMBOL_TYPE_FUNCTION|
-									   IANJUTA_SYMBOL_TYPE_METHOD|
-									   IANJUTA_SYMBOL_TYPE_MACRO_WITH_ARG,
-									   TRUE, 
-									   IANJUTA_SYMBOL_FIELD_SIMPLE|
-			                           IANJUTA_SYMBOL_FIELD_TYPE|
-			                           IANJUTA_SYMBOL_FIELD_ACCESS|
-			                           IANJUTA_SYMBOL_FIELD_KIND,		    
-									   call_context, IANJUTA_SYMBOL_MANAGER_SEARCH_FS_PUBLIC,
-									   -1, -1, NULL);
-	if (iter_global)
-	{
-		tips = g_list_concat (tips, cpp_java_assist_create_calltips (iter_global));
-		g_object_unref (iter_global);
+		g_object_unref (begin);
+		*start_iter = NULL;
 	}
 	
-	if (tips)
-	{	
-		ianjuta_editor_tip_show (IANJUTA_EDITOR_TIP(assist->priv->itip), tips,
-										 position_iter, 0,
-										 NULL);
-		g_list_foreach (tips, (GFunc) g_free, NULL);
-		g_list_free (tips);
-		return TRUE;
-	}
-	return FALSE;
+	g_object_unref (end);
+	return preword_chars;
 }
 
+/**
+ * cpp_java_assist_update_pre_word:
+ * @assist: self
+ * @pre_word: new pre_word
+ *
+ * Updates the current pre_word
+ */
 static void
-cpp_java_assist_calltip (CppJavaAssist *assist,
-					      			   gboolean calltips, gboolean backspace)
+cpp_java_assist_update_pre_word (CppJavaAssist* assist, const gchar* pre_word)
 {
-	IAnjutaEditor *editor;
-	IAnjutaIterable *iter;
-	
-	if (!calltips)
-		return; /* Nothing to do */
-	
-	editor = IANJUTA_EDITOR (assist->priv->itip);
-	
-	iter = ianjuta_editor_get_position (editor, NULL);
-	ianjuta_iterable_previous (iter, NULL);
-	if (calltips)
+	g_free (assist->priv->pre_word);
+	if (pre_word)
 	{
-		gchar *call_context =
-			cpp_java_assist_get_calltip_context (assist, iter);
-		if (call_context)
-		{
-			if (ianjuta_editor_tip_visible (IANJUTA_EDITOR_TIP (editor), NULL))
-			{
-				if (assist->priv->calltip_context &&
-				    !g_str_equal (call_context, assist->priv->calltip_context))
-				{
-					cpp_java_assist_show_calltip (assist, call_context,
-					                              iter);
-					g_free (assist->priv->calltip_context);
-					assist->priv->calltip_context = g_strdup(call_context);
-				}
-			}
-			else
-			{
-				cpp_java_assist_show_calltip (assist, call_context,
-				                              iter);
-				g_free (assist->priv->calltip_context);
-				assist->priv->calltip_context = g_strdup(call_context);	
-			}
-		}
-		else
-		{
-			ianjuta_editor_tip_cancel (IANJUTA_EDITOR_TIP(assist->priv->itip), NULL);
-			g_free (assist->priv->calltip_context);
-			assist->priv->calltip_context = NULL;
-		}
-		g_free (call_context);
+		DEBUG_PRINT ("Setting pre_word to %s", pre_word);
+		assist->priv->pre_word = g_strdup (pre_word);
 	}
-	g_object_unref (iter);	
 }
 
-static void
-on_editor_char_added (IAnjutaEditor *editor, IAnjutaIterable *insert_pos,
-					  gchar ch, CppJavaAssist *assist)
-{
-	gboolean enable_calltips =
-		anjuta_preferences_get_bool_with_default (assist->priv->preferences,
-												 PREF_CALLTIP_ENABLE,
-												 TRUE);
-	cpp_java_assist_calltip(assist, enable_calltips, (ch == '\b'));
-}
-
-#define BRACE_LIMIT 100
-
+/**
+ * cpp_java_assist_is_expression_separator:
+ * @c: character to check
+ * @skip_braces: whether to skip closing braces
+ * @iter: current cursor position
+ *
+ * Checks if a character seperates a C/C++ expression. It can skip brances
+ * because they might not really end the expression
+ *
+ * Returns: TRUE if the characters seperates an expression, FALSE otherwise
+ */
 static gboolean
-is_expression_separator (gchar c, gboolean skip_braces, IAnjutaIterable* iter)
+cpp_java_assist_is_expression_separator (gchar c, gboolean skip_braces, IAnjutaIterable* iter)
 {
 	IAnjutaEditorAttribute attrib = ianjuta_editor_cell_get_attribute (IANJUTA_EDITOR_CELL(iter),
 	                                                                   NULL);
@@ -748,7 +295,7 @@ is_expression_separator (gchar c, gboolean skip_braces, IAnjutaIterable* iter)
 	
 	if (c == ')' && skip_braces)
 	{
-		cpp_java_util_jump_to_matching_brace (iter, c, BRACE_LIMIT);
+		cpp_java_util_jump_to_matching_brace (iter, c, BRACE_SEARCH_LIMIT);
 		return TRUE;
 	}
 	else if (c == ')' && !skip_braces)
@@ -763,8 +310,16 @@ is_expression_separator (gchar c, gboolean skip_braces, IAnjutaIterable* iter)
 	return FALSE;
 }
 
+/**
+ * cpp_java_assist_parse_expression:
+ * @assist: self,
+ * @iter: current cursor position
+ * @start_iter: return location for the start of the completion
+ * 
+ * Returns: An iter of a list of IAnjutaSymbols or NULL
+ */
 static IAnjutaIterable*
-cpp_java_parse_expression (CppJavaAssist* assist, IAnjutaIterable* iter, IAnjutaIterable** start_iter)
+cpp_java_assist_parse_expression (CppJavaAssist* assist, IAnjutaIterable* iter, IAnjutaIterable** start_iter)
 {
 	IAnjutaEditor* editor = IANJUTA_EDITOR (assist->priv->iassist);
 	IAnjutaIterable* res = NULL;
@@ -772,14 +327,16 @@ cpp_java_parse_expression (CppJavaAssist* assist, IAnjutaIterable* iter, IAnjuta
 	gboolean op_start = FALSE;
 	gboolean ref_start = FALSE;
 	gchar* stmt = NULL;
+
+	/* Cursor points after the current characters, move back */
+	ianjuta_iterable_previous (cur_pos, NULL);
 	
 	/* Search for a operator in the current line */
 	do 
 	{
 		gchar ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL(cur_pos), 0, NULL);
 		
-		if (is_expression_separator(ch, FALSE, iter)) {
-			DEBUG_PRINT ("found char '%c' which is an expression_separator", ch);
+		if (cpp_java_assist_is_expression_separator(ch, FALSE, iter)) {
 			break;
 		}
 
@@ -790,6 +347,7 @@ cpp_java_parse_expression (CppJavaAssist* assist, IAnjutaIterable* iter, IAnjuta
 			IAnjutaIterable* pre_word_end = ianjuta_iterable_clone (iter, NULL);
 			IAnjutaIterable* stmt_end = ianjuta_iterable_clone (pre_word_start, NULL);
 
+			
 			/* we need to pass to the parser all the statement included the last operator,
 			 * being it "." or "->" or "::"
 			 * Increase the end bound of the statement.
@@ -807,18 +365,17 @@ cpp_java_parse_expression (CppJavaAssist* assist, IAnjutaIterable* iter, IAnjuta
 			{
 				ianjuta_iterable_next (pre_word_start, NULL);
 			}
-			/* Move the end character to be behind the current typed character */
-			ianjuta_iterable_next (pre_word_end, NULL);
 			
-			assist->priv->pre_word = ianjuta_editor_get_text (editor,
-			                                                  pre_word_start, pre_word_end, NULL);
+			cpp_java_assist_update_pre_word (assist, 
+			                                 ianjuta_editor_get_text (editor,
+			                                                          pre_word_start, pre_word_end, NULL));
 
 			/* Try to get the name of the variable */
 			while (ianjuta_iterable_previous (cur_pos, NULL))
 			{
 				gchar word_ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL(cur_pos), 0, NULL);
 				
-				if (is_expression_separator(word_ch, FALSE, cur_pos)) 
+				if (cpp_java_assist_is_expression_separator(word_ch, FALSE, cur_pos)) 
 					break;				
 			}
 			ianjuta_iterable_next (cur_pos, NULL);
@@ -826,6 +383,7 @@ cpp_java_parse_expression (CppJavaAssist* assist, IAnjutaIterable* iter, IAnjuta
 			                                cur_pos, stmt_end, NULL);
 			*start_iter = pre_word_start;
 			g_object_unref (stmt_end);
+			g_object_unref (pre_word_end);
 			break;
 		}
 		else if (ch == '>')
@@ -884,192 +442,392 @@ cpp_java_parse_expression (CppJavaAssist* assist, IAnjutaIterable* iter, IAnjuta
 	return res;
 }
 
-static gboolean
-cpp_java_assist_valid_iter (CppJavaAssist* assist, IAnjutaIterable* iter)
+/** 
+ * cpp_java_assist_create_completion_cache:
+ * @assist: self
+ *
+ * Create a new completion_cache object
+ */
+static void
+cpp_java_assist_create_completion_cache (CppJavaAssist* assist)
 {
-	IAnjutaEditorCell* cell = IANJUTA_EDITOR_CELL (iter);
-	IAnjutaEditorAttribute attribute = ianjuta_editor_cell_get_attribute (cell, NULL);
-	return (attribute != IANJUTA_EDITOR_STRING && attribute != IANJUTA_EDITOR_COMMENT);
+	g_assert (assist->priv->completion_cache == NULL);
+	assist->priv->completion_cache = 
+		g_completion_new (anjuta_proposal_completion_func);
 }
 
+/**
+ * cpp_java_assist_clear_completion_cache
+ * @assist: self
+ *
+ * Clear the completion cache, aborting all async operations
+ */
 static void
-cpp_java_assist_populate (IAnjutaProvider* self, IAnjutaIterable* iter, GError** e)
+cpp_java_assist_clear_completion_cache (CppJavaAssist* assist)
 {
-	CppJavaAssist* assist = CPP_JAVA_ASSIST (self);
-	IAnjutaEditor *editor;
-	gboolean autocomplete = anjuta_preferences_get_bool_with_default (assist->priv->preferences,
-	                                                                  PREF_AUTOCOMPLETE_ENABLE,
-	                                                                  TRUE);	
-	editor = IANJUTA_EDITOR (assist->priv->iassist);
+	if (assist->priv->completion_cache)
+	{	
+		g_list_foreach (assist->priv->completion_cache->items, (GFunc) cpp_java_assist_proposal_free, NULL);
+		g_completion_free (assist->priv->completion_cache);
+	}
+	assist->priv->completion_cache = NULL;
+	g_cancellable_cancel (assist->priv->cancel_file);
+	g_cancellable_cancel (assist->priv->cancel_project);	
+	g_cancellable_cancel (assist->priv->cancel_system);
+}
 
-	g_free (assist->priv->pre_word);
-	assist->priv->pre_word = NULL;
+/**
+ * cpp_java_assist_populate_real:
+ * @assist: self
+ * @finished: TRUE if no more proposals are expected, FALSE otherwise
+ *
+ * Really invokes the completion interfaces and adds completions. Might be called
+ * from an async context
+ */
+static void
+cpp_java_assist_populate_real (CppJavaAssist* assist, gboolean finished)
+{
+	g_assert (assist->priv->pre_word != NULL);
+	gchar* prefix;
+	GList* proposals = g_completion_complete (assist->priv->completion_cache,
+	                                          assist->priv->pre_word,
+	                                          &prefix);
+	DEBUG_PRINT ("%d proposals match, prefix: %s", g_list_length (proposals), prefix);
+	g_free (prefix);
 
-	ianjuta_iterable_previous (iter, NULL);
+	ianjuta_editor_assist_proposals (assist->priv->iassist,
+	                                 IANJUTA_PROVIDER(assist),
+	                                 proposals, finished, NULL);
+}
 
-	if (autocomplete && cpp_java_assist_valid_iter (assist, iter))
-	{
-		/* Check for member completion */
-		IAnjutaIterable* start_iter = NULL;
-		IAnjutaIterable* res = 
-			cpp_java_parse_expression (assist, iter, &start_iter);
-		if (start_iter && assist->priv->pre_word && assist->priv->search_cache && res != NULL &&
-		    g_str_has_prefix (assist->priv->pre_word, assist->priv->search_cache))
+/**
+ * cpp_java_assist_create_member_completion_cache
+ * @assist: self
+ * @cursor: Current cursor position
+ * 
+ * Create the completion_cache for member completion if possible
+ *
+ * Returns: TRUE if a completion cache was build, FALSE otherwise
+ */
+static gboolean
+cpp_java_assist_create_member_completion_cache (CppJavaAssist* assist, IAnjutaIterable* cursor)
+{
+	IAnjutaIterable* symbol = NULL;
+	IAnjutaIterable* start_iter = NULL;
+	symbol = cpp_java_assist_parse_expression (assist, cursor, &start_iter);
+
+	if (symbol)
+	{
+		gint retval = FALSE;
+		/* Query symbol children */
+		IAnjutaIterable *children = 
+			ianjuta_symbol_manager_get_members (assist->priv->isymbol_manager,
+			                                    IANJUTA_SYMBOL(symbol),
+			                                    IANJUTA_SYMBOL_FIELD_SIMPLE |
+			                                    IANJUTA_SYMBOL_FIELD_KIND |
+			                                    IANJUTA_SYMBOL_FIELD_ACCESS |
+			                                    IANJUTA_SYMBOL_FIELD_TYPE,
+			                                    NULL);
+		if (children)
 		{
-			if (assist->priv->start_iter)
-				g_object_unref (assist->priv->start_iter);
+			GList* proposals = 
+				cpp_java_assist_create_completion_from_symbols (children);
+			cpp_java_assist_create_completion_cache (assist);
+			g_completion_add_items (assist->priv->completion_cache, proposals);
+
 			assist->priv->start_iter = start_iter;
-			cpp_java_assist_update_autocomplete (assist);
-			g_object_unref (res);
-			return;
+
+			cpp_java_assist_populate_real (assist, TRUE);
+			g_list_free (proposals);
+			g_object_unref (children);
+			retval = TRUE;
 		}
-		/* we should have a res with just one item */
-		if (res != NULL) 
+		g_object_unref (symbol);
+		return retval;
+	}
+	else if (start_iter)
+		g_object_unref (start_iter);
+	return FALSE;
+}
+
+/**
+ * on_symbol_search_complete:
+ * @search_id: id of this search
+ * @symbols: the returned symbols
+ * @assist: self
+ *
+ * Called by the async search method when it found symbols
+ */
+static void
+on_symbol_search_complete (gint search_id, IAnjutaIterable* symbols, CppJavaAssist* assist)
+{
+	GList* proposals = cpp_java_assist_create_completion_from_symbols (symbols);
+	DEBUG_PRINT ("Found %d symbols, adding!", g_list_length (proposals));
+	g_completion_add_items (assist->priv->completion_cache, proposals);
+	gboolean running = assist->priv->async_system || assist->priv->async_file ||
+		assist->priv->async_project;
+	cpp_java_assist_populate_real (assist, !running);
+	g_list_free (proposals);
+	g_object_unref (symbols);
+}
+
+/**
+ * notify_system_finished:
+ * @notify: the notifycation object
+ * @assist: self
+ *
+ * Called when the system search was finished
+ */
+static void
+notify_system_finished (AnjutaAsyncNotify* notify, CppJavaAssist* assist)
+{
+	assist->priv->async_system = FALSE;
+}
+
+/**
+ * notify_file_finished:
+ * @notify: the notifycation object
+ * @assist: self
+ *
+ * Called when the file search was finished
+ */
+static void
+notify_file_finished (AnjutaAsyncNotify* notify, CppJavaAssist* assist)
+{
+	assist->priv->async_file = FALSE;
+}
+
+/**
+ * notify_project_finished:
+ * @notify: the notifycation object
+ * @assist: self
+ *
+ * Called when the file search was finished
+ */
+static void
+notify_project_finished (AnjutaAsyncNotify* notify, CppJavaAssist* assist)
+{
+	assist->priv->async_project = FALSE;
+}
+
+
+/**
+ * cpp_java_assist_create_autocompletion_cache:
+ * @assist: self
+ * @cursor: Current cursor position
+ * 
+ * Create completion cache for autocompletion. This is done async.
+ *
+ * Returns: TRUE if a preword was detected, FALSE otherwise
+ */ 
+static gboolean
+cpp_java_assist_create_autocompletion_cache (CppJavaAssist* assist, IAnjutaIterable* cursor)
+{
+	IAnjutaIterable* start_iter;
+	gchar* pre_word = 
+		cpp_java_assist_get_pre_word (IANJUTA_EDITOR (assist->priv->iassist), cursor, &start_iter);
+	if (!pre_word || strlen (pre_word) <= 3)
+	{
+		if (start_iter)
+			g_object_unref (start_iter);
+		return FALSE;
+	}
+	else
+	{
+		gchar *pattern = g_strconcat (pre_word, "%", NULL);
+		AnjutaAsyncNotify* notify = NULL;
+		IAnjutaSymbolType match_types = IANJUTA_SYMBOL_TYPE_MAX;
+		IAnjutaSymbolField fields = IANJUTA_SYMBOL_FIELD_SIMPLE |
+			IANJUTA_SYMBOL_FIELD_TYPE |
+			IANJUTA_SYMBOL_FIELD_ACCESS |
+			IANJUTA_SYMBOL_FIELD_KIND;
+		
+		cpp_java_assist_create_completion_cache (assist);
+		cpp_java_assist_update_pre_word (assist, pre_word);
+
+		if (IANJUTA_IS_FILE (assist->priv->iassist))
 		{
-			do
+			GFile *file = ianjuta_file_get_file (IANJUTA_FILE (assist->priv->iassist), NULL);
+			if (file != NULL)
 			{
-				IAnjutaSymbol* symbol = IANJUTA_SYMBOL(res);
-				const gchar* name = ianjuta_symbol_get_name(symbol, NULL);
-				if (name != NULL)
-				{
-					DEBUG_PRINT ("PARENT Completion Symbol: %s", name);
-
-					/* we have just printed the parent's name */
-					/* let's get it's members and print them */
-					IAnjutaIterable *children = 
-						ianjuta_symbol_manager_get_members (assist->priv->isymbol_manager,
-						                                    symbol,
-						                                    IANJUTA_SYMBOL_FIELD_SIMPLE |
-						                                    IANJUTA_SYMBOL_FIELD_KIND |
-						                                    IANJUTA_SYMBOL_FIELD_ACCESS |
-						                                    IANJUTA_SYMBOL_FIELD_TYPE,
-						                                    NULL);
-					if (children != NULL) {
-						cpp_java_assist_destroy_completion_cache (assist);
-						assist->priv->completion_cache = create_completion (assist,
-						                                                    children,
-						                                                    NULL);
-						if (assist->priv->start_iter)
-							g_object_unref (assist->priv->start_iter);
-						assist->priv->start_iter = start_iter;
-						cpp_java_assist_update_autocomplete(assist);
-					}
-				}
-				else
-					break;
+				notify = anjuta_async_notify_new();
+				g_signal_connect (notify, "finished", G_CALLBACK(notify_file_finished), assist);
+				assist->priv->async_file = TRUE;
+				g_cancellable_reset (assist->priv->cancel_file);
+				ianjuta_symbol_manager_search_file_async (assist->priv->isymbol_manager,
+				                                          match_types,
+				                                          TRUE,
+				                                          fields,
+				                                          pattern, file, -1, -1, 
+				                                          assist->priv->cancel_file,
+				                                          notify, 
+				                                          (IAnjutaSymbolManagerSearchCallback) on_symbol_search_complete,
+				                                          assist,
+				                                          NULL);
+				g_object_unref (file);
 			}
-			while (ianjuta_iterable_next (res, NULL));
-			g_object_unref (res);
-			return;
 		}
+		/* This will avoid duplicates of FUNCTION and PROTOTYPE */
+		match_types &= ~IANJUTA_SYMBOL_TYPE_FUNCTION;
+		notify = anjuta_async_notify_new();
+		g_signal_connect (notify, "finished", G_CALLBACK(notify_project_finished), assist);
+		assist->priv->async_project = TRUE;
+		g_cancellable_reset (assist->priv->cancel_project);
+		ianjuta_symbol_manager_search_project_async (assist->priv->isymbol_manager,
+		                                             match_types,
+		                                             TRUE,
+		                                             fields,
+		                                             pattern, 
+		                                             IANJUTA_SYMBOL_MANAGER_SEARCH_FS_PUBLIC, -1, -1, 
+		                                             assist->priv->cancel_project,
+		                                             notify, 
+		                                             (IAnjutaSymbolManagerSearchCallback) on_symbol_search_complete, 
+		                                             assist,
+		                                             NULL);
+
+
+		notify = anjuta_async_notify_new();
+		g_signal_connect (notify, "finished", G_CALLBACK(notify_system_finished), assist);
+		assist->priv->async_system = TRUE;
+		g_cancellable_reset (assist->priv->cancel_system);
+		ianjuta_symbol_manager_search_system_async (assist->priv->isymbol_manager,
+		                                            match_types,
+		                                            TRUE,
+		                                            fields,
+		                                            pattern, IANJUTA_SYMBOL_MANAGER_SEARCH_FS_PUBLIC, -1, -1,
+		                                            assist->priv->cancel_system,
+		                                            notify, 
+		                                            (IAnjutaSymbolManagerSearchCallback) on_symbol_search_complete, 
+		                                            assist,
+		                                            NULL);
+		g_free (pre_word);
+		g_free (pattern);
+
+		assist->priv->start_iter = start_iter;
 		
-		/* Normal autocompletion */
-		/* Moved iter to begin of word */		
-		assist->priv->pre_word = cpp_java_assist_get_pre_word (editor, iter);
-		DEBUG_PRINT ("Pre word: %s", assist->priv->pre_word);
-		
-		if (assist->priv->pre_word && strlen (assist->priv->pre_word) > 3)
-		{	
-			if (!assist->priv->search_cache ||
-			    !g_str_has_prefix (assist->priv->pre_word, assist->priv->search_cache))
-			{
-				if (assist->priv->start_iter)
-					g_object_unref (assist->priv->start_iter);
-				assist->priv->start_iter = ianjuta_iterable_clone(iter, NULL);
-				DEBUG_PRINT ("Setting start iter!");
-				ianjuta_iterable_next (IANJUTA_ITERABLE (assist->priv->start_iter), NULL);
-				cpp_java_assist_create_word_completion_cache(assist);
-				return;
-			}
-			else
-			{
-				cpp_java_assist_update_autocomplete (assist);
-				return;
-			}
-		}
+		return TRUE;
 	}
-	/* Keep completion system happy */
-	ianjuta_editor_assist_proposals (assist->priv->iassist,
-	                                 IANJUTA_PROVIDER(self),
-	                                 NULL, TRUE, NULL);
-} 
+}
 
+/**
+ * cpp_java_assist_populate:
+ * @self: IAnjutaProvider object
+ * @cursor: Iter at current cursor position (after current character)
+ * @e: Error population
+ */
 static void
-cpp_java_assist_activate (IAnjutaProvider* self, IAnjutaIterable* iter, gpointer data, GError** e)
+cpp_java_assist_populate (IAnjutaProvider* self, IAnjutaIterable* cursor, GError** e)
 {
-	CppJavaAssist* assist = CPP_JAVA_ASSIST(self);
-	CppJavaAssistTag *tag;
-	GString *assistance;
-	IAnjutaEditor *te;
-	gboolean add_space_after_func = FALSE;
-	gboolean add_brace_after_func = FALSE;
-	
-	//DEBUG_PRINT ("assist-chosen: %d", selection);
-		
-	tag = data;	
-	
-	g_return_if_fail (tag != NULL);
-	
-	assistance = g_string_new (tag->name);
-	
-	if (tag->is_func)
+	CppJavaAssist* assist = CPP_JAVA_ASSIST (self);
+
+	/* Check if this is a valid text region for completion */
+	IAnjutaEditorAttribute attrib = ianjuta_editor_cell_get_attribute (IANJUTA_EDITOR_CELL(cursor),
+	                                                                   NULL);
+	if (attrib == IANJUTA_EDITOR_STRING ||
+	    attrib == IANJUTA_EDITOR_COMMENT)
 	{
-		add_space_after_func =
-			anjuta_preferences_get_bool_with_default (assist->priv->preferences,
-													 PREF_AUTOCOMPLETE_SPACE_AFTER_FUNC,
-													 TRUE);
-		add_brace_after_func =
-			anjuta_preferences_get_bool_with_default (assist->priv->preferences,
-													 PREF_AUTOCOMPLETE_BRACE_AFTER_FUNC,
-													 TRUE);
-		if (add_space_after_func)
-			g_string_append (assistance, " ");
-		
-		if (add_brace_after_func)
-			g_string_append (assistance, "(");
+		ianjuta_editor_assist_proposals (assist->priv->iassist,
+		                                 IANJUTA_PROVIDER(self),
+		                                 NULL, TRUE, NULL);
+		return;
 	}
 	
-	te = IANJUTA_EDITOR (assist->priv->iassist);
-		
-	ianjuta_document_begin_undo_action (IANJUTA_DOCUMENT (te), NULL);
-	
-	if (ianjuta_iterable_compare(iter, assist->priv->start_iter, NULL) != 0)
+	/* Check if completion was in progress */
+	if (assist->priv->member_completion || assist->priv->autocompletion)
 	{
-		ianjuta_editor_selection_set (IANJUTA_EDITOR_SELECTION (te),
-									  assist->priv->start_iter, iter, FALSE, NULL);
-		ianjuta_editor_selection_replace (IANJUTA_EDITOR_SELECTION (te),
-										  assistance->str, -1, NULL);
+		IAnjutaIterable* start_iter = NULL;
+		g_assert (assist->priv->completion_cache != NULL);
+		gchar* pre_word = cpp_java_assist_get_pre_word (IANJUTA_EDITOR (assist->priv->iassist), cursor, &start_iter);
+		DEBUG_PRINT ("Completion is in progress");
+		if (pre_word && g_str_has_prefix (pre_word, assist->priv->pre_word))
+		{
+			/* Great, we just continue the current completion */
+			g_object_unref (assist->priv->start_iter);
+			assist->priv->start_iter = start_iter;
+
+			cpp_java_assist_update_pre_word (assist, pre_word);
+			cpp_java_assist_populate_real (assist, TRUE);
+			g_free (pre_word);
+			return;
+		}
+		else
+			cpp_java_assist_clear_completion_cache (assist);
+		g_free (pre_word);
 	}
-	else
+	/* Check for member completion */
+	assist->priv->member_completion = FALSE;
+	assist->priv->autocompletion = FALSE;
+	if (cpp_java_assist_create_member_completion_cache (assist, cursor))
 	{
-		ianjuta_editor_insert (te, iter, assistance->str, -1, NULL);
+		assist->priv->member_completion = TRUE;
+		DEBUG_PRINT ("Creating member completion");
+		return;
 	}
-	ianjuta_document_end_undo_action (IANJUTA_DOCUMENT (te), NULL);
-	
-	/* Show calltip if we completed function */
-	if (add_brace_after_func)
-		cpp_java_assist_calltip (assist, TRUE, FALSE);
-	
-	g_string_free (assistance, TRUE);
-	g_free(assist->priv->pre_word);
-	assist->priv->pre_word = NULL;
-	g_free(assist->priv->search_cache);
-	assist->priv->search_cache = NULL;
+	else if (cpp_java_assist_create_autocompletion_cache (assist, cursor))
+	{
+		assist->priv->autocompletion = TRUE;
+		DEBUG_PRINT ("Creating autocompletion");
+		return;
+	}		
+	/* Nothing to propose */
+	if (assist->priv->start_iter)
+	{
+		g_object_unref (assist->priv->start_iter);
+		assist->priv->start_iter = NULL;
+	}
+	ianjuta_editor_assist_proposals (assist->priv->iassist,
+	                                 IANJUTA_PROVIDER(self),
+	                                 NULL, TRUE, NULL);
+} 
+
+/**
+ * cpp_java_assist_activate:
+ * @self: IAnjutaProvider object
+ * @iter: cursor position when proposal was activated
+ * @data: Data assigned to the completion object
+ * @e: Error population
+ */
+static void
+cpp_java_assist_activate (IAnjutaProvider* self, IAnjutaIterable* iter, gpointer data, GError** e)
+{
+
 }
 
+/**
+ * cpp_java_assist_get_start_iter:
+ * @self: IAnjutaProvider object
+ * @e: Error population
+ *
+ * Returns: the iter where the autocompletion starts
+ */
 static IAnjutaIterable*
 cpp_java_assist_get_start_iter (IAnjutaProvider* provider, GError** e)
 {
 	CppJavaAssist* assist = CPP_JAVA_ASSIST (provider);
+	DEBUG_PRINT ("Start iter: %d", ianjuta_iterable_get_position(assist->priv->start_iter, NULL));
 	return assist->priv->start_iter;
 }
 
+/**
+ * cpp_java_assist_get_name:
+ * @self: IAnjutaProvider object
+ * @e: Error population
+ *
+ * Returns: the provider name
+ */
 static const gchar*
 cpp_java_assist_get_name (IAnjutaProvider* provider, GError** e)
 {
 	return _("C/C++");
 }
 
+/**
+ * cpp_java_assist_install:
+ * @self: IAnjutaProvider object
+ * @ieditor: Editor to install support for
+ *
+ * Returns: Registers provider for editor
+ */
 static void
 cpp_java_assist_install (CppJavaAssist *assist, IAnjutaEditor *ieditor)
 {
@@ -1085,6 +843,7 @@ cpp_java_assist_install (CppJavaAssist *assist, IAnjutaEditor *ieditor)
 		assist->priv->iassist = NULL;
 	}
 
+#if 0
 	if (IANJUTA_IS_EDITOR_TIP (ieditor))
 	{
 		assist->priv->itip = IANJUTA_EDITOR_TIP (ieditor);
@@ -1093,19 +852,28 @@ cpp_java_assist_install (CppJavaAssist *assist, IAnjutaEditor *ieditor)
 						  G_CALLBACK (on_editor_char_added), assist);
 	}
 	else
+#endif
 	{
 		assist->priv->itip = NULL;
 	}
 }
 
+/**
+ * cpp_java_assist_uninstall:
+ * @self: IAnjutaProvider object
+ *
+ * Returns: Unregisters provider
+ */
 static void
 cpp_java_assist_uninstall (CppJavaAssist *assist)
 {
 	g_return_if_fail (assist->priv->iassist != NULL);
 
 	DEBUG_PRINT ("uninstall called");
-	
+
+#if 0
 	g_signal_handlers_disconnect_by_func (assist->priv->iassist, G_CALLBACK (on_editor_char_added), assist);
+#endif
 
 	ianjuta_editor_assist_remove (assist->priv->iassist, IANJUTA_PROVIDER(assist), NULL);
 
@@ -1116,7 +884,6 @@ static void
 cpp_java_assist_init (CppJavaAssist *assist)
 {
 	assist->priv = g_new0 (CppJavaAssistPriv, 1);
-	
 	assist->priv->cancel_file = g_cancellable_new();
 	assist->priv->cancel_project = g_cancellable_new();
 	assist->priv->cancel_system = g_cancellable_new();	
@@ -1127,15 +894,17 @@ cpp_java_assist_finalize (GObject *object)
 {
 	CppJavaAssist *assist = CPP_JAVA_ASSIST (object);
 	cpp_java_assist_uninstall (assist);
-	cpp_java_assist_destroy_completion_cache (assist);
+	cpp_java_assist_clear_completion_cache (assist);
+#if 0
 	if (assist->priv->calltip_context)
 	{
 		g_free (assist->priv->calltip_context);
 		assist->priv->calltip_context = NULL;
-		g_object_unref (assist->priv->cancel_file);
-		g_object_unref (assist->priv->cancel_project);
-		g_object_unref (assist->priv->cancel_system);		
 	}
+#endif
+	g_object_unref (assist->priv->cancel_file);
+	g_object_unref (assist->priv->cancel_project);
+	g_object_unref (assist->priv->cancel_system);		
 	g_free (assist->priv);
 	G_OBJECT_CLASS (cpp_java_assist_parent_class)->finalize (object);
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]