[libpeas] Consider all an interfaces potential properties



commit 47e286b64d67c006c25b640ed3f5d1a886ccb0a0
Author: Garrett Regier <garrettregier gmail com>
Date:   Wed Mar 2 11:15:27 2016 -0800

    Consider all an interfaces potential properties
    
    An interface can have a prerequisite which is
    derived from GObject an as such is not an interface.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=762899

 libpeas/peas-utils.c                               |   66 +++++++++---
 tests/libpeas/introspection/Makefile.am            |    2 +
 .../introspection/introspection-has-prerequisite.c |   16 ++-
 .../introspection/introspection-prerequisite.c     |  111 ++++++++++++++++++++
 .../introspection/introspection-prerequisite.h     |   56 ++++++++++
 .../plugins/extension-c/extension-c-plugin.c       |    3 +-
 .../plugins/extension-lua/extension-lua51.lua      |   12 +-
 .../plugins/extension-python/extension-py.py.in    |    2 +-
 tests/libpeas/testing/testing-extension.c          |    7 ++
 9 files changed, 246 insertions(+), 29 deletions(-)
---
diff --git a/libpeas/peas-utils.c b/libpeas/peas-utils.c
index 8237011..1051d20 100644
--- a/libpeas/peas-utils.c
+++ b/libpeas/peas-utils.c
@@ -3,6 +3,7 @@
  * This file is part of libpeas
  *
  * Copyright (C) 2010 Steve Frécinaux
