[gnome-builder] plugins: add GParameter helper
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] plugins: add GParameter helper
- Date: Sat, 11 Mar 2017 10:09:15 +0000 (UTC)
commit 08310b69ad2a1c34fa3dc1a25246309e944b648f
Author: Christian Hergert <chergert redhat com>
Date: Sat Mar 11 01:47:16 2017 -0800
plugins: add GParameter helper
Libpeas is not sufficient to extract GParameters that we need because we
also care about the base objects in the prerequisites, not just interfaces.
This is a sort of barebones implementation of that. Scan the interfaces
chain, and then the objects that are pre-reqs. If we find the property,
all good.
https://bugzilla.gnome.org/show_bug.cgi?id=779891
libide/plugins/ide-extension-util.c | 178 +++++++++++++++++++++++++++++++++++
libide/plugins/ide-extension-util.h | 21 +++-
2 files changed, 193 insertions(+), 6 deletions(-)
---
diff --git a/libide/plugins/ide-extension-util.c b/libide/plugins/ide-extension-util.c
index 77b1b90..5d81c53 100644
--- a/libide/plugins/ide-extension-util.c
+++ b/libide/plugins/ide-extension-util.c
@@ -18,6 +18,8 @@
#define G_LOG_DOMAIN "ide-extension-util"
+#include <glib-object.h>
+#include <gobject/gvaluecollector.h>
#include <stdlib.h>
#include "ide-extension-util.h"
@@ -92,3 +94,179 @@ ide_extension_util_can_use_plugin (PeasEngine *engine,
settings = g_settings_new_with_path ("org.gnome.builder.extension-type", path);
return g_settings_get_boolean (settings, "enabled");
}
+
+static void
+clear_param (gpointer data)
+{
+ GParameter *p = data;
+ g_value_unset (&p->value);
+}
+
+static GType
+find_property_type (GType type,
+ const gchar *name)
+{
+ g_autoptr(GArray) types = NULL;
+ g_autofree GType *prereqs = NULL;
+ guint n_prereqs = 0;
+ GType ancestor = type;
+
+ g_assert (name != NULL);
+ g_assert (G_TYPE_IS_INTERFACE (type));
+
+ /* Collect all the types to locate properties from */
+ types = g_array_new (FALSE, FALSE, sizeof (GType));
+ for (ancestor = type; ancestor != 0; ancestor = g_type_parent (ancestor))
+ g_array_append_val (types, ancestor);
+ prereqs = g_type_interface_prerequisites (type, &n_prereqs);
+ for (guint i = 0; i < n_prereqs; i++)
+ g_array_append_val (types, prereqs[i]);
+
+ /* Try to locate the property within the types */
+ for (guint i = 0; i < types->len; i++)
+ {
+ GType prereq_type = g_array_index (types, GType, i);
+ GObjectClass *klass = NULL;
+ GTypeInterface *iface = NULL;
+ GParamSpec *pspec = NULL;
+ GType ret = G_TYPE_INVALID;
+
+ if (G_TYPE_IS_FUNDAMENTAL (prereq_type))
+ continue;
+
+ if (!G_TYPE_IS_OBJECT (prereq_type) && !G_TYPE_IS_INTERFACE (prereq_type))
+ continue;
+
+ if (G_TYPE_IS_OBJECT (prereq_type))
+ {
+ klass = g_type_class_ref (prereq_type);
+ pspec = g_object_class_find_property (klass, name);
+ }
+ else if (G_TYPE_IS_INTERFACE (prereq_type))
+ {
+ iface = g_type_default_interface_ref (prereq_type);
+ pspec = g_object_interface_find_property (iface, name);
+ }
+ else
+ g_assert_not_reached ();
+
+ if (pspec != NULL)
+ ret = pspec->value_type;
+
+ g_clear_pointer (&klass, g_type_class_unref);
+ g_clear_pointer (&iface, g_type_default_interface_unref);
+
+ if (ret != G_TYPE_INVALID)
+ return ret;
+ }
+
+ return G_TYPE_INVALID;
+}
+
+static GArray *
+collect_parameters (GType type,
+ const gchar *first_property,
+ va_list args)
+{
+ const gchar *property = first_property;
+ g_autoptr(GArray) params = NULL;
+
+ params = g_array_new (FALSE, FALSE, sizeof (GParameter));
+ g_array_set_clear_func (params, clear_param);
+
+ while (property != NULL)
+ {
+ GType property_type = find_property_type (type, property);
+ GParameter param = { property };
+ g_autofree gchar *errmsg = NULL;
+
+ if (property_type == G_TYPE_INVALID)
+ {
+ g_warning ("Unknown property \"%s\" from interface %s", property, g_type_name (type));
+ break;
+ }
+
+ G_VALUE_COLLECT_INIT (¶m.value, property_type, args, 0, &errmsg);
+
+ if (errmsg)
+ {
+ g_warning ("Error collecting property: %s", errmsg);
+ break;
+ }
+
+ g_array_append_val (params, param);
+
+ property = va_arg (args, const gchar *);
+ }
+
+ if (property != NULL)
+ return NULL;
+
+ return g_steal_pointer (¶ms);
+}
+
+/**
+ * ide_extension_set_new:
+ *
+ * This function acts like peas_extension_set_new() except that it allows for
+ * us to pass properties that are in the parent class.
+ *
+ * It does this by duplicating some of the GParameter stuff that libpeas does
+ * but looking at base-classes in addition to interface properties.
+ *
+ * Returns: (transfer full): A #PeasExtensionSet.
+ */
+PeasExtensionSet *
+ide_extension_set_new (PeasEngine *engine,
+ GType type,
+ const gchar *first_property,
+ ...)
+{
+ g_autoptr(GArray) params = NULL;
+ va_list args;
+
+ g_return_val_if_fail (!engine || PEAS_IS_ENGINE (engine), NULL);
+ g_return_val_if_fail (G_TYPE_IS_INTERFACE (type), NULL);
+
+ if (engine == NULL)
+ engine = peas_engine_get_default ();
+
+ va_start (args, first_property);
+ params = collect_parameters (type, first_property, args);
+ va_end (args);
+
+ if (params == NULL)
+ return NULL;
+
+ return peas_extension_set_newv (engine, type, params->len, (GParameter *)params->data);
+}
+
+PeasExtension *
+ide_extension_new (PeasEngine *engine,
+ PeasPluginInfo *plugin_info,
+ GType type,
+ const gchar *first_property,
+ ...)
+{
+ g_autoptr(GArray) params = NULL;
+ va_list args;
+
+ g_return_val_if_fail (!engine || PEAS_IS_ENGINE (engine), NULL);
+ g_return_val_if_fail (G_TYPE_IS_INTERFACE (type), NULL);
+
+ if (engine == NULL)
+ engine = peas_engine_get_default ();
+
+ va_start (args, first_property);
+ params = collect_parameters (type, first_property, args);
+ va_end (args);
+
+ if (params == NULL)
+ return NULL;
+
+ return peas_engine_create_extensionv (engine,
+ plugin_info,
+ type,
+ params->len,
+ (GParameter *)params->data);
+}
diff --git a/libide/plugins/ide-extension-util.h b/libide/plugins/ide-extension-util.h
index b7ec516..637c003 100644
--- a/libide/plugins/ide-extension-util.h
+++ b/libide/plugins/ide-extension-util.h
@@ -23,12 +23,21 @@
G_BEGIN_DECLS
-gboolean ide_extension_util_can_use_plugin (PeasEngine *engine,
- PeasPluginInfo *plugin_info,
- GType interface_type,
- const gchar *key,
- const gchar *value,
- gint *priority);
+gboolean ide_extension_util_can_use_plugin (PeasEngine *engine,
+ PeasPluginInfo *plugin_info,
+ GType interface_type,
+ const gchar *key,
+ const gchar *value,
+ gint *priority);
+PeasExtensionSet *ide_extension_set_new (PeasEngine *engine,
+ GType type,
+ const gchar *first_property,
+ ...);
+PeasExtension *ide_extension_new (PeasEngine *engine,
+ PeasPluginInfo *plugin_info,
+ GType interface_type,
+ const gchar *first_property,
+ ...);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]