[vala/staging] codegen: Support GObject properties with nullable GType-based struct type
- From: Rico Tzschichholz <ricotz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/staging] codegen: Support GObject properties with nullable GType-based struct type
- Date: Mon, 6 May 2019 13:21:01 +0000 (UTC)
commit 3af1cfb3bf6b1d3d4a8116382e6eda702f7335bf
Author: Rico Tzschichholz <ricotz ubuntu com>
Date: Mon May 6 14:48:25 2019 +0200
codegen: Support GObject properties with nullable GType-based struct type
Fixes https://gitlab.gnome.org/GNOME/vala/issues/792
codegen/valaccodebasemodule.vala | 18 ++++++-----
codegen/valagobjectmodule.vala | 19 +++++++-----
tests/Makefile.am | 1 +
tests/objects/property-gboxed-nullable.vala | 48 +++++++++++++++++++++++++++++
vala/valasemanticanalyzer.vala | 8 +++--
5 files changed, 78 insertions(+), 16 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index 9d6320ccf..17091394f 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -1883,16 +1883,20 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
ccode.open_if (new CCodeBinaryExpression
(CCodeBinaryOperator.INEQUALITY, ccall, new CCodeConstant ("0")));
} else if (property_type is StructValueType) {
ccode.add_declaration (get_ccode_name (property_type), new
CCodeVariableDeclarator ("old_value"));
- get_call.add_argument (new CCodeUnaryExpression
(CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("old_value")));
-
- var get_expr = new CCodeCommaExpression ();
- get_expr.append_expression (get_call);
- get_expr.append_expression (new CCodeUnaryExpression
(CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("old_value")));
-
+ if (property_type.nullable) {
+ ccode.add_assignment (new CCodeIdentifier
("old_value"), get_call);
+ } else {
+ get_call.add_argument (new CCodeUnaryExpression
(CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("old_value")));
+ ccode.add_expression (get_call);
+ }
var equalfunc = generate_struct_equal_function ((Struct)
property_type.data_type);
var ccall = new CCodeFunctionCall (new CCodeIdentifier
(equalfunc));
ccall.add_argument (new CCodeIdentifier ("value"));
- ccall.add_argument (get_expr);
+ if (property_type.nullable) {
+ ccall.add_argument (new CCodeIdentifier
("old_value"));
+ } else {
+ ccall.add_argument (new CCodeUnaryExpression
(CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("old_value")));
+ }
ccode.open_if (new CCodeBinaryExpression
(CCodeBinaryOperator.INEQUALITY, ccall, new CCodeConstant ("TRUE")));
} else {
ccode.open_if (new CCodeBinaryExpression
(CCodeBinaryOperator.INEQUALITY, get_call, new CCodeIdentifier ("value")));
diff --git a/codegen/valagobjectmodule.vala b/codegen/valagobjectmodule.vala
index 8ad676ab9..8c31c924f 100644
--- a/codegen/valagobjectmodule.vala
+++ b/codegen/valagobjectmodule.vala
@@ -233,21 +233,26 @@ public class Vala.GObjectModule : GTypeModule {
ccode.add_case (new CCodeIdentifier ("%s_PROPERTY".printf (get_ccode_upper_case_name
(prop))));
if (prop.property_type.is_real_struct_type ()) {
- var st = prop.property_type.data_type as Struct;
-
ccode.open_block ();
- ccode.add_declaration (get_ccode_name (st), new CCodeVariableDeclarator
("boxed"));
+ ccode.add_declaration (get_ccode_name (prop.property_type), new
CCodeVariableDeclarator ("boxed"));
ccall = new CCodeFunctionCall (cfunc);
ccall.add_argument (cself);
- var boxed_addr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new
CCodeIdentifier ("boxed"));
- ccall.add_argument (boxed_addr);
- ccode.add_expression (ccall);
+ if (prop.property_type.nullable) {
+ ccode.add_assignment (new CCodeIdentifier ("boxed"), ccall);
+ } else {
+ ccall.add_argument (new CCodeUnaryExpression
(CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("boxed")));
+ ccode.add_expression (ccall);
+ }
var csetcall = new CCodeFunctionCall ();
csetcall.call = get_value_setter_function (prop.property_type);
csetcall.add_argument (new CCodeIdentifier ("value"));
- csetcall.add_argument (boxed_addr);
+ if (prop.property_type.nullable) {
+ csetcall.add_argument (new CCodeIdentifier ("boxed"));
+ } else {
+ csetcall.add_argument (new CCodeUnaryExpression
(CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("boxed")));
+ }
add_guarded_expression (prop, csetcall);
if (requires_destroy (prop.get_accessor.value_type)) {
diff --git a/tests/Makefile.am b/tests/Makefile.am
index cfdfafa1e..4527506aa 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -316,6 +316,7 @@ TESTS = \
objects/property-read-only-write.test \
objects/property-construct-only-write.test \
objects/property-construct-only-write-foreign.test \
+ objects/property-gboxed-nullable.vala \
objects/property-static.vala \
objects/regex.vala \
objects/signals.vala \
diff --git a/tests/objects/property-gboxed-nullable.vala b/tests/objects/property-gboxed-nullable.vala
new file mode 100644
index 000000000..bbf023f76
--- /dev/null
+++ b/tests/objects/property-gboxed-nullable.vala
@@ -0,0 +1,48 @@
+public struct Bar {
+ public string s;
+}
+
+public class Foo : Object {
+ public Bar? bar { get; construct set; }
+
+ public Foo (Bar? bar) {
+ Object (bar: bar);
+ }
+}
+
+public class Faz : Object {
+ [NoAccessorMethod]
+ public Bar? baz { owned get; set; }
+}
+
+void main () {
+ {
+ var foo = new Foo (null);
+ assert (foo.bar == null);
+ }
+ {
+ Bar bar = { "foo" };
+ var foo = (Foo) Object.@new (typeof (Foo), "bar", bar);
+ assert (foo.bar == bar);
+ assert (foo.bar.s == "foo");
+ foo.bar = null;
+ assert (foo.bar == null);
+ }
+ {
+ Bar bar = { "foo" };
+ var foo = (Foo) Object.@new (typeof (Foo), "bar", null);
+ assert (foo.bar == null);
+ foo.bar = bar;
+ assert (foo.bar == bar);
+ }
+ {
+ Bar bar = { "foo" };
+ var faz = new Faz ();
+ assert (faz.baz == null);
+ faz.baz = bar;
+ assert (faz.baz == bar);
+ assert (faz.baz.s == "foo");
+ faz.baz = null;
+ assert (faz.baz == null);
+ }
+}
diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala
index af7e63eb6..fa90deb7a 100644
--- a/vala/valasemanticanalyzer.vala
+++ b/vala/valasemanticanalyzer.vala
@@ -450,8 +450,12 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
public bool is_gobject_property_type (DataType property_type) {
var st = property_type.data_type as Struct;
- if (st != null && (!st.get_attribute_bool ("CCode", "has_type_id", true) ||
property_type.nullable)) {
- return false;
+ if (st != null) {
+ if (st.get_attribute_bool ("CCode", "has_type_id", true)) {
+ // Allow GType-based struct types
+ } else if (property_type.nullable) {
+ return false;
+ }
}
if (property_type is ArrayType && ((ArrayType) property_type).element_type.data_type !=
string_type.data_type) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]