+ * Copyright (C) 2011-2017 Garrett Regier
  *
  * libpeas is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -49,37 +50,61 @@ G_STATIC_ASSERT (G_N_ELEMENTS (all_plugin_loader_modules) == PEAS_UTILS_N_LOADER
 G_STATIC_ASSERT (G_N_ELEMENTS (conflicting_plugin_loaders) == PEAS_UTILS_N_LOADERS);
 
 static void
-add_all_interfaces (GType      iface_type,
-                    GPtrArray *type_structs)
+add_all_prerequisites (GType      iface_type,
+                       GType     *base_type,
+                       GPtrArray *ifaces)
 {
   GType *prereq;
   guint n_prereq;
   guint i;
 
-  g_ptr_array_add (type_structs,
-                   g_type_default_interface_ref (iface_type));
+  g_ptr_array_add (ifaces, g_type_default_interface_ref (iface_type));
 
   prereq = g_type_interface_prerequisites (iface_type, &n_prereq);
 
   for (i = 0; i < n_prereq; ++i)
     {
       if (G_TYPE_IS_INTERFACE (prereq[i]))
-        add_all_interfaces (prereq[i], type_structs);
+        {
+          add_all_prerequisites (prereq[i], base_type, ifaces);
+          continue;
+        }
+
+      if (!G_TYPE_IS_OBJECT (prereq[i]))
+        continue;
+
+      if (*base_type != G_TYPE_INVALID)
+        {
+          /* We already have the descendant GType */
+          if (g_type_is_a (*base_type, prereq[i]))
+            continue;
+
+          /* Neither GType are descendant of the other, this is an
+           * error and GObject will not be able to create an object
+           */
+          g_warn_if_fail (g_type_is_a (prereq[i], *base_type));
+        }
+
+      *base_type = prereq[i];
     }
 
   g_free (prereq);
 }
 
 static GParamSpec *
-find_param_spec_in_interfaces (GPtrArray   *type_structs,
-                               const gchar *name)
+find_param_spec_for_prerequisites (const gchar  *name,
+                                   GObjectClass *klass,
+                                   GPtrArray    *ifaces)
 {
   guint i;
   GParamSpec *pspec = NULL;
 
-  for (i = 0; i < type_structs->len && pspec == NULL; ++i)
+  if (klass != NULL)
+    pspec = g_object_class_find_property (klass, name);
+
+  for (i = 0; i < ifaces->len && pspec == NULL; ++i)
     {
-      gpointer iface = g_ptr_array_index (type_structs, i);
+      gpointer iface = g_ptr_array_index (ifaces, i);
 
       pspec = g_object_interface_find_property (iface, name);
     }
@@ -94,16 +119,21 @@ peas_utils_valist_to_parameter_list (GType         iface_type,
                                      GParameter  **params,
                                      guint        *n_params)
 {
-  GPtrArray *type_structs;
+  GPtrArray *ifaces;
+  GType base_type = G_TYPE_INVALID;
+  GObjectClass *klass = NULL;
   const gchar *name;
   guint n_allocated_params;
 
   g_return_val_if_fail (G_TYPE_IS_INTERFACE (iface_type), FALSE);
 
-  type_structs = g_ptr_array_new ();
-  g_ptr_array_set_free_func (type_structs,
+  ifaces = g_ptr_array_new ();
+  g_ptr_array_set_free_func (ifaces,
                              (GDestroyNotify) g_type_default_interface_unref);
-  add_all_interfaces (iface_type, type_structs);
+  add_all_prerequisites (iface_type, &base_type, ifaces);
+
+  if (base_type != G_TYPE_INVALID)
+    klass = g_type_class_ref (base_type);
 
   *n_params = 0;
   n_allocated_params = 16;
@@ -113,7 +143,9 @@ peas_utils_valist_to_parameter_list (GType         iface_type,
   while (name)
     {
       gchar *error_msg = NULL;
-      GParamSpec *pspec = find_param_spec_in_interfaces (type_structs, name);
+      GParamSpec *pspec;
+
+      pspec = find_param_spec_for_prerequisites (name, klass, ifaces);
 
       if (!pspec)
         {
@@ -146,7 +178,8 @@ peas_utils_valist_to_parameter_list (GType         iface_type,
       name = va_arg (args, gchar*);
     }
 
-  g_ptr_array_unref (type_structs);
+  g_ptr_array_unref (ifaces);
+  g_clear_pointer (&klass, g_type_class_unref);
 
   return TRUE;
 
@@ -156,7 +189,8 @@ error:
     g_value_unset (&(*params)[*n_params].value);
 
   g_free (*params);
-  g_ptr_array_unref (type_structs);
+  g_ptr_array_unref (ifaces);
+  g_clear_pointer (&klass, g_type_class_unref);
 
   return FALSE;
 }
diff --git a/tests/libpeas/introspection/Makefile.am b/tests/libpeas/introspection/Makefile.am
index 3cd8b41..930851b 100644
--- a/tests/libpeas/introspection/Makefile.am
+++ b/tests/libpeas/introspection/Makefile.am
@@ -19,6 +19,8 @@ libintrospection_1_0_la_SOURCES = \
        introspection-callable.h                \
        introspection-has-prerequisite.c        \
        introspection-has-prerequisite.h        \
+       introspection-prerequisite.c            \
+       introspection-prerequisite.h            \
        introspection-unimplemented.c           \
        introspection-unimplemented.h
 
diff --git a/tests/libpeas/introspection/introspection-has-prerequisite.c 
b/tests/libpeas/introspection/introspection-has-prerequisite.c
index 145c8dd..f836f52 100644
--- a/tests/libpeas/introspection/introspection-has-prerequisite.c
+++ b/tests/libpeas/introspection/introspection-has-prerequisite.c
@@ -2,7 +2,7 @@
  * introspection-has-prerequisite.h
  * This file is part of libpeas
  *
- * Copyright (C) 2011 Garrett Regier
+ * Copyright (C) 2011-2017 Garrett Regier
  *
  * libpeas is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -23,13 +23,19 @@
 #include <config.h>
 #endif
 
+#include "introspection-base.h"
+#include "introspection-callable.h"
 #include "introspection-has-prerequisite.h"
 
-#include "introspection-base.h"
+#include "introspection-prerequisite.h"
 
-G_DEFINE_INTERFACE(IntrospectionHasPrerequisite,
-                   introspection_has_prerequisite,
-                   INTROSPECTION_TYPE_BASE)
+G_DEFINE_INTERFACE_WITH_CODE(IntrospectionHasPrerequisite,
+                             introspection_has_prerequisite,
+                             INTROSPECTION_TYPE_PREREQUISITE,
+                             g_type_interface_add_prerequisite (g_define_type_id,
+                                                                INTROSPECTION_TYPE_BASE);
+                             g_type_interface_add_prerequisite (g_define_type_id,
+                                                                INTROSPECTION_TYPE_CALLABLE);)
 
 void
 introspection_has_prerequisite_default_init (IntrospectionHasPrerequisiteInterface *iface)
diff --git a/tests/libpeas/introspection/introspection-prerequisite.c 
b/tests/libpeas/introspection/introspection-prerequisite.c
new file mode 100644
index 0000000..1fed47e
--- /dev/null
+++ b/tests/libpeas/introspection/introspection-prerequisite.c
@@ -0,0 +1,111 @@
+/*
+ * introspection-prerequisite.h
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2017 Garrett Regier
+ *
+ * libpeas is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * libpeas is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "introspection-prerequisite.h"
+
+typedef struct {
+  gint value;
+} IntrospectionPrerequisitePrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (IntrospectionPrerequisite,
+                            introspection_prerequisite,
+                            PEAS_TYPE_EXTENSION_BASE)
+
+#define GET_PRIV(o) \
+  (introspection_prerequisite_get_instance_private (o))
+
+enum {
+  PROP_0,
+  PROP_PREREQUISITE_PROPERTY,
+  N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL };
+
+static void
+introspection_prerequisite_get_property (GObject    *object,
+                                         guint       prop_id,
+                                         GValue     *value,
+                                         GParamSpec *pspec)
+{
+  IntrospectionPrerequisite *prereq = INTROSPECTION_PREREQUISITE (object);
+  IntrospectionPrerequisitePrivate *priv = GET_PRIV (prereq);
+
+  switch (prop_id)
+    {
+    case PROP_PREREQUISITE_PROPERTY:
+      g_value_set_int (value, priv->value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+introspection_prerequisite_set_property (GObject      *object,
+                                         guint         prop_id,
+                                         const GValue *value,
+                                         GParamSpec   *pspec)
+{
+  IntrospectionPrerequisite *prereq = INTROSPECTION_PREREQUISITE (object);
+  IntrospectionPrerequisitePrivate *priv = GET_PRIV (prereq);
+
+  switch (prop_id)
+    {
+    case PROP_PREREQUISITE_PROPERTY:
+      priv->value = g_value_get_int (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+introspection_prerequisite_class_init (IntrospectionPrerequisiteClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->get_property = introspection_prerequisite_get_property;
+  object_class->set_property = introspection_prerequisite_set_property;
+
+  properties[PROP_PREREQUISITE_PROPERTY] =
+      g_param_spec_int ("prerequisite-property",
+                        "Prerequisite Property",
+                        "The IntrospectionPrerequisite",
+                        G_MININT,
+                        G_MAXINT,
+                        -1,
+                        G_PARAM_READWRITE |
+                        G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+}
+
+static void
+introspection_prerequisite_init (IntrospectionPrerequisite *prereq)
+{
+}
diff --git a/tests/libpeas/introspection/introspection-prerequisite.h 
b/tests/libpeas/introspection/introspection-prerequisite.h
new file mode 100644
index 0000000..f600d9f
--- /dev/null
+++ b/tests/libpeas/introspection/introspection-prerequisite.h
@@ -0,0 +1,56 @@
+/*
+ * introspection-prerequisite.h
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2017 Garrett Regier
+ *
+ * libpeas is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * libpeas is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.
+ */
+
+#ifndef __INTROSPECTION_PREREQUISITE_H__
+#define __INTROSPECTION_PREREQUISITE_H__
+
+#include <libpeas/peas.h>
+
+G_BEGIN_DECLS
+
+/*
+ * Type checking and casting macros
+ */
+#define INTROSPECTION_TYPE_PREREQUISITE           (introspection_prerequisite_get_type ())
+#define INTROSPECTION_PREREQUISITE(obj)           (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
INTROSPECTION_TYPE_PREREQUISITE, IntrospectionPrerequisite))
+#define INTROSPECTION_PREREQUISITE_CLASS(obj)     (G_TYPE_CHECK_CLASS_CAST ((obj), 
INTROSPECTION_TYPE_PREREQUISITE, IntrospectionPrerequisiteClass))
+#define INTROSPECTION_IS_PREREQUISITE(obj)        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
INTROSPECTION_TYPE_PREREQUISITE))
+#define INTROSPECTION_PREREQUISITE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), 
INTROSPECTION_TYPE_PREREQUISITE, IntrospectionPrerequisiteClass))
+
+typedef struct _IntrospectionPrerequisite         IntrospectionPrerequisite;
+typedef struct _IntrospectionPrerequisiteClass    IntrospectionPrerequisiteClass;
+
+struct _IntrospectionPrerequisite {
+  PeasExtensionBase parent;
+};
+
+struct _IntrospectionPrerequisiteClass {
+  PeasExtensionBaseClass parent_class;
+};
+
+/*
+ * Public methods
+ */
+GType        introspection_prerequisite_get_type         (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __INTROSPECTION_PREREQUISITE_H__ */
diff --git a/tests/libpeas/plugins/extension-c/extension-c-plugin.c 
b/tests/libpeas/plugins/extension-c/extension-c-plugin.c
index 6b08995..3125de8 100644
--- a/tests/libpeas/plugins/extension-c/extension-c-plugin.c
+++ b/tests/libpeas/plugins/extension-c/extension-c-plugin.c
@@ -32,6 +32,7 @@
 #include "introspection-base.h"
 #include "introspection-callable.h"
 #include "introspection-has-prerequisite.h"
+#include "introspection-prerequisite.h"
 
 #include "extension-c-plugin.h"
 
@@ -44,7 +45,7 @@ static void introspection_has_prerequisite_iface_init (IntrospectionHasPrerequis
 
 G_DEFINE_DYNAMIC_TYPE_EXTENDED (TestingExtensionCPlugin,
                                 testing_extension_c_plugin,
-                                PEAS_TYPE_EXTENSION_BASE,
+                                INTROSPECTION_TYPE_PREREQUISITE,
                                 0,
                                 G_IMPLEMENT_INTERFACE_DYNAMIC (INTROSPECTION_TYPE_BASE,
                                                                introspection_base_iface_init)
diff --git a/tests/libpeas/plugins/extension-lua/extension-lua51.lua 
b/tests/libpeas/plugins/extension-lua/extension-lua51.lua
index 4b97a30..69df5f7 100644
--- a/tests/libpeas/plugins/extension-lua/extension-lua51.lua
+++ b/tests/libpeas/plugins/extension-lua/extension-lua51.lua
@@ -22,12 +22,12 @@ local Introspection = lgi.Introspection
 local Peas = lgi.Peas
 
 
-local ExtensionLuaPlugin = GObject.Object:derive('ExtensionLuaPlugin', {
-    Peas.Activatable,
-    Introspection.Base,
-    Introspection.Callable,
-    Introspection.HasPrerequisite
-})
+local ExtensionLuaPlugin =
+    Introspection.Prerequisite:derive('ExtensionLuaPlugin', {
+                                      Peas.Activatable,
+                                      Introspection.Base,
+                                      Introspection.Callable,
+                                      Introspection.HasPrerequisite })
 
 ExtensionLuaPlugin._property.object =
     GObject.ParamSpecObject('object', 'object', 'object',
diff --git a/tests/libpeas/plugins/extension-python/extension-py.py.in 
b/tests/libpeas/plugins/extension-python/extension-py.py.in
index 728b399..d5ea6fa 100644
--- a/tests/libpeas/plugins/extension-python/extension-py.py.in
+++ b/tests/libpeas/plugins/extension-python/extension-py.py.in
@@ -27,7 +27,7 @@ from gi.repository import GObject, Introspection, Peas
 __all__ = [ 'ExtensionPythonPlugin' ]
 
 
-class ExtensionPythonPlugin(GObject.Object, Peas.Activatable,
+class ExtensionPythonPlugin(Introspection.Prerequisite, Peas.Activatable,
                             Introspection.Base, Introspection.Callable,
                             Introspection.HasPrerequisite):
 
diff --git a/tests/libpeas/testing/testing-extension.c b/tests/libpeas/testing/testing-extension.c
index 100d299..60e88f4 100644
--- a/tests/libpeas/testing/testing-extension.c
+++ b/tests/libpeas/testing/testing-extension.c
@@ -190,14 +190,21 @@ test_extension_create_with_prerequisite (PeasEngine     *engine,
                                          PeasPluginInfo *info)
 {
   PeasExtension *extension;
+  gint prerequisite_property = -1;
 
   extension = peas_engine_create_extension (engine, info,
                                             INTROSPECTION_TYPE_HAS_PREREQUISITE,
+                                            "prerequisite-property", 47,
                                             NULL);
 
   g_assert (INTROSPECTION_IS_HAS_PREREQUISITE (extension));
   g_assert (INTROSPECTION_IS_CALLABLE (extension));
 
+  g_object_get (extension,
+                "prerequisite-property", &prerequisite_property,
+                NULL);
+  g_assert_cmpint (prerequisite_property, ==, 47);
+
   g_object_unref (extension);
 }
 


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