]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
girwriter: Improve struct creation method binding
authorPrinceton Ferro <princetonferro@gmail.com>
Thu, 15 Jul 2021 06:32:00 +0000 (02:32 -0400)
committerRico Tzschichholz <ricotz@ubuntu.com>
Wed, 18 Aug 2021 11:47:50 +0000 (13:47 +0200)
Struct creation methods are supposed to have `void` return type and take
an implicit `self` as the first instance parameter.

codegen/valagirwriter.vala
tests/girwriter/GirTest-1.0.gir-expected
tests/girwriter/girtest.vapigen-expected
vala/valagirparser.vala

index 997d899ffec6cf18d8ba1dcf0db3fb348e77f76a..22b0245139f2400da5c9a704f6440d451387c4d0 100644 (file)
@@ -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;
index 7d30eea03826048403cc8826ba1375cf06807846..0843634a043f3c82745306f1ae17c410422b1392 100644 (file)
                <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>
                                        <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"/>
                <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>
                                        <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"/>
index 1bc67d83abe3b2b81a21149d097c4e276480cc5f..61d438058903b2db04f40a00d9ccbc99bd80e270 100644 (file)
@@ -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 ()")]
index 9db320a72f4b4713e7fe6fbcca45324c50dfe932..a005efdb06da6c0371dfff30a8ecbf226397f38e 100644 (file)
@@ -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;
                                        }
                                }