[gobject-introspection/ebassi/final-type: 1/2] Add "final" class attribute




commit 0683274e193c6fa97bbab13f158f047a2cde9eae
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Tue Feb 9 11:38:27 2021 +0000

    Add "final" class attribute
    
    A "final" class is a leaf node in a derivable type hierarchy, and cannot
    be derived any further.
    
    This matches the changes in libgobject that introduced G_TYPE_FLAG_FINAL
    to the type flags.

 docs/gir-1.2.rnc                  |  2 ++
 girepository/gdump.c              | 11 +++++++++++
 girepository/giobjectinfo.c       | 23 +++++++++++++++++++++++
 girepository/giobjectinfo.h       |  3 +++
 girepository/girnode.c            |  1 +
 girepository/girnode.h            |  1 +
 girepository/girparser.c          |  3 +++
 girepository/girwriter.c          |  5 +++++
 girepository/gitypelib-internal.h |  8 +++++---
 giscanner/ast.py                  |  4 +++-
 giscanner/gdumpparser.py          |  8 ++++++--
 giscanner/girparser.py            |  3 +++
 giscanner/girwriter.py            |  2 ++
 13 files changed, 68 insertions(+), 6 deletions(-)
---
diff --git a/docs/gir-1.2.rnc b/docs/gir-1.2.rnc
index 8f53c18e..bac6968d 100644
--- a/docs/gir-1.2.rnc
+++ b/docs/gir-1.2.rnc
@@ -170,6 +170,8 @@ grammar {
       attribute abstract { "0" | "1" }?,
       ## Binary attribute to declare the class fundamental or not (top-level class which do not derives from 
any other type)
       attribute glib:fundamental { "0" | "1" }?,
+      ## Binary attribute to declare the class final or not (non-derivable class in a derivable hierarchy)
+      attribute glib:final { "0" | "1" }?,
 
       # Other elements a class can contain
       (Info.elements
diff --git a/girepository/gdump.c b/girepository/gdump.c
index 0e8c6035..e79f1719 100644
--- a/girepository/gdump.c
+++ b/girepository/gdump.c
@@ -241,6 +241,12 @@ dump_object_type (GType type, const char *symbol, GOutputStream *out)
 
   if (G_TYPE_IS_ABSTRACT (type))
     escaped_printf (out, " abstract=\"1\"");
+
+#if GLIB_CHECK_VERSION (2, 70, 0)
+  if (G_TYPE_IS_FINAL (type))
+    escaped_printf (out, " final=\"1\"");
+#endif
+
   goutput_write (out, ">\n");
 
   interfaces = g_type_interfaces (type, &n_interfaces);
@@ -354,6 +360,11 @@ dump_fundamental_type (GType type, const char *symbol, GOutputStream *out)
   if (G_TYPE_IS_ABSTRACT (type))
     escaped_printf (out, " abstract=\"1\"");
 
+#if GLIB_CHECK_VERSION (2, 70, 0)
+  if (G_TYPE_IS_FINAL (type))
+    escaped_printf (out, " final=\"1\"");
+#endif
+
   if (G_TYPE_IS_INSTANTIATABLE (type))
     escaped_printf (out, " instantiatable=\"1\"");
 
diff --git a/girepository/giobjectinfo.c b/girepository/giobjectinfo.c
index 13cfdaa8..15a518c1 100644
--- a/girepository/giobjectinfo.c
+++ b/girepository/giobjectinfo.c
@@ -133,6 +133,29 @@ g_object_info_get_abstract (GIObjectInfo *info)
   return blob->abstract != 0;
 }
 
