[gnome-builder] libide: allow creating IdeObjects from Peas extensions
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] libide: allow creating IdeObjects from Peas extensions
- Date: Sun, 23 Aug 2015 00:27:40 +0000 (UTC)
commit f764f2fbae4f91758e5dce069bc6f720bbe37f94
Author: Christian Hergert <christian hergert me>
Date: Sat Aug 22 17:22:07 2015 -0700
libide: allow creating IdeObjects from Peas extensions
This adds the same dependency injection trick we were using for
GIOExtensionPoint to be provided via a peas extension. The one caveat
is that we don't have direct access to any sort of priority, so that
needs to be implemented via a callback if necessary.
libide/ide-object.c | 148 +++++++++++++++++++++++++++++++++++++++++++++++++++
libide/ide-object.h | 10 ++++
2 files changed, 158 insertions(+), 0 deletions(-)
---
diff --git a/libide/ide-object.c b/libide/ide-object.c
index 2fcf9e5..d9e76a6 100644
--- a/libide/ide-object.c
+++ b/libide/ide-object.c
@@ -19,6 +19,7 @@
#define G_LOG_DOMAIN "ide-object"
#include <glib/gi18n.h>
+#include <libpeas/peas.h>
#include "ide-context.h"
#include "ide-debug.h"
@@ -38,7 +39,15 @@ typedef struct
int io_priority;
} InitAsyncState;
+typedef struct
+{
+ GPtrArray *plugins;
+ gint position;
+ gint io_priority;
+} InitExtensionAsyncState;
+
static void ide_object_new_async_try_next (InitAsyncState *state);
+static void ide_object_new_for_extension_async_try_next (GTask *task);
G_DEFINE_TYPE_WITH_PRIVATE (IdeObject, ide_object, G_TYPE_OBJECT)
@@ -286,6 +295,145 @@ ide_object_new_async_try_next (InitAsyncState *state)
state);
}
+static void
+extension_async_state_free (gpointer data)
+{
+ InitExtensionAsyncState *state = data;
+
+ g_ptr_array_unref (state->plugins);
+ g_slice_free (InitExtensionAsyncState, state);
+}
+
+static void
+extensions_foreach_cb (PeasExtensionSet *set,
+ PeasPluginInfo *plugin_info,
+ PeasExtension *exten,
+ gpointer user_data)
+{
+ InitExtensionAsyncState *state = user_data;
+
+ g_assert (state != NULL);
+ g_assert (state->plugins != NULL);
+
+ if (!G_IS_ASYNC_INITABLE (exten))
+ {
+ g_warning ("\"%s\" does not implement GAsyncInitable. Ignoring extension.",
+ G_OBJECT_TYPE_NAME (exten));
+ return;
+ }
+
+ g_ptr_array_add (state->plugins, g_object_ref (exten));
+}
+
+static void
+extension_init_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = user_data;
+ GAsyncInitable *initable = (GAsyncInitable *)object;
+ GError *error = NULL;
+ InitExtensionAsyncState *state;
+
+ g_assert (G_IS_TASK (task));
+ g_assert (G_IS_ASYNC_INITABLE (initable));
+
+ state = g_task_get_task_data (task);
+
+ if (!g_async_initable_init_finish (initable, result, &error))
+ {
+ if (state->position == state->plugins->len)
+ {
+ g_task_return_error (task, error);
+ return;
+ }
+
+ g_clear_error (&error);
+ ide_object_new_for_extension_async_try_next (task);
+ return;
+ }
+
+ g_task_return_pointer (task, g_object_ref (initable), g_object_unref);
+}
+
+static void
+ide_object_new_for_extension_async_try_next (GTask *task)
+{
+ InitExtensionAsyncState *state;
+ IdeBuildSystem *build_system;
+
+ g_assert (G_IS_TASK (task));
+
+ state = g_task_get_task_data (task);
+
+ if (state->position == state->plugins->len)
+ {
+ g_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ _("Failed to locate build system plugin."));
+ return;
+ }
+
+ build_system = g_ptr_array_index (state->plugins, state->position++);
+
+ g_async_initable_init_async (G_ASYNC_INITABLE (build_system),
+ state->io_priority,
+ g_task_get_cancellable (task),
+ extension_init_cb,
+ g_object_ref (task));
+}
+
+/**
+ * ide_object_new_for_extension_async:
+ * @sort_priority_func: (scope call) (allow-none): A #GCompareDataFunc or %NULL.
+ *
+ */
+void
+ide_object_new_for_extension_async (GType interface_gtype,
+ GCompareDataFunc sort_priority_func,
+ gpointer sort_priority_data,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ const gchar *first_property,
+ ...)
+{
+ PeasEngine *engine;
+ PeasExtensionSet *set;
+ g_autoptr(GTask) task = NULL;
+ InitExtensionAsyncState *state;
+ va_list args;
+
+ g_return_if_fail (G_TYPE_IS_INTERFACE (interface_gtype));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ engine = peas_engine_get_default ();
+
+ va_start (args, first_property);
+ set = peas_extension_set_new_valist (engine, interface_gtype, first_property, args);
+ va_end (args);
+
+ task = g_task_new (NULL, cancellable, callback, user_data);
+
+ state = g_slice_new0 (InitExtensionAsyncState);
+ state->plugins = g_ptr_array_new_with_free_func (g_object_unref);
+ state->position = 0;
+ state->io_priority = io_priority;
+
+ peas_extension_set_foreach (set, extensions_foreach_cb, state);
+
+ if (sort_priority_func != NULL)
+ g_ptr_array_sort_with_data (state->plugins, sort_priority_func, sort_priority_data);
+
+ g_task_set_task_data (task, state, extension_async_state_free);
+
+ ide_object_new_for_extension_async_try_next (task);
+
+ g_clear_object (&set);
+}
+
void
ide_object_new_async (const gchar *extension_point,
int io_priority,
diff --git a/libide/ide-object.h b/libide/ide-object.h
index 325dc63..14b655b 100644
--- a/libide/ide-object.h
+++ b/libide/ide-object.h
@@ -37,6 +37,16 @@ struct _IdeObjectClass
};
IdeContext *ide_object_get_context (IdeObject *self);
+void ide_object_new_for_extension_async
+ (GType interface_gtype,
+ GCompareDataFunc sort_priority_func,
+ gpointer sort_proirity_data,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ const gchar *first_property,
+ ...);
void ide_object_new_async (const gchar *extension_point,
int io_priority,
GCancellable *cancellable,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]