[gnome-builder/wip/libide] libide: use GPtrArray instead of GList for results
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/libide] libide: use GPtrArray instead of GList for results
- Date: Sun, 15 Mar 2015 23:33:24 +0000 (UTC)
commit 42c0be6693d844bc5dab1e2a85c3b72c9d9ba9ba
Author: Christian Hergert <christian hergert me>
Date: Sun Mar 15 16:33:06 2015 -0700
libide: use GPtrArray instead of GList for results
We should only fallback to GList at the very last moment before passing
data to GtkSourceCompletionContext. Everything else causes incredibly
poor performance.
libide/clang/ide-clang-completion-provider.c | 107 ++++++++++++++++++++++++-
libide/clang/ide-clang-translation-unit.c | 20 ++---
libide/clang/ide-clang-translation-unit.h | 2 +-
3 files changed, 110 insertions(+), 19 deletions(-)
---
diff --git a/libide/clang/ide-clang-completion-provider.c b/libide/clang/ide-clang-completion-provider.c
index 1b46bdc..2d8ff77 100644
--- a/libide/clang/ide-clang-completion-provider.c
+++ b/libide/clang/ide-clang-completion-provider.c
@@ -16,9 +16,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#define G_LOG_DOMAIN "ide-clang-completion"
+
#include <glib/gi18n.h>
#include "ide-buffer.h"
+#include "ide-clang-completion-item.h"
#include "ide-clang-completion-provider.h"
#include "ide-clang-service.h"
#include "ide-clang-translation-unit.h"
@@ -34,6 +37,8 @@ struct _IdeClangCompletionProviderClass
struct _IdeClangCompletionProvider
{
GObject parent_instance;
+
+ GPtrArray *last_results;
};
typedef struct
@@ -67,6 +72,78 @@ add_proposals_state_free (AddProposalsState *state)
g_free (state);
}
+static gboolean
+stop_on_predicate (gunichar ch,
+ gpointer data)
+{
+ switch (ch)
+ {
+ case '_':
+ return FALSE;
+
+ case ')':
+ case '(':
+ case '&':
+ case '*':
+ case '{':
+ case '}':
+ case ' ':
+ case '\t':
+ case '[':
+ case ']':
+ case '=':
+ case '"':
+ case '\'':
+ return TRUE;
+
+ default:
+ return !g_unichar_isalnum (ch);
+ }
+}
+
+static gchar *
+get_word (const GtkTextIter *location)
+{
+ GtkTextIter iter = *location;
+ GtkTextBuffer *buffer;
+ GtkTextIter end;
+
+ end = iter;
+ buffer = gtk_text_iter_get_buffer (&iter);
+
+ if (!gtk_text_iter_backward_find_char (&iter, stop_on_predicate, NULL, NULL))
+ return gtk_text_buffer_get_text (buffer, &iter, &end, TRUE);
+
+ gtk_text_iter_forward_char (&iter);
+
+ return gtk_text_iter_get_text (&iter, &end);
+}
+
+static GList *
+filter_list (GPtrArray *ar,
+ const gchar *word)
+{
+ g_autoptr(GPtrArray) matched = NULL;
+ GList *ret = NULL;
+ gsize i;
+
+ matched = g_ptr_array_new ();
+
+ for (i = 0; i < ar->len; i++)
+ {
+ IdeClangCompletionItem *item;
+
+ item = g_ptr_array_index (ar, i);
+ if (ide_clang_completion_item_matches (item, word))
+ g_ptr_array_add (matched, item);
+ }
+
+ for (i = 0; i < matched->len; i++)
+ ret = g_list_prepend (ret, g_ptr_array_index (matched, i));
+
+ return ret;
+}
+
static void
ide_clang_completion_provider_class_init (IdeClangCompletionProviderClass *klass)
{
@@ -89,21 +166,41 @@ ide_clang_completion_provider_complete_cb (GObject *object,
gpointer user_data)
{
IdeClangTranslationUnit *tu = (IdeClangTranslationUnit *)object;
+ IdeClangCompletionProvider *self;
AddProposalsState *state = user_data;
+ g_autofree gchar *word = NULL;
+ g_autoptr(GPtrArray) ar = NULL;
+ GtkTextIter iter;
GError *error = NULL;
- GList *list;
+ GList *filtered = NULL;
+
+ self = (IdeClangCompletionProvider *)state->provider;
- list = ide_clang_translation_unit_code_complete_finish (tu, result, &error);
+ ar = ide_clang_translation_unit_code_complete_finish (tu, result, &error);
- if (!list && error)
+ if (!ar)
{
g_warning ("%s", error->message);
g_clear_error (&error);
+ goto failure;
}
+ g_clear_pointer (&self->last_results, g_ptr_array_free);
+ self->last_results = g_ptr_array_ref (ar);
+
+ gtk_source_completion_context_get_iter (state->context, &iter);
+ word = get_word (&iter);
+
+ IDE_TRACE_MSG ("Current word: %s", word ?: "(null)");
+
+ if (word)
+ filtered = filter_list (ar, word);
+
+failure:
if (!g_cancellable_is_cancelled (state->cancellable))
- gtk_source_completion_context_add_proposals (state->context, state->provider, list, TRUE);
- g_list_free_full (list, g_object_unref);
+ gtk_source_completion_context_add_proposals (state->context, state->provider, filtered, TRUE);
+
+ g_list_free (filtered);
add_proposals_state_free (state);
}
diff --git a/libide/clang/ide-clang-translation-unit.c b/libide/clang/ide-clang-translation-unit.c
index 9770d9a..3188afe 100644
--- a/libide/clang/ide-clang-translation-unit.c
+++ b/libide/clang/ide-clang-translation-unit.c
@@ -466,12 +466,6 @@ ide_clang_translation_unit_init (IdeClangTranslationUnit *self)
}
static void
-cleanup_list (gpointer data)
-{
- g_list_free_full (data, g_object_unref);
-}
-
-static void
ide_clang_translation_unit_code_complete_worker (GTask *task,
gpointer source_object,
gpointer task_data,
@@ -482,7 +476,7 @@ ide_clang_translation_unit_code_complete_worker (GTask *task,
CXCodeCompleteResults *results;
g_autoptr(IdeRefPtr) refptr = NULL;
struct CXUnsavedFile *ufs;
- GList *list = NULL;
+ g_autoptr(GPtrArray) ar = NULL;
gsize i;
gsize j = 0;
@@ -546,6 +540,7 @@ ide_clang_translation_unit_code_complete_worker (GTask *task,
* we will inflate result strings as necessary.
*/
refptr = ide_ref_ptr_new (results, (GDestroyNotify)clang_disposeCodeCompleteResults);
+ ar = g_ptr_array_new ();
for (i = 0; i < results->NumResults; i++)
{
@@ -555,10 +550,10 @@ ide_clang_translation_unit_code_complete_worker (GTask *task,
"results", ide_ref_ptr_ref (refptr),
"index", (guint)i,
NULL);
- list = g_list_prepend (list, proposal);
+ g_ptr_array_add (ar, proposal);
}
- g_task_return_pointer (task, g_list_reverse (list), cleanup_list);
+ g_task_return_pointer (task, g_ptr_array_ref (ar), (GDestroyNotify)g_ptr_array_unref);
/* cleanup malloc'd state */
for (i = 0; i < j; i++)
@@ -614,11 +609,10 @@ ide_clang_translation_unit_code_complete_async (IdeClangTranslationUnit *self,
*
* Completes a call to ide_clang_translation_unit_code_complete_async().
*
- * Returns: (transfer full) (element-type GtkSourceCompletionProposal*): A list of
- * #GtkSourceCompletionProposal. If this is %NULL, check @error to determine if
- * there was an error.
+ * Returns: (transfer container) (element-type GtkSourceCompletionProposal*): An array of
+ * #GtkSourceCompletionProposal. Upon failure, %NULL is returned.
*/
-GList *
+GPtrArray *
ide_clang_translation_unit_code_complete_finish (IdeClangTranslationUnit *self,
GAsyncResult *result,
GError **error)
diff --git a/libide/clang/ide-clang-translation-unit.h b/libide/clang/ide-clang-translation-unit.h
index 60e5539..4d59c9c 100644
--- a/libide/clang/ide-clang-translation-unit.h
+++ b/libide/clang/ide-clang-translation-unit.h
@@ -37,7 +37,7 @@ void ide_clang_translation_unit_code_complete_async (IdeClangTransla
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
-GList *ide_clang_translation_unit_code_complete_finish (IdeClangTranslationUnit *self,
+GPtrArray *ide_clang_translation_unit_code_complete_finish (IdeClangTranslationUnit *self,
GAsyncResult *result,
GError **error);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]