+/**
+ * g_object_info_get_final:
+ * @info: a #GIObjectInfo
+ *
+ * Checks whether the object type is a final type, i.e. if it cannot
+ * be derived
+ *
+ * Returns: %TRUYE if the object type is final
+ */
+gboolean
+g_object_info_get_final (GIObjectInfo *info)
+{
+  GIRealInfo *rinfo = (GIRealInfo *) info;
+  ObjectBlob *blob;
+
+  g_return_val_if_fail (info != NULL, FALSE);
+  g_return_val_if_fail (GI_IS_OBJECT_INFO (info), FALSE);
+
+  blob = (ObjectBlob *) &rinfo->typelib->data[rinfo->offset];
+
+  return blob->final_ != 0;
+}
+
 /**
  * g_object_info_get_fundamental:
  * @info: a #GIObjectInfo
diff --git a/girepository/giobjectinfo.h b/girepository/giobjectinfo.h
index dac95abf..aa6f9c9d 100644
--- a/girepository/giobjectinfo.h
+++ b/girepository/giobjectinfo.h
@@ -87,6 +87,9 @@ const gchar *     g_object_info_get_type_init  (GIObjectInfo *info);
 GI_AVAILABLE_IN_ALL
 gboolean          g_object_info_get_abstract     (GIObjectInfo *info);
 
+GI_AVAILABLE_IN_1_70
+gboolean          g_object_info_get_final        (GIObjectInfo *info);
+
 GI_AVAILABLE_IN_ALL
 gboolean          g_object_info_get_fundamental  (GIObjectInfo *info);
 
diff --git a/girepository/girnode.c b/girepository/girnode.c
index fadfe56f..796f2001 100644
--- a/girepository/girnode.c
+++ b/girepository/girnode.c
@@ -2096,6 +2096,7 @@ _g_ir_node_build_typelib (GIrNode         *node,
        blob->blob_type = BLOB_TYPE_OBJECT;
        blob->abstract = object->abstract;
         blob->fundamental = object->fundamental;
+        blob->final_ = object->final_;
        blob->deprecated = object->deprecated;
        blob->reserved = 0;
        blob->name = _g_ir_write_string (node->name, strings, data, offset2);
diff --git a/girepository/girnode.h b/girepository/girnode.h
index e4ce85a4..9b42accd 100644
--- a/girepository/girnode.h
+++ b/girepository/girnode.h
@@ -240,6 +240,7 @@ struct _GIrNodeInterface
   gboolean abstract;
   gboolean deprecated;
   gboolean fundamental;
+  gboolean final_;
 
   gchar *gtype_name;
   gchar *gtype_init;
diff --git a/girepository/girparser.c b/girepository/girparser.c
index f62b1de6..b6983d1a 100644
--- a/girepository/girparser.c
+++ b/girepository/girparser.c
@@ -1806,6 +1806,7 @@ start_class (GMarkupParseContext *context,
   const gchar *deprecated;
   const gchar *abstract;
   const gchar *fundamental;
+  const gchar *final;
   const gchar *ref_func;
   const gchar *unref_func;
   const gchar *set_value_func;
@@ -1826,6 +1827,7 @@ start_class (GMarkupParseContext *context,
   typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
   deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
   abstract = find_attribute ("abstract", attribute_names, attribute_values);
+  final = find_attribute ("final", attribute_names, attribute_values);
   fundamental = find_attribute ("glib:fundamental", attribute_names, attribute_values);
   ref_func = find_attribute ("glib:ref-func", attribute_names, attribute_values);
   unref_func = find_attribute ("glib:unref-func", attribute_names, attribute_values);
@@ -1861,6 +1863,7 @@ start_class (GMarkupParseContext *context,
     iface->deprecated = FALSE;
 
   iface->abstract = abstract && strcmp (abstract, "1") == 0;
+  iface->final_ = final && strcmp (final, "1") == 0;
 
   if (fundamental)
     iface->fundamental = TRUE;
diff --git a/girepository/girwriter.c b/girepository/girwriter.c
index d092df10..104ee633 100644
--- a/girepository/girwriter.c
+++ b/girepository/girwriter.c
@@ -988,6 +988,7 @@ write_object_info (const gchar  *namespace,
   gboolean deprecated;
   gboolean is_abstract;
   gboolean is_fundamental;
+  gboolean is_final;
   GIObjectInfo *pnode;
   GIStructInfo *class_struct;
   gint i;
@@ -996,6 +997,7 @@ write_object_info (const gchar  *namespace,
   deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
   is_abstract = g_object_info_get_abstract (info);
   is_fundamental = g_object_info_get_fundamental (info);
+  is_final = g_object_info_get_final (info);
 
   type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
   type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
@@ -1019,6 +1021,9 @@ write_object_info (const gchar  *namespace,
   if (is_abstract)
     xml_printf (file, " abstract=\"1\"");
 
+  if (is_final)
+    xml_printf (file, " final=\"1\"");
+
   xml_printf (file, " glib:type-name=\"%s\" glib:get-type=\"%s\"", type_name, type_init);
 
   if (is_fundamental)
diff --git a/girepository/gitypelib-internal.h b/girepository/gitypelib-internal.h
index 28b177d6..f25b863b 100644
--- a/girepository/gitypelib-internal.h
+++ b/girepository/gitypelib-internal.h
@@ -1034,10 +1034,11 @@ typedef struct {
 /**
  * ObjectBlob:
  * @blob_type: #BLOB_TYPE_OBJECT
- * @deprecated: TODO
- * @abstract: TODO
+ * @deprecated: whether the type is deprecated
+ * @abstract: whether the type can be instantiated
  * @fundamental: this object is not a GObject derived type, instead it's
  *   an additional fundamental type.
+ * @final: whether the type can be derived
  * @reserved: Reserved for future use.
  * @name: TODO
  * @gtype_name: String name of the associated #GType
@@ -1076,7 +1077,8 @@ typedef struct {
   guint16   deprecated   : 1;
   guint16   abstract     : 1;
   guint16   fundamental  : 1;
-  guint16   reserved     :13;
+  guint16   final_       : 1;
+  guint16   reserved     :12;
   guint32   name;
 
   guint32   gtype_name;
diff --git a/giscanner/ast.py b/giscanner/ast.py
index 9a0d95c7..e11fc988 100644
--- a/giscanner/ast.py
+++ b/giscanner/ast.py
@@ -1188,7 +1188,8 @@ class Class(Node, Registered):
                  gtype_name=None,
                  get_type=None,
                  c_symbol_prefix=None,
-                 is_abstract=False):
+                 is_abstract=False,
+                 is_final=False):
         Node.__init__(self, name)
         Registered.__init__(self, gtype_name, get_type)
         self.ctype = ctype
@@ -1205,6 +1206,7 @@ class Class(Node, Registered):
         self.parent_chain = []
         self.glib_type_struct = None
         self.is_abstract = is_abstract
+        self.is_final = is_final
         self.methods = []
         self.virtual_methods = []
         self.static_methods = []
diff --git a/giscanner/gdumpparser.py b/giscanner/gdumpparser.py
index 03a4ecc3..1a0794d4 100644
--- a/giscanner/gdumpparser.py
+++ b/giscanner/gdumpparser.py
@@ -320,6 +320,7 @@ different --identifier-prefix.""" % (xmlnode.attrib['name'], self._namespace.ide
     def _introspect_object(self, xmlnode):
         type_name = xmlnode.attrib['name']
         is_abstract = bool(xmlnode.attrib.get('abstract', False))
+        is_final = bool(xmlnode.attrib.get('final', False))
         (get_type, c_symbol_prefix) = self._split_type_and_symbol_prefix(xmlnode)
         try:
             object_name = self._transformer.strip_identifier(type_name)
@@ -329,7 +330,8 @@ different --identifier-prefix.""" % (xmlnode.attrib['name'], self._namespace.ide
                          gtype_name=type_name,
                          get_type=get_type,
                          c_symbol_prefix=c_symbol_prefix,
-                         is_abstract=is_abstract)
+                         is_abstract=is_abstract,
+                         is_final=is_final)
         self._parse_parents(xmlnode, node)
         self._introspect_properties(node, xmlnode)
         self._introspect_signals(node, xmlnode)
@@ -458,6 +460,7 @@ different --identifier-prefix.""" % (xmlnode.attrib['name'], self._namespace.ide
         type_name = xmlnode.attrib['name']
 
         is_abstract = bool(xmlnode.attrib.get('abstract', False))
+        is_final = bool(xmlnode.attrib.get('final', False))
         (get_type, c_symbol_prefix) = self._split_type_and_symbol_prefix(xmlnode)
         try:
             fundamental_name = self._transformer.strip_identifier(type_name)
@@ -469,7 +472,8 @@ different --identifier-prefix.""" % (xmlnode.attrib['name'], self._namespace.ide
                          gtype_name=type_name,
                          get_type=get_type,
                          c_symbol_prefix=c_symbol_prefix,
-                         is_abstract=is_abstract)
+                         is_abstract=is_abstract,
+                         is_final=is_final)
         self._parse_parents(xmlnode, node)
         node.fundamental = True
         self._introspect_implemented_interfaces(node, xmlnode)
diff --git a/giscanner/girparser.py b/giscanner/girparser.py
index da200a65..9f124d89 100644
--- a/giscanner/girparser.py
+++ b/giscanner/girparser.py
@@ -259,6 +259,9 @@ class GIRParser(object):
             is_abstract = node.attrib.get('abstract')
             is_abstract = is_abstract and is_abstract != '0'
             ctor_kwargs['is_abstract'] = is_abstract
+            is_final = node.attrib.get('final')
+            is_final = is_final and is_final != '0'
+            ctor_kwargs['is_final'] = is_final
         else:
             raise AssertionError(node)
 
diff --git a/giscanner/girwriter.py b/giscanner/girwriter.py
index 54c957c0..d276e923 100644
--- a/giscanner/girwriter.py
+++ b/giscanner/girwriter.py
@@ -475,6 +475,8 @@ class GIRWriter(XMLWriter):
                               self._type_to_name(node.parent_type)))
             if node.is_abstract:
                 attrs.append(('abstract', '1'))
+            if node.is_final:
+                attrs.append(('final', '1'))
         else:
             assert isinstance(node, ast.Interface)
             tag_name = 'interface'


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