[gnome-builder] code-index: add asynchronous next_entries_async API
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] code-index: add asynchronous next_entries_async API
- Date: Sun, 25 Mar 2018 23:35:28 +0000 (UTC)
commit c46b603d1bda20bec3cac4366d5c7384d44946be
Author: Christian Hergert <chergert redhat com>
Date: Sat Mar 24 17:12:35 2018 -0700
code-index: add asynchronous next_entries_async API
Previously, the IdeCodeIndexEntries API required generating content on the main
thread (or rather, accessing it synchronously with a generator-like API).
This instead creates an async API to get the next chunk of items with a default
implementation to call that sync API on the main thread.
The Vala and Clang indexers have been ported to the Async API to batch all the
results in a single call.
This allows less work to be done on the main thread (other than building the
index GVariant content files).
A new IdeCodeIndexerEntryBuilder API has been created to create entry
instances. This also allowed us to make IdeCodeIndexerEntry not an object
anymore, but a boxed type. This should be a little bit faster by avoiding all
those property creations.
src/libide/symbols/ide-code-index-entries.c | 99 ++++++
src/libide/symbols/ide-code-index-entries.h | 25 +-
src/libide/symbols/ide-code-index-entry.c | 411 ++++++++++-------------
src/libide/symbols/ide-code-index-entry.h | 84 +++--
src/plugins/clang/ide-clang-code-index-entries.c | 106 ++++--
src/plugins/code-index/ide-code-index-builder.c | 105 +++---
src/plugins/gjs-symbols/gjs_symbols.py | 18 +-
src/plugins/vala-pack/ide-vala-code-indexer.vala | 39 ++-
8 files changed, 529 insertions(+), 358 deletions(-)
---
diff --git a/src/libide/symbols/ide-code-index-entries.c b/src/libide/symbols/ide-code-index-entries.c
index 8d8ef7864..5573e1596 100644
--- a/src/libide/symbols/ide-code-index-entries.c
+++ b/src/libide/symbols/ide-code-index-entries.c
@@ -22,12 +22,60 @@
#include "application/ide-application.h"
#include "symbols/ide-code-index-entries.h"
+#include "threading/ide-task.h"
G_DEFINE_INTERFACE (IdeCodeIndexEntries, ide_code_index_entries, G_TYPE_OBJECT)
+static void
+ide_code_index_entries_real_next_entries_async (IdeCodeIndexEntries *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(IdeTask) task = NULL;
+ g_autoptr(GPtrArray) ret = NULL;
+ IdeCodeIndexEntry *entry;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (IDE_IS_CODE_INDEX_ENTRIES (self));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = ide_task_new (self, cancellable, callback, user_data);
+ ide_task_set_source_tag (task, ide_code_index_entries_real_next_entries_async);
+ ide_task_set_priority (task, G_PRIORITY_LOW);
+ ide_task_set_kind (task, IDE_TASK_KIND_INDEXER);
+
+ ret = g_ptr_array_new_with_free_func ((GDestroyNotify)ide_code_index_entry_free);
+
+ while ((entry = ide_code_index_entries_get_next_entry (self)))
+ g_ptr_array_add (ret, g_steal_pointer (&entry));
+
+ ide_task_return_pointer (task, g_steal_pointer (&ret), (GDestroyNotify)g_ptr_array_unref);
+}
+
+static GPtrArray *
+ide_code_index_entries_real_next_entries_finish (IdeCodeIndexEntries *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_assert (IDE_IS_CODE_INDEX_ENTRIES (self));
+ g_assert (IDE_IS_TASK (result));
+
+ return ide_task_propagate_pointer (IDE_TASK (result), error);
+}
+
+static IdeCodeIndexEntry *
+ide_code_index_entries_real_get_next_entry (IdeCodeIndexEntries *self)
+{
+ return NULL;
+}
+
static void
ide_code_index_entries_default_init (IdeCodeIndexEntriesInterface *iface)
{
+ iface->get_next_entry = ide_code_index_entries_real_get_next_entry;
+ iface->next_entries_async = ide_code_index_entries_real_next_entries_async;
+ iface->next_entries_finish = ide_code_index_entries_real_next_entries_finish;
}
/**
@@ -67,3 +115,54 @@ ide_code_index_entries_get_file (IdeCodeIndexEntries *self)
return IDE_CODE_INDEX_ENTRIES_GET_IFACE (self)->get_file (self);
}
+
+/**
+ * ide_code_index_entries_next_entries_async:
+ * @self: a #IdeCodeIndexEntries
+ * @cancellable: (nullable): a #GCancellable or %NULL
+ * @callback: a callback to execute upon completion
+ * @user_data: user data for @callback, or %NULL
+ *
+ * Requests the next set of results from the code index asynchronously.
+ * This allows implementations to possibly process data off the main thread
+ * without blocking the main loop.
+ *
+ * Since: 3.30
+ */
+void
+ide_code_index_entries_next_entries_async (IdeCodeIndexEntries *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_return_if_fail (IDE_IS_MAIN_THREAD ());
+ g_return_if_fail (IDE_IS_CODE_INDEX_ENTRIES (self));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ IDE_CODE_INDEX_ENTRIES_GET_IFACE (self)->next_entries_async (self, cancellable, callback, user_data);
+}
+
+/**
+ * ide_code_index_entries_next_entries_finish:
+ * @self: a #IdeCodeIndexEntries
+ * @result: a #GAsyncResult provided to callback
+ * @error: a location for a #GError, or %NULL
+ *
+ * Completes an asynchronous request for the next set of entries from the index.
+ *
+ * Returns: (transfer container) (element-type Ide.CodeIndexEntry): a #GPtrArray
+ * of #IdeCodeIndexEntry.
+ *
+ * Since: 3.30
+ */
+GPtrArray *
+ide_code_index_entries_next_entries_finish (IdeCodeIndexEntries *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (IDE_IS_MAIN_THREAD (), NULL);
+ g_return_val_if_fail (IDE_IS_CODE_INDEX_ENTRIES (self), NULL);
+ g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
+
+ return IDE_CODE_INDEX_ENTRIES_GET_IFACE (self)->next_entries_finish (self, result, error);
+}
diff --git a/src/libide/symbols/ide-code-index-entries.h b/src/libide/symbols/ide-code-index-entries.h
index 4fdd64e18..a0a6c9044 100644
--- a/src/libide/symbols/ide-code-index-entries.h
+++ b/src/libide/symbols/ide-code-index-entries.h
@@ -19,6 +19,7 @@
#pragma once
#include "ide-object.h"
+#include "ide-version-macros.h"
#include "symbols/ide-code-index-entry.h"
#include "symbols/ide-symbol.h"
@@ -34,13 +35,29 @@ struct _IdeCodeIndexEntriesInterface
{
GTypeInterface parent_iface;
- GFile *(*get_file) (IdeCodeIndexEntries *self);
- IdeCodeIndexEntry *(*get_next_entry) (IdeCodeIndexEntries *self);
+ GFile *(*get_file) (IdeCodeIndexEntries *self);
+ IdeCodeIndexEntry *(*get_next_entry) (IdeCodeIndexEntries *self);
+ void (*next_entries_async) (IdeCodeIndexEntries *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ GPtrArray *(*next_entries_finish) (IdeCodeIndexEntries *self,
+ GAsyncResult *result,
+ GError **error);
};
IDE_AVAILABLE_IN_ALL
-IdeCodeIndexEntry *ide_code_index_entries_get_next_entry (IdeCodeIndexEntries *self);
+IdeCodeIndexEntry *ide_code_index_entries_get_next_entry (IdeCodeIndexEntries *self);
IDE_AVAILABLE_IN_ALL
-GFile *ide_code_index_entries_get_file (IdeCodeIndexEntries *self);
+GFile *ide_code_index_entries_get_file (IdeCodeIndexEntries *self);
+IDE_AVAILABLE_IN_3_30
+void ide_code_index_entries_next_entries_async (IdeCodeIndexEntries *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+IDE_AVAILABLE_IN_3_30
+GPtrArray *ide_code_index_entries_next_entries_finish (IdeCodeIndexEntries *self,
+ GAsyncResult *result,
+ GError **error);
G_END_DECLS
diff --git a/src/libide/symbols/ide-code-index-entry.c b/src/libide/symbols/ide-code-index-entry.c
index 908b12fd2..f626c6b32 100644
--- a/src/libide/symbols/ide-code-index-entry.c
+++ b/src/libide/symbols/ide-code-index-entry.c
@@ -22,286 +22,245 @@
#include "symbols/ide-code-index-entry.h"
-typedef struct
+/**
+ * SECTION:ide-code-index-entry
+ * @title: IdeCodeIndexEntry
+ * @short_description: information about code index entry
+ *
+ * The #IdeCodeIndexEntry structure contains information about something to be
+ * indexed in the code index. It is an immutable data object so that it can be
+ * passed between threads where data is indexed. Plugins should use
+ * #IdeCodeIndexEntryBuilder to create index entries.
+ */
+
+struct _IdeCodeIndexEntry
{
- GObject parent;
-
- gchar *key;
- gchar *name;
-
- IdeSymbolKind kind;
- IdeSymbolFlags flags;
-
- guint begin_line;
- guint begin_line_offset;
- guint end_line;
- guint end_line_offset;
-} IdeCodeIndexEntryPrivate;
-
-G_DEFINE_TYPE_WITH_PRIVATE (IdeCodeIndexEntry, ide_code_index_entry, G_TYPE_OBJECT)
-
-enum {
- PROP_0,
- PROP_KEY,
- PROP_NAME,
- PROP_KIND,
- PROP_FLAGS,
- PROP_BEGIN_LINE,
- PROP_BEGIN_LINE_OFFSET,
- PROP_END_LINE,
- PROP_END_LINE_OFFSET,
- N_PROPS
-};
+ gchar *key;
+ gchar *name;
-static GParamSpec *properties [N_PROPS];
+ IdeSymbolKind kind;
+ IdeSymbolFlags flags;
-static void
-ide_code_index_entry_finalize (GObject *object)
+ guint begin_line;
+ guint begin_line_offset;
+ guint end_line;
+ guint end_line_offset;
+};
+
+struct _IdeCodeIndexEntryBuilder
{
- IdeCodeIndexEntry *self = (IdeCodeIndexEntry *)object;
- IdeCodeIndexEntryPrivate *priv = ide_code_index_entry_get_instance_private (self);
+ IdeCodeIndexEntry entry;
+};
- g_clear_pointer (&priv->name, g_free);
- g_clear_pointer (&priv->key, g_free);
+G_DEFINE_BOXED_TYPE (IdeCodeIndexEntry,
+ ide_code_index_entry,
+ ide_code_index_entry_copy,
+ ide_code_index_entry_free)
+G_DEFINE_BOXED_TYPE (IdeCodeIndexEntryBuilder,
+ ide_code_index_entry_builder,
+ ide_code_index_entry_builder_copy,
+ ide_code_index_entry_builder_free)
- G_OBJECT_CLASS (ide_code_index_entry_parent_class)->finalize (object);
+void
+ide_code_index_entry_free (IdeCodeIndexEntry *self)
+{
+ if (self != NULL)
+ {
+ g_clear_pointer (&self->name, g_free);
+ g_clear_pointer (&self->key, g_free);
+ g_slice_free (IdeCodeIndexEntry, self);
+ }
}
-static void
-ide_code_index_entry_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
+IdeCodeIndexEntry *
+ide_code_index_entry_copy (const IdeCodeIndexEntry *self)
{
- IdeCodeIndexEntry *self = (IdeCodeIndexEntry *)object;
- IdeCodeIndexEntryPrivate *priv = ide_code_index_entry_get_instance_private (self);
+ IdeCodeIndexEntry *copy = NULL;
- switch (prop_id)
+ if (self != NULL)
{
- case PROP_KEY:
- g_free (priv->key);
- priv->key = g_value_dup_string (value);
- break;
-
- case PROP_NAME:
- g_free (priv->name);
- priv->name = g_value_dup_string (value);
- break;
-
- case PROP_KIND:
- priv->kind = g_value_get_int (value);
- break;
-
- case PROP_FLAGS:
- priv->flags = g_value_get_int (value);
- break;
-
- case PROP_BEGIN_LINE:
- priv->begin_line = g_value_get_uint (value);
- break;
-
- case PROP_BEGIN_LINE_OFFSET:
- priv->begin_line_offset = g_value_get_uint (value);
- break;
-
- case PROP_END_LINE:
- priv->end_line = g_value_get_uint (value);
- break;
-
- case PROP_END_LINE_OFFSET:
- priv->end_line_offset = g_value_get_uint (value);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ copy = g_slice_dup (IdeCodeIndexEntry, self);
+ copy->name = g_strdup (self->name);
+ copy->key = g_strdup (self->key);
}
+
+ return copy;
}
-static void
-ide_code_index_entry_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
+const gchar *
+ide_code_index_entry_get_key (const IdeCodeIndexEntry *self)
{
- IdeCodeIndexEntry *self = (IdeCodeIndexEntry *)object;
- IdeCodeIndexEntryPrivate *priv = ide_code_index_entry_get_instance_private (self);
+ g_return_val_if_fail (self != NULL, NULL);
- switch (prop_id)
- {
- case PROP_KEY:
- g_value_set_string (value, priv->key);
- break;
+ return self->key;
+}
- case PROP_NAME:
- g_value_set_string (value, priv->name);
- break;
+const gchar *
+ide_code_index_entry_get_name (const IdeCodeIndexEntry *self)
+{
+ g_return_val_if_fail (self != NULL, NULL);
- case PROP_KIND:
- g_value_set_int (value, priv->kind);
- break;
+ return self->name;
+}
- case PROP_FLAGS:
- g_value_set_int (value, priv->flags);
- break;
+IdeSymbolKind
+ide_code_index_entry_get_kind (const IdeCodeIndexEntry *self)
+{
+ g_return_val_if_fail (self != NULL, IDE_SYMBOL_NONE);
- case PROP_BEGIN_LINE:
- g_value_set_uint (value, priv->begin_line);
- break;
+ return self->kind;
+}
- case PROP_BEGIN_LINE_OFFSET:
- g_value_set_uint (value, priv->begin_line_offset);
- break;
+IdeSymbolFlags
+ide_code_index_entry_get_flags (const IdeCodeIndexEntry *self)
+{
+ g_return_val_if_fail (self != NULL, IDE_SYMBOL_FLAGS_NONE);
- case PROP_END_LINE:
- g_value_set_uint (value, priv->end_line);
- break;
+ return self->flags;
+}
- case PROP_END_LINE_OFFSET:
- g_value_set_uint (value, priv->end_line_offset);
- break;
+/**
+ * ide_code_index_entry_get_range:
+ * @self: a #IdeCodeIndexEntry
+ * @begin_line: (out): first line
+ * @begin_line_offset: (out): first line offset
+ * @end_line: (out): last line
+ * @end_line_offset: (out): last line offset
+ *
+ * Since: 3.30
+ */
+void
+ide_code_index_entry_get_range (const IdeCodeIndexEntry *self,
+ guint *begin_line,
+ guint *begin_line_offset,
+ guint *end_line,
+ guint *end_line_offset)
+{
+ g_return_if_fail (self != NULL);
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- }
+ if (begin_line != NULL)
+ *begin_line = self->begin_line;
+
+ if (begin_line_offset != NULL)
+ *begin_line_offset = self->begin_line_offset;
+
+ if (end_line != NULL)
+ *end_line = self->end_line;
+
+ if (end_line_offset != NULL)
+ *end_line_offset = self->end_line_offset;
}
-static void
-ide_code_index_entry_class_init (IdeCodeIndexEntryClass *klass)
+IdeCodeIndexEntryBuilder *
+ide_code_index_entry_builder_new (void)
{
- GObjectClass *object_class = (GObjectClass *)klass;
-
- object_class->finalize = ide_code_index_entry_finalize;
- object_class->set_property = ide_code_index_entry_set_property;
- object_class->get_property = ide_code_index_entry_get_property;
-
- properties [PROP_KEY] =
- g_param_spec_string ("key",
- "Key",
- "A key unique to declaration.",
- NULL,
- (G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- properties [PROP_NAME] =
- g_param_spec_string ("name",
- "Name",
- "Name of declaration.",
- NULL,
- (G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- properties [PROP_KIND] =
- g_param_spec_int ("kind",
- "Kind",
- "Kind of declaration.",
- G_MININT, G_MAXINT, IDE_SYMBOL_NONE,
- (G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- properties [PROP_FLAGS] =
- g_param_spec_int ("flags",
- "Flags",
- "Flags of declaration.",
- G_MININT, G_MAXINT, IDE_SYMBOL_FLAGS_NONE,
- (G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- properties [PROP_BEGIN_LINE] =
- g_param_spec_uint ("begin-line",
- "Begin Line",
- "Begin Line of declaration.",
- 0, G_MAXUINT, 0,
- (G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- properties [PROP_BEGIN_LINE_OFFSET] =
- g_param_spec_uint ("begin-line-offset",
- "Begin Line Offset",
- "Begin Line Offset of declaration.",
- 0, G_MAXUINT, 0,
- (G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- properties [PROP_END_LINE] =
- g_param_spec_uint ("end-line",
- "End Line",
- "End Line of declaration.",
- 0, G_MAXUINT, 0,
- (G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- properties [PROP_END_LINE_OFFSET] =
- g_param_spec_uint ("end-line-offset",
- "End Line Offset",
- "End Line Offset of declaration.",
- 0, G_MAXUINT, 0,
- (G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_properties (object_class, N_PROPS, properties);
+ return g_slice_new0 (IdeCodeIndexEntryBuilder);
}
-static void
-ide_code_index_entry_init (IdeCodeIndexEntry *self)
+void
+ide_code_index_entry_builder_free (IdeCodeIndexEntryBuilder *builder)
{
+ if (builder != NULL)
+ {
+ g_clear_pointer (&builder->entry.key, g_free);
+ g_clear_pointer (&builder->entry.name, g_free);
+ g_slice_free (IdeCodeIndexEntryBuilder, builder);
+ }
}
-const gchar *
-ide_code_index_entry_get_key (IdeCodeIndexEntry *self)
+void
+ide_code_index_entry_builder_set_range (IdeCodeIndexEntryBuilder *builder,
+ guint begin_line,
+ guint begin_line_offset,
+ guint end_line,
+ guint end_line_offset)
{
- IdeCodeIndexEntryPrivate *priv = ide_code_index_entry_get_instance_private (self);
-
- g_return_val_if_fail (IDE_IS_CODE_INDEX_ENTRY (self), NULL);
+ g_return_if_fail (builder != NULL);
- return priv->key;
+ builder->entry.begin_line = begin_line;
+ builder->entry.begin_line_offset = begin_line_offset;
+ builder->entry.end_line = end_line;
+ builder->entry.end_line_offset = end_line_offset;
}
-const gchar *
-ide_code_index_entry_get_name (IdeCodeIndexEntry *self)
+void
+ide_code_index_entry_builder_set_name (IdeCodeIndexEntryBuilder *builder,
+ const gchar *name)
{
- IdeCodeIndexEntryPrivate *priv = ide_code_index_entry_get_instance_private (self);
+ g_return_if_fail (builder != NULL);
- g_return_val_if_fail (IDE_IS_CODE_INDEX_ENTRY (self), NULL);
-
- return priv->name;
+ if (name != builder->entry.name)
+ {
+ g_free (builder->entry.name);
+ builder->entry.name = g_strdup (name);
+ }
}
-IdeSymbolKind
-ide_code_index_entry_get_kind (IdeCodeIndexEntry *self)
+void
+ide_code_index_entry_builder_set_key (IdeCodeIndexEntryBuilder *builder,
+ const gchar *key)
{
- IdeCodeIndexEntryPrivate *priv;
+ g_return_if_fail (builder != NULL);
- g_return_val_if_fail (IDE_IS_CODE_INDEX_ENTRY (self), IDE_SYMBOL_NONE);
-
- priv = ide_code_index_entry_get_instance_private (self);
- return priv->kind;
+ if (key != builder->entry.key)
+ {
+ g_free (builder->entry.key);
+ builder->entry.key = g_strdup (key);
+ }
}
-IdeSymbolFlags
-ide_code_index_entry_get_flags (IdeCodeIndexEntry *self)
+void
+ide_code_index_entry_builder_set_flags (IdeCodeIndexEntryBuilder *builder,
+ IdeSymbolFlags flags)
{
- IdeCodeIndexEntryPrivate *priv;
-
- g_return_val_if_fail (IDE_IS_CODE_INDEX_ENTRY (self), IDE_SYMBOL_FLAGS_NONE);
+ g_return_if_fail (builder != NULL);
- priv = ide_code_index_entry_get_instance_private (self);
- return priv->flags;
+ builder->entry.flags = flags;
}
void
-ide_code_index_entry_get_range (IdeCodeIndexEntry *self,
- guint *begin_line,
- guint *begin_line_offset,
- guint *end_line,
- guint *end_line_offset)
+ide_code_index_entry_builder_set_kind (IdeCodeIndexEntryBuilder *builder,
+ IdeSymbolKind kind)
{
- IdeCodeIndexEntryPrivate *priv;
+ g_return_if_fail (builder != NULL);
- g_return_if_fail (IDE_IS_CODE_INDEX_ENTRY (self));
+ builder->entry.kind = kind;
+}
- priv = ide_code_index_entry_get_instance_private (self);
+/**
+ * ide_code_index_entry_builder_build:
+ * @builder: a #IdeCodeIndexEntryBuilder
+ *
+ * Creates an immutable #IdeCodeIndexEntry from the builder content.
+ *
+ * Returns: (transfer full): an #IdeCodeIndexEntry
+ *
+ * Since: 3.30
+ */
+IdeCodeIndexEntry *
+ide_code_index_entry_builder_build (IdeCodeIndexEntryBuilder *builder)
+{
+ g_return_val_if_fail (builder != NULL, NULL);
- if (begin_line != NULL)
- *begin_line = priv->begin_line;
+ return ide_code_index_entry_copy (&builder->entry);
+}
- if (begin_line_offset != NULL)
- *begin_line_offset = priv->begin_line_offset;
+/**
+ * ide_code_index_entry_builder_copy:
+ * @builder: a #IdeCodeIndexEntryBuilder
+ *
+ * Returns: (transfer full): a deep copy of @builder
+ *
+ * Since: 3.30
+ */
+IdeCodeIndexEntryBuilder *
+ide_code_index_entry_builder_copy (IdeCodeIndexEntryBuilder *builder)
+{
+ IdeCodeIndexEntryBuilder *copy;
- if (end_line != NULL)
- *end_line = priv->end_line;
+ copy = g_slice_dup (IdeCodeIndexEntryBuilder, builder);
+ copy->entry.key = g_strdup (builder->entry.key);
+ copy->entry.name = g_strdup (builder->entry.name);
- if (end_line_offset != NULL)
- *end_line_offset = priv->end_line_offset;
+ return copy;
}
diff --git a/src/libide/symbols/ide-code-index-entry.h b/src/libide/symbols/ide-code-index-entry.h
index ecca68528..06c3ca465 100644
--- a/src/libide/symbols/ide-code-index-entry.h
+++ b/src/libide/symbols/ide-code-index-entry.h
@@ -25,32 +25,62 @@
G_BEGIN_DECLS
-#define IDE_TYPE_CODE_INDEX_ENTRY (ide_code_index_entry_get_type ())
-
-IDE_AVAILABLE_IN_ALL
-G_DECLARE_DERIVABLE_TYPE (IdeCodeIndexEntry, ide_code_index_entry, IDE, CODE_INDEX_ENTRY, GObject)
-
-struct _IdeCodeIndexEntryClass
-{
- GObjectClass parent;
-
- /*< private */
- gpointer _padding[16];
-};
-
-IDE_AVAILABLE_IN_ALL
-const gchar *ide_code_index_entry_get_key (IdeCodeIndexEntry *self);
-IDE_AVAILABLE_IN_ALL
-const gchar *ide_code_index_entry_get_name (IdeCodeIndexEntry *self);
-IDE_AVAILABLE_IN_ALL
-IdeSymbolKind ide_code_index_entry_get_kind (IdeCodeIndexEntry *self);
-IDE_AVAILABLE_IN_ALL
-IdeSymbolFlags ide_code_index_entry_get_flags (IdeCodeIndexEntry *self);
-IDE_AVAILABLE_IN_ALL
-void ide_code_index_entry_get_range (IdeCodeIndexEntry *self,
- guint *begin_line,
- guint *begin_line_offset,
- guint *end_line,
- guint *end_line_offset);
+#define IDE_TYPE_CODE_INDEX_ENTRY (ide_code_index_entry_get_type())
+#define IDE_TYPE_CODE_INDEX_ENTRY_BUILDER (ide_code_index_entry_builder_get_type())
+
+typedef struct _IdeCodeIndexEntry IdeCodeIndexEntry;
+typedef struct _IdeCodeIndexEntryBuilder IdeCodeIndexEntryBuilder;
+
+IDE_AVAILABLE_IN_3_30
+GType ide_code_index_entry_get_type (void);
+IDE_AVAILABLE_IN_3_30
+GType ide_code_index_entry_builder_get_type (void);
+IDE_AVAILABLE_IN_3_30
+IdeCodeIndexEntryBuilder *ide_code_index_entry_builder_new (void);
+IDE_AVAILABLE_IN_3_30
+void ide_code_index_entry_builder_set_range (IdeCodeIndexEntryBuilder *builder,
+ guint begin_line,
+ guint
begin_line_offset,
+ guint end_line,
+ guint end_line_offset);
+IDE_AVAILABLE_IN_3_30
+void ide_code_index_entry_builder_set_key (IdeCodeIndexEntryBuilder *builder,
+ const gchar *key);
+IDE_AVAILABLE_IN_3_30
+void ide_code_index_entry_builder_set_name (IdeCodeIndexEntryBuilder *builder,
+ const gchar *name);
+IDE_AVAILABLE_IN_3_30
+void ide_code_index_entry_builder_set_kind (IdeCodeIndexEntryBuilder *builder,
+ IdeSymbolKind kind);
+IDE_AVAILABLE_IN_3_30
+void ide_code_index_entry_builder_set_flags (IdeCodeIndexEntryBuilder *builder,
+ IdeSymbolFlags flags);
+IDE_AVAILABLE_IN_3_30
+IdeCodeIndexEntry *ide_code_index_entry_builder_build (IdeCodeIndexEntryBuilder *builder);
+IDE_AVAILABLE_IN_3_30
+IdeCodeIndexEntryBuilder *ide_code_index_entry_builder_copy (IdeCodeIndexEntryBuilder *builder);
+IDE_AVAILABLE_IN_3_30
+void ide_code_index_entry_builder_free (IdeCodeIndexEntryBuilder *builder);
+IDE_AVAILABLE_IN_3_30
+void ide_code_index_entry_free (IdeCodeIndexEntry *self);
+IDE_AVAILABLE_IN_3_30
+IdeCodeIndexEntry *ide_code_index_entry_copy (const IdeCodeIndexEntry *self);
+IDE_AVAILABLE_IN_3_30
+const gchar *ide_code_index_entry_get_key (const IdeCodeIndexEntry *self);
+IDE_AVAILABLE_IN_3_30
+const gchar *ide_code_index_entry_get_name (const IdeCodeIndexEntry *self);
+IDE_AVAILABLE_IN_3_30
+IdeSymbolKind ide_code_index_entry_get_kind (const IdeCodeIndexEntry *self);
+IDE_AVAILABLE_IN_3_30
+IdeSymbolFlags ide_code_index_entry_get_flags (const IdeCodeIndexEntry *self);
+IDE_AVAILABLE_IN_3_30
+void ide_code_index_entry_get_range (const IdeCodeIndexEntry *self,
+ guint *begin_line,
+ guint
*begin_line_offset,
+ guint *end_line,
+ guint *end_line_offset);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (IdeCodeIndexEntry, ide_code_index_entry_free)
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (IdeCodeIndexEntryBuilder, ide_code_index_entry_builder_free)
G_END_DECLS
diff --git a/src/plugins/clang/ide-clang-code-index-entries.c
b/src/plugins/clang/ide-clang-code-index-entries.c
index ef972758b..8fcb66f85 100644
--- a/src/plugins/clang/ide-clang-code-index-entries.c
+++ b/src/plugins/clang/ide-clang-code-index-entries.c
@@ -47,6 +47,8 @@ struct _IdeClangCodeIndexEntries
* GSlice allocated structures holding the raw CXCursor from the
* translation unit. Since we own the unit/index, these are safe for the
* lifetime of the object.
+ *
+ * These are manipulated from a worker thread when generating the entries.
*/
GQueue cursors;
GQueue decl_cursors;
@@ -203,6 +205,7 @@ visitor (CXCursor cursor,
*/
static IdeCodeIndexEntry *
ide_clang_code_index_entries_real_get_next_entry (IdeClangCodeIndexEntries *self,
+ IdeCodeIndexEntryBuilder *builder,
gboolean *finish)
{
g_autoptr(CXCursor) cursor = NULL;
@@ -221,8 +224,9 @@ ide_clang_code_index_entries_real_get_next_entry (IdeClangCodeIndexEntries *self
guint column = 0;
guint offset = 0;
- g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (!IDE_IS_MAIN_THREAD ());
g_assert (IDE_IS_CLANG_CODE_INDEX_ENTRIES (self));
+ g_assert (builder != NULL);
g_assert (finish != NULL);
*finish = FALSE;
@@ -300,50 +304,104 @@ ide_clang_code_index_entries_real_get_next_entry (IdeClangCodeIndexEntries *self
key = clang_getCString (usr);
}
- return g_object_new (IDE_TYPE_CODE_INDEX_ENTRY,
- "name", name,
- "key", key,
- "kind", kind,
- "flags", flags,
- "begin-line", line,
- "begin-line-offset", column,
- NULL);
+ ide_code_index_entry_builder_set_name (builder, name);
+ ide_code_index_entry_builder_set_key (builder, key);
+ ide_code_index_entry_builder_set_kind (builder, kind);
+ ide_code_index_entry_builder_set_flags (builder, flags);
+ ide_code_index_entry_builder_set_range (builder, line, column, 0, 0);
+
+ return ide_code_index_entry_builder_build (builder);
}
-static IdeCodeIndexEntry *
-ide_clang_code_index_entries_get_next_entry (IdeCodeIndexEntries *entries)
+static GFile *
+ide_clang_code_index_entries_get_file (IdeCodeIndexEntries *entries)
{
IdeClangCodeIndexEntries *self = (IdeClangCodeIndexEntries *)entries;
- g_autoptr(IdeCodeIndexEntry) entry = NULL;
- gboolean finish = FALSE;
- g_assert (IDE_IS_MAIN_THREAD ());
+ g_return_val_if_fail (IDE_IS_CLANG_CODE_INDEX_ENTRIES (self), NULL);
+
+ return g_file_new_for_path (self->path);
+}
+
+static void
+ide_clang_code_index_entries_worker (IdeTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ IdeClangCodeIndexEntries *self = source_object;
+ g_autoptr(IdeCodeIndexEntryBuilder) builder = NULL;
+ g_autoptr(GPtrArray) ret = NULL;
+
+ g_assert (IDE_IS_TASK (task));
g_assert (IDE_IS_CLANG_CODE_INDEX_ENTRIES (self));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ ret = g_ptr_array_new_with_free_func ((GDestroyNotify)ide_code_index_entry_free);
+ builder = ide_code_index_entry_builder_new ();
+
+ for (;;)
+ {
+ g_autoptr(IdeCodeIndexEntry) entry = NULL;
+ gboolean finish = FALSE;
+
+ if ((entry = ide_clang_code_index_entries_real_get_next_entry (self, builder, &finish)))
+ {
+ g_ptr_array_add (ret, g_steal_pointer (&entry));
+ continue;
+ }
- do
- entry = ide_clang_code_index_entries_real_get_next_entry (self, &finish);
- while (entry == NULL && finish == FALSE);
+ if (!finish)
+ continue;
- g_assert (entry == NULL || IDE_IS_CODE_INDEX_ENTRY (entry));
+ break;
+ }
- return g_steal_pointer (&entry);
+ ide_task_return_pointer (task, g_steal_pointer (&ret), (GDestroyNotify)g_ptr_array_unref);
}
-static GFile *
-ide_clang_code_index_entries_get_file (IdeCodeIndexEntries *entries)
+static void
+ide_clang_code_index_entries_next_entries_async (IdeCodeIndexEntries *entries,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
IdeClangCodeIndexEntries *self = (IdeClangCodeIndexEntries *)entries;
+ g_autoptr(IdeTask) task = NULL;
- g_return_val_if_fail (IDE_IS_CLANG_CODE_INDEX_ENTRIES (self), NULL);
+ g_assert (IDE_IS_CLANG_CODE_INDEX_ENTRIES (self));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
- return g_file_new_for_path (self->path);
+ task = ide_task_new (self, cancellable, callback, user_data);
+ ide_task_set_source_tag (task, ide_clang_code_index_entries_next_entries_async);
+ ide_task_set_priority (task, G_PRIORITY_LOW + 1000);
+ ide_task_set_kind (task, IDE_TASK_KIND_INDEXER);
+ ide_task_run_in_thread (task, ide_clang_code_index_entries_worker);
+}
+
+static GPtrArray *
+ide_clang_code_index_entries_next_entries_finish (IdeCodeIndexEntries *entries,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_assert (IDE_IS_CLANG_CODE_INDEX_ENTRIES (entries));
+ g_assert (IDE_IS_TASK (result));
+ g_assert (ide_task_is_valid (result, entries));
+
+ return ide_task_propagate_pointer (IDE_TASK (result), error);
}
static void
index_entries_iface_init (IdeCodeIndexEntriesInterface *iface)
{
- iface->get_next_entry = ide_clang_code_index_entries_get_next_entry;
+ /*
+ * We only implement the Async API, not the sync API so that we can generate
+ * the results inside of a thread.
+ */
+
iface->get_file = ide_clang_code_index_entries_get_file;
+ iface->next_entries_async = ide_clang_code_index_entries_next_entries_async;
+ iface->next_entries_finish = ide_clang_code_index_entries_next_entries_finish;
}
G_DEFINE_TYPE_WITH_CODE (IdeClangCodeIndexEntries, ide_clang_code_index_entries, G_TYPE_OBJECT,
diff --git a/src/plugins/code-index/ide-code-index-builder.c b/src/plugins/code-index/ide-code-index-builder.c
index 3fabde84f..ce4f3ea72 100644
--- a/src/plugins/code-index/ide-code-index-builder.c
+++ b/src/plugins/code-index/ide-code-index-builder.c
@@ -807,39 +807,29 @@ get_changes_finish (IdeCodeIndexBuilder *self,
/**
* add_entries_to_index
- * @self: a #IdeCodeIndexBuilder
+ * @entries: (element-type Ide.CodeIndexEntry): the entries to add
* @file_id: the id within the index
* @map_builder: the persistent map builder to append
* @fuzzy_builder: the fuzzy index builder to append
- * @deadline: the deadline to stop processing on this thread. This should
- * be a time using the monotonic clock, g_get_monotonic_time().
*
- * This will incrementally add entries to the builder. However,
- * it will stop processing once @deadline has expired.
- *
- * Returns: %TRUE if there are more items to process; otherwise %FALSE
+ * This will incrementally add entries to the builder.
*/
-static gboolean
-add_entries_to_index (IdeCodeIndexEntries *entries,
+static void
+add_entries_to_index (GPtrArray *entries,
+ GFile *file,
guint32 file_id,
IdePersistentMapBuilder *map_builder,
- DzlFuzzyIndexBuilder *fuzzy_builder,
- gint64 deadline)
+ DzlFuzzyIndexBuilder *fuzzy_builder)
{
g_autofree gchar *filename = NULL;
- g_autoptr(GFile) file = NULL;
- guint count = 0;
gchar num[16];
g_assert (IDE_IS_MAIN_THREAD ());
- g_assert (IDE_IS_CODE_INDEX_ENTRIES (entries));
+ g_assert (G_IS_FILE (file));
g_assert (file_id > 0);
g_assert (IDE_IS_PERSISTENT_MAP_BUILDER (map_builder));
g_assert (DZL_IS_FUZZY_INDEX_BUILDER (fuzzy_builder));
- file = ide_code_index_entries_get_file (entries);
- g_assert (G_IS_FILE (file));
-
/*
* Storing file_name:id and id:file_name into index, file_name:id will be
* used to check whether a file is there in index or not.
@@ -852,9 +842,9 @@ add_entries_to_index (IdeCodeIndexEntries *entries,
dzl_fuzzy_index_builder_set_metadata_uint32 (fuzzy_builder, filename, file_id);
dzl_fuzzy_index_builder_set_metadata_string (fuzzy_builder, num, filename);
- for (;;)
+ for (guint i = 0; i < entries->len; i++)
{
- g_autoptr(IdeCodeIndexEntry) entry = NULL;
+ IdeCodeIndexEntry *entry = g_ptr_array_index (entries, i);
const gchar *key;
const gchar *name;
IdeSymbolKind kind;
@@ -862,9 +852,6 @@ add_entries_to_index (IdeCodeIndexEntries *entries,
guint begin_line;
guint begin_line_offset;
- if (!(entry = ide_code_index_entries_get_next_entry (entries)))
- break;
-
key = ide_code_index_entry_get_key (entry);
name = ide_code_index_entry_get_name (entry);
kind = ide_code_index_entry_get_kind (entry);
@@ -898,17 +885,7 @@ add_entries_to_index (IdeCodeIndexEntries *entries,
flags,
kind),
0);
-
- if (++count > ADD_ENTRIES_CHUNK_SIZE)
- {
- count = 0;
-
- if (g_get_monotonic_time () >= deadline)
- return TRUE;
- }
}
-
- return FALSE;
}
static void
@@ -943,37 +920,58 @@ index_directory_worker (IdeTask *task,
ide_task_return_boolean (task, TRUE);
}
-static gboolean
-add_entries_to_index_cb (gpointer data)
+static void
+add_entries_to_index_next_entries_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
{
+ IdeCodeIndexEntries *entries = (IdeCodeIndexEntries *)object;
+ g_autoptr(GPtrArray) ret = NULL;
+ g_autoptr(IdeTask) task = user_data;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GFile) file = NULL;
AddEntriesData *task_data;
- IdeTask *task = data;
- gint64 deadline;
- gboolean has_more;
+ GCancellable *cancellable;
- g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (IDE_IS_CODE_INDEX_ENTRIES (entries));
+ g_assert (G_IS_ASYNC_RESULT (result));
g_assert (IDE_IS_TASK (task));
+ ret = ide_code_index_entries_next_entries_finish (entries, result, &error);
+
+ if (error != NULL)
+ {
+ ide_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ if (ret == NULL || ret->len == 0)
+ {
+ ide_task_return_boolean (task, TRUE);
+ return;
+ }
+
+ cancellable = ide_task_get_cancellable (task);
task_data = ide_task_get_task_data (task);
+
g_assert (task_data != NULL);
g_assert (IDE_IS_CODE_INDEX_ENTRIES (task_data->entries));
g_assert (IDE_IS_PERSISTENT_MAP_BUILDER (task_data->map_builder));
g_assert (DZL_IS_FUZZY_INDEX_BUILDER (task_data->fuzzy_builder));
g_assert (task_data->file_id > 0);
- /* 1 msec of indexing allowed this cycle */
- deadline = g_get_monotonic_time () + (G_USEC_PER_SEC / 1000);
- has_more = add_entries_to_index (task_data->entries,
- task_data->file_id,
- task_data->map_builder,
- task_data->fuzzy_builder,
- deadline);
+ file = ide_code_index_entries_get_file (entries);
- /* Complete task if there's nothing more */
- if (!has_more)
- ide_task_return_boolean (task, TRUE);
+ add_entries_to_index (ret,
+ file,
+ task_data->file_id,
+ task_data->map_builder,
+ task_data->fuzzy_builder);
- return has_more;
+ ide_code_index_entries_next_entries_async (entries,
+ cancellable,
+ add_entries_to_index_next_entries_cb,
+ g_steal_pointer (&task));
}
static void
@@ -1012,11 +1010,10 @@ add_entries_to_index_async (IdeCodeIndexBuilder *self,
task_data->file_id = file_id;
ide_task_set_task_data (task, task_data, (GDestroyNotify)add_entries_data_free);
- /* Super low priority to avoid UI stalls */
- g_idle_add_full (G_PRIORITY_LOW + 1000,
- add_entries_to_index_cb,
- g_steal_pointer (&task),
- g_object_unref);
+ ide_code_index_entries_next_entries_async (entries,
+ cancellable,
+ add_entries_to_index_next_entries_cb,
+ g_steal_pointer (&task));
}
static gboolean
diff --git a/src/plugins/gjs-symbols/gjs_symbols.py b/src/plugins/gjs-symbols/gjs_symbols.py
index d1533b154..786a7e43b 100644
--- a/src/plugins/gjs-symbols/gjs_symbols.py
+++ b/src/plugins/gjs-symbols/gjs_symbols.py
@@ -390,18 +390,18 @@ class GjsCodeIndexer(Ide.Object, Ide.CodeIndexer):
except (IndexError, KeyError) as e:
raise GLib.Error('Failed to extract information from ast: {}'.format(e))
+ builder = Ide.CodeIndexEntryBuilder()
+
entries = []
# TODO: Avoid recreating the same data
for node in self._flatten_node_list(root_node):
- entry = Ide.CodeIndexEntry(
- key=node.props.file.get_path() + '|' + node.props.name, # Some unique value..
- name=self._get_node_name(node),
- kind=node.props.kind,
- flags=node.props.flags,
- begin_line=node.props.line + 1, # Not sure why offset here doesn't match tree
- begin_line_offset=node.props.col + 1,
- )
- entries.append(entry)
+ builder.set_key(node.props.file.get_path() + '|' + node.props.name) # Some unique value..
+ builder.set_name(self._get_node_name(node))
+ builder.set_kind(node.props.kind)
+ builder.set_flags(node.props.flags)
+ # Not sure why offset here doesn't match tree
+ builder.set_range(node.props.line + 1, node.props.col + 1, 0, 0)
+ entries.append(builder.build())
task.entries = JsCodeIndexEntries(task.file, entries)
task.return_boolean(True)
diff --git a/src/plugins/vala-pack/ide-vala-code-indexer.vala
b/src/plugins/vala-pack/ide-vala-code-indexer.vala
index 78a184fc6..ad91a3b1b 100644
--- a/src/plugins/vala-pack/ide-vala-code-indexer.vala
+++ b/src/plugins/vala-pack/ide-vala-code-indexer.vala
@@ -99,11 +99,29 @@ namespace Ide
return null;
}
+ public async GLib.GenericArray<weak Ide.CodeIndexEntry> next_entries_async (GLib.Cancellable?
cancellable)
+ throws GLib.Error
+ {
+ var ret = new GLib.GenericArray<Ide.CodeIndexEntry> ();
+
+ for (;;)
+ {
+ Ide.CodeIndexEntry entry = get_next_entry ();
+
+ if (entry == null)
+ break;
+ ret.add (entry);
+ }
+
+ return ret;
+ }
+
void add_children (Ide.ValaSymbolTree tree,
Ide.SymbolNode? parent,
string prefix)
{
var n_children = tree.get_n_children (parent);
+ var builder = new Ide.CodeIndexEntryBuilder ();
for (var i = 0; i < n_children; i++) {
var child = tree.get_nth_child (parent, i) as Ide.ValaSymbolNode;
@@ -145,16 +163,13 @@ namespace Ide
break;
}
- var entry = new Ide.ValaCodeIndexEntry () {
- flags = child.flags | Ide.SymbolFlags.IS_DEFINITION,
- name = search_name,
- kind = child.kind,
- begin_line = loc.begin.line,
- begin_line_offset = loc.begin.column,
- end_line = loc.end.line,
- end_line_offset = loc.end.column,
- key = node.get_full_name ()
- };
+ builder.set_flags (child.flags | Ide.SymbolFlags.IS_DEFINITION);
+ builder.set_name (search_name);
+ builder.set_key (node.get_full_name ());
+ builder.set_kind (child.kind);
+ builder.set_range (loc.begin.line, loc.begin.column, loc.end.line,
loc.end.column);
+
+ var entry = builder.build ();
this.entries.add (entry);
}
@@ -163,8 +178,4 @@ namespace Ide
}
}
}
-
- public class ValaCodeIndexEntry : Ide.CodeIndexEntry
- {
- }
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]