diff options
author | Emmanuele Bassi <ebassi@gnome.org> | 2022-07-13 12:45:57 +0100 |
---|---|---|
committer | Emmanuele Bassi <ebassi@gmail.com> | 2023-01-08 21:48:45 +0000 |
commit | 8d44bd13940649a708c8a2186cd3ba58ce6fc503 (patch) | |
tree | 390c0457dc2939502a7c7a1e15e8b933fc1145d7 /giscanner | |
parent | 9ffbdd3738b02a0220c8d9156babf20e0c5ff7d4 (diff) | |
download | gobject-introspection-8d44bd13940649a708c8a2186cd3ba58ce6fc503.tar.gz |
Split disguised attribute into two
The disguised attribute started off as a way to indicate a typedef to a
structure pointer, e.g.
typedef struct Foo* FooPtr;
Over the years, though, it started to include opaque structure types,
e.g.
typedef struct _FooObject FooObject;
typedef struct _FooObjectClass FooObjectClass;
This has led to issues in language bindings, code generators, and
documentation generators, which now have issues when dealing with both
pointer aliases and opaque types.
An initial attempt at fixing this mess in commit f606183a ended up
breaking Vala, and had to be reverted.
To avoid breaking existing users we can follow a similar approach to the
allow-none/nullable/optional solution:
1. introduce a new pair of attributes: "pointer" and "opaque"
2. deprecate the "disguised" attribute
The "pointer" attribute covers the case of pointer types.
The "opaque" attribute covers the case of opaque structured types.
See also: https://gitlab.gnome.org/GNOME/vala/-/issues/735
Fixes: #101
Diffstat (limited to 'giscanner')
-rw-r--r-- | giscanner/ast.py | 12 | ||||
-rw-r--r-- | giscanner/gdumpparser.py | 8 | ||||
-rw-r--r-- | giscanner/girparser.py | 2 | ||||
-rw-r--r-- | giscanner/girwriter.py | 4 | ||||
-rw-r--r-- | giscanner/transformer.py | 27 |
5 files changed, 41 insertions, 12 deletions
diff --git a/giscanner/ast.py b/giscanner/ast.py index bbfbe267..ad94f437 100644 --- a/giscanner/ast.py +++ b/giscanner/ast.py @@ -1021,6 +1021,8 @@ class Compound(Node, Registered): get_type=None, c_symbol_prefix=None, disguised=False, + opaque=False, + pointer=False, tag_name=None): Node.__init__(self, name) Registered.__init__(self, gtype_name, get_type) @@ -1030,6 +1032,8 @@ class Compound(Node, Registered): self.fields = [] self.constructors = [] self.disguised = disguised + self.opaque = opaque + self.pointer = pointer self.gtype_name = gtype_name self.get_type = get_type self.c_symbol_prefix = c_symbol_prefix @@ -1116,6 +1120,8 @@ class Record(Compound): get_type=None, c_symbol_prefix=None, disguised=False, + opaque=False, + pointer=False, tag_name=None): Compound.__init__(self, name, ctype=ctype, @@ -1123,6 +1129,8 @@ class Record(Compound): get_type=get_type, c_symbol_prefix=c_symbol_prefix, disguised=disguised, + opaque=opaque, + pointer=pointer, tag_name=tag_name) # If non-None, this record defines the FooClass C structure # for some Foo GObject (or similar for GInterface) @@ -1143,6 +1151,8 @@ class Union(Compound): get_type=None, c_symbol_prefix=None, disguised=False, + opaque=False, + pointer=False, tag_name=None): Compound.__init__(self, name, ctype=ctype, @@ -1150,6 +1160,8 @@ class Union(Compound): get_type=get_type, c_symbol_prefix=c_symbol_prefix, disguised=disguised, + opaque=opaque, + pointer=pointer, tag_name=tag_name) # If non-None, this union has a copy function for heap # allocated instances diff --git a/giscanner/gdumpparser.py b/giscanner/gdumpparser.py index b5ca4362..10cbcc91 100644 --- a/giscanner/gdumpparser.py +++ b/giscanner/gdumpparser.py @@ -229,7 +229,10 @@ blob containing data gleaned from GObject's primitive introspection.""" get_type='intern', c_symbol_prefix='variant') elif record.name == 'InitiallyUnownedClass': + # InitiallyUnowned is just GObject with extra steps, so we alias + # it in the introspection data record.fields = self._namespace.get('ObjectClass').fields + record.opaque = False record.disguised = False # Introspection over the data we get from the dynamic @@ -522,8 +525,9 @@ different --identifier-prefix.""" % (xmlnode.attrib['name'], self._namespace.ide pair_node.add_gtype(boxed.gtype_name, boxed.get_type) assert boxed.c_symbol_prefix is not None pair_node.c_symbol_prefix = boxed.c_symbol_prefix - # Quick hack - reset the disguised flag; we're setting it - # incorrectly in the scanner + # Backward compatibility hack - reset the disguised flag; we're + # setting it incorrectly in the scanner. We don't change the + # opaque flag, because it's a new one and we define its behavior pair_node.disguised = False else: return False diff --git a/giscanner/girparser.py b/giscanner/girparser.py index 2f8c5f66..b652f2d6 100644 --- a/giscanner/girparser.py +++ b/giscanner/girparser.py @@ -435,6 +435,8 @@ class GIRParser(object): compound = cls(node.attrib.get('name'), ctype=node.attrib.get(_cns('type')), disguised=node.attrib.get('disguised') == '1', + opaque=node.attrib.get('opaque') == '1', + pointer=node.attrib.get('pointer') == '1', gtype_name=node.attrib.get(_glibns('type-name')), get_type=node.attrib.get(_glibns('get-type')), c_symbol_prefix=node.attrib.get(_cns('symbol-prefix'))) diff --git a/giscanner/girwriter.py b/giscanner/girwriter.py index 810acad6..db4dccb4 100644 --- a/giscanner/girwriter.py +++ b/giscanner/girwriter.py @@ -587,6 +587,10 @@ class GIRWriter(XMLWriter): attrs.append(('c:type', record.ctype)) if record.disguised: attrs.append(('disguised', '1')) + if record.opaque: + attrs.append(('opaque', '1')) + if record.pointer: + attrs.append(('pointer', '1')) if record.foreign: attrs.append(('foreign', '1')) if record.is_gtype_struct_for is not None: diff --git a/giscanner/transformer.py b/giscanner/transformer.py index ad2a87f4..3b0bea8a 100644 --- a/giscanner/transformer.py +++ b/giscanner/transformer.py @@ -613,7 +613,7 @@ raise ValueError.""" elif (ctype == CTYPE_FUNCTION): node = self._create_typedef_callback(symbol) elif (ctype == CTYPE_POINTER and symbol.base_type.base_type.type == CTYPE_STRUCT): - node = self._create_typedef_compound(ast.Record, symbol, disguised=True) + node = self._create_typedef_compound(ast.Record, symbol, disguised=True, pointer=True) elif ctype == CTYPE_STRUCT: node = self._create_typedef_compound(ast.Record, symbol) elif ctype == CTYPE_UNION: @@ -801,7 +801,7 @@ raise ValueError.""" const.add_symbol_reference(symbol) return const - def _create_typedef_compound(self, compound_class, symbol, disguised=False): + def _create_typedef_compound(self, compound_class, symbol, disguised=False, pointer=False): name = self.strip_identifier(symbol.ident) assert symbol.base_type if symbol.base_type.name: @@ -840,12 +840,14 @@ raise ValueError.""" # Structs with a typedef name are promoted into the main namespace # by it being returned to the "parse" function and are also added to # the tag namespace if it has a tag_name set. - compound = compound_class(name, symbol.ident, disguised=disguised, tag_name=tag_name) + compound = compound_class(name, symbol.ident, disguised=disguised, pointer=pointer, tag_name=tag_name) if tag_name: - # Force the struct as disguised for now since we do not yet know - # if it has fields that will be parsed. Note that this is using - # an erroneous definition of disguised and we should eventually - # only look at the field count when needed. + # Force the struct as opaque for now since we do not yet know + # if it has fields that will be parsed. + compound.opaque = True + # Set disguised as well, for backward compatibility; the "disguised" field + # is used incorrectly, here, but it's too late for us to change this. See + # https://gitlab.gnome.org/GNOME/gobject-introspection/-/issues/101 compound.disguised = True else: # Case where we have an anonymous struct which is typedef'd: @@ -864,12 +866,17 @@ raise ValueError.""" else: compound = compound_class(None, symbol.ident, tag_name=symbol.ident) - # Make sure disguised is False as we are now about to parse the - # fields of the real struct. - compound.disguised = False # Fields may need to be parsed in either of the above cases because the # Record can be created with a typedef prior to the struct definition. self._parse_fields(symbol, compound) + + # A compound type with no fields is opaque + compound.opaque = len(compound.fields) == 0 + # Unconditionally set disguised to false, for backward compatibility; + # the "disguised" field is used incorrectly, here, but it's too late for + # us to change this. See: + # https://gitlab.gnome.org/GNOME/gobject-introspection/-/issues/101 + compound.disguised = False compound.add_symbol_reference(symbol) return compound |