From 661ca094e8d2279709258169a9e67ff7dc10f3a7 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Tue, 9 Feb 2021 11:38:27 +0000 Subject: 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 | 25 +++++++++++++++++++++++++ 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, 70 insertions(+), 6 deletions(-) diff --git a/docs/gir-1.2.rnc b/docs/gir-1.2.rnc index 9906efed..6a39b20f 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..2042793a 100644 --- a/girepository/giobjectinfo.c +++ b/girepository/giobjectinfo.c @@ -133,6 +133,31 @@ 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: %TRUE if the object type is final + * + * Since: 1.70 + */ +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' -- cgit v1.2.1