diff options
author | Princeton Ferro <princetonferro@gmail.com> | 2021-07-15 02:32:00 -0400 |
---|---|---|
committer | Rico Tzschichholz <ricotz@ubuntu.com> | 2021-08-18 13:47:50 +0200 |
commit | cf3a4087bcc5dd443f1eb99b893fe8cb2c536ab8 (patch) | |
tree | 173b0285b376ea8a34f75d87dce453273faa8df1 | |
parent | 9471ab001c713598702c0a35ac9c93d01b6233ef (diff) | |
download | vala-cf3a4087bcc5dd443f1eb99b893fe8cb2c536ab8.tar.gz |
girwriter: Improve struct creation method binding
Struct creation methods are supposed to have `void` return type and take
an implicit `self` as the first instance parameter.
-rw-r--r-- | codegen/valagirwriter.vala | 11 | ||||
-rw-r--r-- | tests/girwriter/GirTest-1.0.gir-expected | 32 | ||||
-rw-r--r-- | tests/girwriter/girtest.vapigen-expected | 10 | ||||
-rw-r--r-- | vala/valagirparser.vala | 25 |
4 files changed, 49 insertions, 29 deletions
diff --git a/codegen/valagirwriter.vala b/codegen/valagirwriter.vala index 997d899ff..22b024513 100644 --- a/codegen/valagirwriter.vala +++ b/codegen/valagirwriter.vala @@ -1207,8 +1207,8 @@ public class Vala.GIRWriter : CodeVisitor { } if (constructor && ret_is_struct) { - // struct constructor has its result as first parameter - write_param_or_return (return_type, "parameter", ref index, false, "result", return_comment, ParameterDirection.OUT, constructor, true); + // struct constructor has a caller-allocates / out-parameter as instance + write_param_or_return (return_type, "instance-parameter", ref index, false, "self", return_comment, ParameterDirection.OUT, constructor, true); } if (type_params != null) { @@ -1422,12 +1422,14 @@ public class Vala.GIRWriter : CodeVisitor { bool is_struct = m.parent_symbol is Struct; // GI doesn't like constructors that return void type - string tag_name = is_struct ? "function" : "constructor"; + string tag_name = is_struct ? "method" : "constructor"; if (m.parent_symbol is Class && m == ((Class)m.parent_symbol).default_construction_method || m.parent_symbol is Struct && m == ((Struct)m.parent_symbol).default_construction_method) { string m_name = is_struct ? "init" : "new"; buffer.append_printf ("<%s name=\"%s\" c:identifier=\"%s\"", tag_name, m_name, get_ccode_name (m)); + } else if (is_struct) { + buffer.append_printf ("<%s name=\"init_%s\" c:identifier=\"%s\"", tag_name, m.name, get_ccode_name (m)); } else { buffer.append_printf ("<%s name=\"%s\" c:identifier=\"%s\"", tag_name, m.name, get_ccode_name (m)); } @@ -1565,7 +1567,8 @@ public class Vala.GIRWriter : CodeVisitor { unowned DelegateType? delegate_type = type as DelegateType; unowned ArrayType? array_type = type as ArrayType; - if (type != null && ((type.value_owned && delegate_type == null) || (constructor && !type.type_symbol.is_subtype_of (ginitiallyunowned_type)))) { + if (type != null && ((type.value_owned && delegate_type == null) || (constructor + && !(type.type_symbol is Struct || type.type_symbol.is_subtype_of (ginitiallyunowned_type))))) { var any_owned = false; foreach (var generic_arg in type.get_type_arguments ()) { any_owned |= generic_arg.value_owned; diff --git a/tests/girwriter/GirTest-1.0.gir-expected b/tests/girwriter/GirTest-1.0.gir-expected index 7d30eea03..0843634a0 100644 --- a/tests/girwriter/GirTest-1.0.gir-expected +++ b/tests/girwriter/GirTest-1.0.gir-expected @@ -2769,24 +2769,24 @@ <field name="internal_field_name" writable="1"> <type name="gint" c:type="gint"/> </field> - <function name="init" c:identifier="gir_test_boxed_struct_init"> + <method name="init" c:identifier="gir_test_boxed_struct_init"> <return-value transfer-ownership="none"> <type name="none" c:type="void"/> </return-value> <parameters> - <parameter name="result" direction="out" transfer-ownership="full" caller-allocates="1"> + <instance-parameter name="self" direction="out" transfer-ownership="none" caller-allocates="1"> <type name="GirTest.BoxedStruct" c:type="GirTestBoxedStruct*"/> - </parameter> + </instance-parameter> </parameters> - </function> - <function name="foo" c:identifier="gir_test_boxed_struct_init_foo"> + </method> + <method name="init_foo" c:identifier="gir_test_boxed_struct_init_foo"> <return-value transfer-ownership="none"> <type name="none" c:type="void"/> </return-value> <parameters> - <parameter name="result" direction="out" transfer-ownership="full" caller-allocates="1"> + <instance-parameter name="self" direction="out" transfer-ownership="none" caller-allocates="1"> <type name="GirTest.BoxedStruct" c:type="GirTestBoxedStruct*"/> - </parameter> + </instance-parameter> <parameter name="param1" transfer-ownership="none"> <type name="gint" c:type="gint"/> </parameter> @@ -2794,7 +2794,7 @@ <type name="gint" c:type="gint"/> </parameter> </parameters> - </function> + </method> <method name="inv" c:identifier="gir_test_boxed_struct_inv"> <return-value transfer-ownership="full"> <type name="none" c:type="void"/> @@ -2813,24 +2813,24 @@ <field name="internal_field_name" writable="1"> <type name="gint" c:type="gint"/> </field> - <function name="init" c:identifier="gir_test_struct_init"> + <method name="init" c:identifier="gir_test_struct_init"> <return-value transfer-ownership="none"> <type name="none" c:type="void"/> </return-value> <parameters> - <parameter name="result" direction="out" transfer-ownership="full" caller-allocates="1"> + <instance-parameter name="self" direction="out" transfer-ownership="none" caller-allocates="1"> <type name="GirTest.Struct" c:type="GirTestStruct*"/> - </parameter> + </instance-parameter> </parameters> - </function> - <function name="foo" c:identifier="gir_test_struct_init_foo"> + </method> + <method name="init_foo" c:identifier="gir_test_struct_init_foo"> <return-value transfer-ownership="none"> <type name="none" c:type="void"/> </return-value> <parameters> - <parameter name="result" direction="out" transfer-ownership="full" caller-allocates="1"> + <instance-parameter name="self" direction="out" transfer-ownership="none" caller-allocates="1"> <type name="GirTest.Struct" c:type="GirTestStruct*"/> - </parameter> + </instance-parameter> <parameter name="param1" transfer-ownership="none"> <type name="gint" c:type="gint"/> </parameter> @@ -2838,7 +2838,7 @@ <type name="gint" c:type="gint"/> </parameter> </parameters> - </function> + </method> <method name="inv" c:identifier="gir_test_struct_inv"> <return-value transfer-ownership="full"> <type name="none" c:type="void"/> diff --git a/tests/girwriter/girtest.vapigen-expected b/tests/girwriter/girtest.vapigen-expected index 1bc67d83a..61d438058 100644 --- a/tests/girwriter/girtest.vapigen-expected +++ b/tests/girwriter/girtest.vapigen-expected @@ -202,9 +202,8 @@ namespace GirTest { public struct BoxedStruct { public int field_name; public int internal_field_name; - [CCode (cname = "gir_test_boxed_struct_init_foo")] - public void foo (int param1, int param2); - public static GirTest.BoxedStruct init (); + public BoxedStruct (); + public BoxedStruct.foo (int param1, int param2); public void inv (); } [CCode (cheader_filename = "girtest.h", cname = "GirTestNamedCompactClass", has_type_id = false)] @@ -218,9 +217,8 @@ namespace GirTest { public struct Struct { public int field_name; public int internal_field_name; - [CCode (cname = "gir_test_struct_init_foo")] - public void foo (int param1, int param2); - public static GirTest.Struct init (); + public Struct (); + public Struct.foo (int param1, int param2); public void inv (); } [CCode (cheader_filename = "girtest.h", cprefix = "GIR_TEST_ENUM_TEST_", type_id = "gir_test_enum_test_get_type ()")] diff --git a/vala/valagirparser.vala b/vala/valagirparser.vala index 9db320a72..a005efdb0 100644 --- a/vala/valagirparser.vala +++ b/vala/valagirparser.vala @@ -3475,10 +3475,29 @@ public class Vala.GirParser : CodeVisitor { } pop_metadata (); continue; - } else { - //TODO can more be done here? - m.binding = MemberBinding.STATIC; + } else if (current.parent.symbol is Struct + && caller_allocates && param.direction == ParameterDirection.OUT) { + // struct methods that have instance parameters with 'out' direction are usually creation methods + string? cm_name = m.name; + if (cm_name != null && (cm_name == "init" || cm_name.has_prefix ("init_"))) { + if (cm_name == "init") { + cm_name = null; + } else if (cm_name.has_prefix ("init_")) { + cm_name = cm_name.substring ("init_".length); + } + s = new CreationMethod (null, cm_name, m.source_reference, m.comment); + s.access = SymbolAccessibility.PUBLIC; + current.symbol = s; + pop_metadata (); + continue; + } + } else if (current.parent.symbol is Class && ((Class) current.parent.symbol).is_compact + && caller_allocates && param.direction == ParameterDirection.OUT) { + pop_metadata (); + continue; } + //TODO can more be done here? + m.binding = MemberBinding.STATIC; } } |