summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPrinceton Ferro <princetonferro@gmail.com>2021-07-15 02:32:00 -0400
committerRico Tzschichholz <ricotz@ubuntu.com>2021-08-18 13:47:50 +0200
commitcf3a4087bcc5dd443f1eb99b893fe8cb2c536ab8 (patch)
tree173b0285b376ea8a34f75d87dce453273faa8df1
parent9471ab001c713598702c0a35ac9c93d01b6233ef (diff)
downloadvala-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.vala11
-rw-r--r--tests/girwriter/GirTest-1.0.gir-expected32
-rw-r--r--tests/girwriter/girtest.vapigen-expected10
-rw-r--r--vala/valagirparser.vala25
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;
}
}