From 3943988d5addbea4603f9b4ee5103c604d03e8f4 Mon Sep 17 00:00:00 2001 From: Krzesimir Nowak Date: Wed, 4 Jul 2012 22:52:02 +0200 Subject: [PATCH] giscanner: Write detailed information in "type" tag's "c:type" attribute. That is - write also type qualifiers (const and volatile here). Update existing tests and add a new struct to regress.h having members with type qualifiers. https://bugzilla.gnome.org/show_bug.cgi?id=656445 --- giscanner/ast.py | 4 +- giscanner/girwriter.py | 4 +- giscanner/transformer.py | 84 +++++++++++++++++++++++------ tests/scanner/Annotation-1.0-expected.gir | 10 ++-- tests/scanner/Foo-1.0-expected.gir | 18 +++---- tests/scanner/Regress-1.0-expected.gir | 90 +++++++++++++++++++------------ tests/scanner/Utility-1.0-expected.gir | 6 +-- tests/scanner/regress.h | 14 +++++ 8 files changed, 163 insertions(+), 67 deletions(-) diff --git a/giscanner/ast.py b/giscanner/ast.py index 456f921..6945d60 100644 --- a/giscanner/ast.py +++ b/giscanner/ast.py @@ -45,7 +45,8 @@ from a C type string, or a gtype_name (from g_type_name()). target_foreign=None, _target_unknown=False, is_const=False, - origin_symbol=None): + origin_symbol=None, + complete_ctype=None): self.ctype = ctype self.gtype_name = gtype_name self.origin_symbol = origin_symbol @@ -68,6 +69,7 @@ from a C type string, or a gtype_name (from g_type_name()). self.target_giname = target_giname self.target_foreign = target_foreign self.is_const = is_const + self.complete_ctype = complete_ctype @property def resolved(self): diff --git a/giscanner/girwriter.py b/giscanner/girwriter.py index bfe82a8..cb13d21 100644 --- a/giscanner/girwriter.py +++ b/giscanner/girwriter.py @@ -272,7 +272,9 @@ and/or use gtk-doc annotations. ''') def _write_type(self, ntype, relation=None, function=None): assert isinstance(ntype, ast.Type), ntype attrs = [] - if ntype.ctype: + if ntype.complete_ctype: + attrs.append(('c:type', ntype.complete_ctype)) + elif ntype.ctype: attrs.append(('c:type', ntype.ctype)) if isinstance(ntype, ast.Varargs): with self.tagcontext('varargs', []): diff --git a/giscanner/transformer.py b/giscanner/transformer.py index cf284d8..91d00af 100644 --- a/giscanner/transformer.py +++ b/giscanner/transformer.py @@ -32,7 +32,7 @@ from .sourcescanner import ( CSYMBOL_TYPE_FUNCTION, CSYMBOL_TYPE_TYPEDEF, CSYMBOL_TYPE_STRUCT, CSYMBOL_TYPE_ENUM, CSYMBOL_TYPE_UNION, CSYMBOL_TYPE_OBJECT, CSYMBOL_TYPE_MEMBER, CSYMBOL_TYPE_ELLIPSIS, CSYMBOL_TYPE_CONST, - TYPE_QUALIFIER_CONST) + TYPE_QUALIFIER_CONST, TYPE_QUALIFIER_VOLATILE) class TransformerException(Exception): pass @@ -435,6 +435,45 @@ raise ValueError.""" value = 'gpointer' return value + def _create_complete_source_type(self, source_type): + assert source_type is not None + + const = (source_type.type_qualifier & TYPE_QUALIFIER_CONST) + volatile = (source_type.type_qualifier & TYPE_QUALIFIER_VOLATILE) + + if source_type.type == CTYPE_VOID: + return 'void' + elif source_type.type in [CTYPE_BASIC_TYPE, + CTYPE_TYPEDEF, + CTYPE_STRUCT, + CTYPE_UNION, + CTYPE_ENUM]: + value = source_type.name + if const: + value = 'const ' + value + if volatile: + value = 'volatile ' + value + elif source_type.type == CTYPE_ARRAY: + return self._create_complete_source_type(source_type.base_type) + elif source_type.type == CTYPE_POINTER: + value = self._create_complete_source_type(source_type.base_type) + '*' + # TODO: handle pointer to function as a special case? + if const: + value += ' const' + if volatile: + value += ' volatile' + + else: + if const: + value = 'gconstpointer' + else: + value = 'gpointer' + if volatile: + value = 'volatile ' + value + return value + + return value + def _create_parameters(self, base_type): # warn if we see annotations for unknown parameters param_names = set(child.ident for child in base_type.child_list) @@ -476,6 +515,7 @@ raise ValueError.""" # Special handling for fields; we don't have annotations on them # to apply later, yet. if source_type.type == CTYPE_ARRAY: + complete_ctype = self._create_complete_source_type(source_type) # If the array contains anonymous unions, like in the GValue # struct, we need to handle this specially. This is necessary # to be able to properly calculate the size of the compound @@ -484,7 +524,7 @@ raise ValueError.""" if (source_type.base_type.type == CTYPE_UNION and source_type.base_type.name is None): synthesized_type = self._synthesize_union_type(symbol, parent_symbol) - ftype = ast.Array(None, synthesized_type) + ftype = ast.Array(None, synthesized_type, complete_ctype=complete_ctype) else: ctype = self._create_source_type(source_type) canonical_ctype = self._canonicalize_ctype(ctype) @@ -492,8 +532,15 @@ raise ValueError.""" derefed_name = canonical_ctype[:-1] else: derefed_name = canonical_ctype - ftype = ast.Array(None, self.create_type_from_ctype_string(ctype), - ctype=derefed_name) + if complete_ctype[-1] == '*': + derefed_complete_ctype = complete_ctype[:-1] + else: + derefed_complete_ctype = complete_ctype + from_ctype = self.create_type_from_ctype_string(ctype, + complete_ctype=complete_ctype) + ftype = ast.Array(None, from_ctype, + ctype=derefed_name, + complete_ctype=derefed_complete_ctype) child_list = list(symbol.base_type.child_list) ftype.zeroterminated = False if child_list: @@ -535,7 +582,9 @@ raise ValueError.""" message.warn(e) return None if symbol.base_type.name: - target = self.create_type_from_ctype_string(symbol.base_type.name) + complete_ctype = self._create_complete_source_type(symbol.base_type) + target = self.create_type_from_ctype_string(symbol.base_type.name, + complete_ctype=complete_ctype) else: target = ast.TYPE_ANY if name in ast.type_names: @@ -588,20 +637,22 @@ raise ValueError.""" def _create_type_from_base(self, source_type, is_parameter=False, is_return=False): ctype = self._create_source_type(source_type) + complete_ctype = self._create_complete_source_type(source_type) const = ((source_type.type == CTYPE_POINTER) and (source_type.base_type.type_qualifier & TYPE_QUALIFIER_CONST)) return self.create_type_from_ctype_string(ctype, is_const=const, - is_parameter=is_parameter, is_return=is_return) + is_parameter=is_parameter, is_return=is_return, + complete_ctype=complete_ctype) def _create_bare_container_type(self, base, ctype=None, - is_const=False): + is_const=False, complete_ctype=None): if base in ('GList', 'GSList', 'GLib.List', 'GLib.SList'): if base in ('GList', 'GSList'): name = 'GLib.' + base[1:] else: name = base return ast.List(name, ast.TYPE_ANY, ctype=ctype, - is_const=is_const) + is_const=is_const, complete_ctype=complete_ctype) elif base in ('GArray', 'GPtrArray', 'GByteArray', 'GLib.Array', 'GLib.PtrArray', 'GLib.ByteArray', 'GObject.Array', 'GObject.PtrArray', 'GObject.ByteArray'): @@ -610,13 +661,15 @@ raise ValueError.""" else: name = 'GLib.' + base[1:] return ast.Array(name, ast.TYPE_ANY, ctype=ctype, - is_const=is_const) + is_const=is_const, complete_ctype=complete_ctype) elif base in ('GHashTable', 'GLib.HashTable', 'GObject.HashTable'): - return ast.Map(ast.TYPE_ANY, ast.TYPE_ANY, ctype=ctype, is_const=is_const) + return ast.Map(ast.TYPE_ANY, ast.TYPE_ANY, ctype=ctype, is_const=is_const, + complete_ctype=complete_ctype) return None def create_type_from_ctype_string(self, ctype, is_const=False, - is_parameter=False, is_return=False): + is_parameter=False, is_return=False, + complete_ctype=None): canonical = self._canonicalize_ctype(ctype) base = canonical.replace('*', '') @@ -625,17 +678,18 @@ raise ValueError.""" bare_utf8 = ast.TYPE_STRING.clone() bare_utf8.ctype = None return ast.Array(None, bare_utf8, ctype=ctype, - is_const=is_const) + is_const=is_const, complete_ctype=complete_ctype) fundamental = ast.type_names.get(base) if fundamental is not None: return ast.Type(target_fundamental=fundamental.target_fundamental, ctype=ctype, - is_const=is_const) - container = self._create_bare_container_type(base, ctype=ctype, is_const=is_const) + is_const=is_const, complete_ctype=complete_ctype) + container = self._create_bare_container_type(base, ctype=ctype, is_const=is_const, + complete_ctype=complete_ctype) if container: return container - return ast.Type(ctype=ctype, is_const=is_const) + return ast.Type(ctype=ctype, is_const=is_const, complete_ctype=complete_ctype) def _create_parameter(self, symbol): if symbol.type == CSYMBOL_TYPE_ELLIPSIS: diff --git a/tests/scanner/Annotation-1.0-expected.gir b/tests/scanner/Annotation-1.0-expected.gir index ce43b36..2ea6c54 100644 --- a/tests/scanner/Annotation-1.0-expected.gir +++ b/tests/scanner/Annotation-1.0-expected.gir @@ -39,12 +39,12 @@ and/or use gtk-doc annotations. --> This is a callback. array of ints - + array of ints - + @@ -57,7 +57,7 @@ and/or use gtk-doc annotations. --> - + @@ -110,7 +110,7 @@ and/or use gtk-doc annotations. --> - + @@ -659,7 +659,7 @@ it says it's pointer but it's actually a string. Some data. - + diff --git a/tests/scanner/Foo-1.0-expected.gir b/tests/scanner/Foo-1.0-expected.gir index b18375a..b0c3634 100644 --- a/tests/scanner/Foo-1.0-expected.gir +++ b/tests/scanner/Foo-1.0-expected.gir @@ -446,7 +446,7 @@ uses a C sugar return type. - + @@ -478,7 +478,7 @@ uses a C sugar return type. - + @@ -661,7 +661,7 @@ uses a C sugar return type. source rectangle - + @@ -910,7 +910,7 @@ exposed to language bindings. - + @@ -936,7 +936,7 @@ exposed to language bindings. - + @@ -1143,14 +1143,14 @@ exposed to language bindings. - + - + - + - + diff --git a/tests/scanner/Regress-1.0-expected.gir b/tests/scanner/Regress-1.0-expected.gir index 3f2b6dd..0b39bff 100644 --- a/tests/scanner/Regress-1.0-expected.gir +++ b/tests/scanner/Regress-1.0-expected.gir @@ -275,7 +275,7 @@ use it should be. - + @@ -351,7 +351,7 @@ use it should be. glib:nick="value4"/> - + @@ -502,7 +502,7 @@ use it should be. + c:type="const RegressTestFundamentalObject*"/> @@ -534,7 +534,7 @@ use it should be. - + @@ -621,7 +621,7 @@ use it should be. - + @@ -686,7 +686,7 @@ case. Meaningless string - + @@ -700,7 +700,7 @@ case. Meaningless string - + @@ -983,7 +983,7 @@ raise an error. - + - + Meaningless string - + @@ -1357,7 +1357,8 @@ Use with regress_test_obj_emit_sig_with_obj - + @@ -1507,6 +1508,29 @@ Use with regress_test_obj_emit_sig_with_obj + + + + + + + + + + + + + + + + + + + + + + + @@ -2298,7 +2322,7 @@ call and can be released on return. c:identifier="regress_test_enum_param" moved-to="TestEnum.param"> - + @@ -2435,7 +2459,7 @@ element-type annotation. - + @@ -2459,7 +2483,7 @@ element-type annotation. - + @@ -2481,7 +2505,7 @@ element-type annotation. - + @@ -2499,7 +2523,7 @@ element-type annotation. caller-allocates="0" transfer-ownership="full" allow-none="1"> - + @@ -2509,7 +2533,7 @@ element-type annotation. - + @@ -2538,7 +2562,7 @@ element-type annotation. - + @@ -2560,7 +2584,7 @@ element-type annotation. - + @@ -2626,7 +2650,7 @@ element-type annotation. - + @@ -2648,7 +2672,7 @@ element-type annotation. - + @@ -2814,7 +2838,7 @@ element-type annotation. - + @@ -2825,7 +2849,7 @@ element-type annotation. - + @@ -2966,7 +2990,7 @@ What we're testing here is that the scanner ignores the @a nested inside XML. - + - + @@ -3090,7 +3114,7 @@ What we're testing here is that the scanner ignores the @a nested inside XML. - + - + - + - + @@ -3294,7 +3318,7 @@ What we're testing here is that the scanner ignores the @a nested inside XML. - + @@ -3302,7 +3326,7 @@ What we're testing here is that the scanner ignores the @a nested inside XML. UTF-8 string - + @@ -3411,7 +3435,7 @@ What we're testing here is that the scanner ignores the @a nested inside XML. - + @@ -3419,7 +3443,7 @@ What we're testing here is that the scanner ignores the @a nested inside XML. the int wrapped in a GValue. - + diff --git a/tests/scanner/Utility-1.0-expected.gir b/tests/scanner/Utility-1.0-expected.gir index dec7984..747f99c 100644 --- a/tests/scanner/Utility-1.0-expected.gir +++ b/tests/scanner/Utility-1.0-expected.gir @@ -50,7 +50,7 @@ and/or use gtk-doc annotations. --> - + @@ -75,7 +75,7 @@ and/or use gtk-doc annotations. --> - + - +