[vala/staging] codegen: Support gobject property of null-terminated array without length



commit f3248c8531e1500db79f73fb01c426f7c3dfeeff
Author: Rico Tzschichholz <ricotz ubuntu com>
Date:   Wed Oct 2 09:29:06 2019 +0200

    codegen: Support gobject property of null-terminated array without length
    
    Properly evaluate given array_length and array_null_terminated attributes
    on properties to create the expected API.
    
    Fixes https://gitlab.gnome.org/GNOME/vala/issues/855

 codegen/valaccodebasemodule.vala  | 14 +++----
 codegen/valagobjectmodule.vala    | 16 ++++----
 codegen/valagtypemodule.vala      |  8 ++--
 tests/Makefile.am                 |  1 +
 tests/objects/property-array.vala | 84 +++++++++++++++++++++++++++++++++++++++
 vala/valapropertyaccessor.vala    |  3 ++
 vala/valasemanticanalyzer.vala    |  7 +++-
 7 files changed, 114 insertions(+), 19 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index 012c78081..548ec58a6 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -1586,7 +1586,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                        function.add_parameter (cvalueparam);
                }
 
-               if (acc.value_type is ArrayType) {
+               if (acc.value_type is ArrayType && get_ccode_array_length (prop)) {
                        var array_type = (ArrayType) acc.value_type;
                        var length_ctype = get_ccode_array_length_type (array_type);
                        for (int dim = 1; dim <= array_type.rank; dim++) {
@@ -1680,7 +1680,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                                function.add_parameter (cvalueparam);
                        }
 
-                       if (acc.value_type is ArrayType) {
+                       if (acc.value_type is ArrayType && get_ccode_array_length (prop)) {
                                var array_type = (ArrayType) acc.value_type;
                                var length_ctype = get_ccode_array_length_type (array_type);
                                for (int dim = 1; dim <= array_type.rank; dim++) {
@@ -1734,7 +1734,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                                        vcall.add_argument (new CCodeIdentifier ("result"));
                                        ccode.add_expression (vcall);
                                } else {
-                                       if (acc.value_type is ArrayType) {
+                                       if (acc.value_type is ArrayType && get_ccode_array_length (prop)) {
                                                var array_type = (ArrayType) acc.value_type;
 
                                                for (int dim = 1; dim <= array_type.rank; dim++) {
@@ -1752,7 +1752,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                                vcall.add_argument (new CCodeIdentifier ("self"));
                                vcall.add_argument (new CCodeIdentifier ("value"));
 
-                               if (acc.value_type is ArrayType) {
+                               if (acc.value_type is ArrayType && get_ccode_array_length (prop)) {
                                        var array_type = (ArrayType) acc.value_type;
 
                                        for (int dim = 1; dim <= array_type.rank; dim++) {
@@ -1804,7 +1804,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                                function.add_parameter (cvalueparam);
                        }
 
-                       if (acc.value_type is ArrayType) {
+                       if (acc.value_type is ArrayType && get_ccode_array_length (prop)) {
                                var array_type = (ArrayType) acc.value_type;
                                var length_ctype = get_ccode_array_length_type (array_type);
                                for (int dim = 1; dim <= array_type.rank; dim++) {
@@ -1862,7 +1862,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                                        var get_call = new CCodeFunctionCall (new CCodeIdentifier 
(get_ccode_real_name (get_accessor)));
                                        get_call.add_argument (new CCodeIdentifier (is_virtual ? "base" : 
"self"));
 
-                                       if (property_type is ArrayType) {
+                                       if (property_type is ArrayType && get_ccode_array_length (prop)) {
                                                ccode.add_declaration (get_ccode_array_length_type 
(property_type), new CCodeVariableDeclarator ("old_value_length"));
                                                get_call.add_argument (new CCodeUnaryExpression 
(CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("old_value_length")));
                                                ccode.open_if (new CCodeBinaryExpression 
(CCodeBinaryOperator.INEQUALITY, get_call, new CCodeIdentifier ("value")));
@@ -3852,7 +3852,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                }
 
                // return array length if appropriate
-               if (((current_method != null && get_ccode_array_length (current_method)) || 
current_property_accessor != null) && current_return_type is ArrayType) {
+               if (((current_method != null && get_ccode_array_length (current_method)) || 
(current_property_accessor != null && get_ccode_array_length (current_property_accessor.prop))) && 
current_return_type is ArrayType) {
                        var temp_value = store_temp_value (stmt.return_expression.target_value, stmt);
 
                        var array_type = (ArrayType) current_return_type;
diff --git a/codegen/valagobjectmodule.vala b/codegen/valagobjectmodule.vala
index a54242882..65726fe68 100644
--- a/codegen/valagobjectmodule.vala
+++ b/codegen/valagobjectmodule.vala
@@ -263,7 +263,7 @@ public class Vala.GObjectModule : GTypeModule {
                                ccall = new CCodeFunctionCall (cfunc);
                                ccall.add_argument (cself);
                                var array_type = prop.property_type as ArrayType;
-                               if (array_type != null && array_type.element_type.type_symbol == 
string_type.type_symbol) {
+                               if (array_type != null && get_ccode_array_length (prop) && 
array_type.element_type.type_symbol == string_type.type_symbol) {
                                        // G_TYPE_STRV
                                        ccode.open_block ();
                                        ccode.add_declaration ("int", new CCodeVariableDeclarator ("length"));
@@ -278,7 +278,7 @@ public class Vala.GObjectModule : GTypeModule {
                                csetcall.add_argument (new CCodeIdentifier ("value"));
                                csetcall.add_argument (ccall);
                                add_guarded_expression (prop, csetcall);
-                               if (array_type != null && array_type.element_type.type_symbol == 
string_type.type_symbol) {
+                               if (array_type != null && get_ccode_array_length (prop) && 
array_type.element_type.type_symbol == string_type.type_symbol) {
                                        ccode.close ();
                                }
                        }
@@ -355,12 +355,14 @@ public class Vala.GObjectModule : GTypeModule {
                                ccode.add_assignment (new CCodeIdentifier ("boxed"), cgetcall);
                                ccall.add_argument (new CCodeIdentifier ("boxed"));
 
-                               var cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new 
CCodeIdentifier ("boxed"), new CCodeConstant ("NULL"));
-                               var cstrvlen = new CCodeFunctionCall (new CCodeIdentifier ("g_strv_length"));
-                               cstrvlen.add_argument (new CCodeIdentifier ("boxed"));
-                               var ccond = new CCodeConditionalExpression (cisnull, new CCodeConstant ("0"), 
cstrvlen);
+                               if (get_ccode_array_length (prop)) {
+                                       var cisnull = new CCodeBinaryExpression 
(CCodeBinaryOperator.EQUALITY, new CCodeIdentifier ("boxed"), new CCodeConstant ("NULL"));
+                                       var cstrvlen = new CCodeFunctionCall (new CCodeIdentifier 
("g_strv_length"));
+                                       cstrvlen.add_argument (new CCodeIdentifier ("boxed"));
+                                       var ccond = new CCodeConditionalExpression (cisnull, new 
CCodeConstant ("0"), cstrvlen);
 
-                               ccall.add_argument (ccond);
+                                       ccall.add_argument (ccond);
+                               }
                                add_guarded_expression (prop, ccall);
                                ccode.close ();
                        } else {
diff --git a/codegen/valagtypemodule.vala b/codegen/valagtypemodule.vala
index 56bf3188d..7f05bfd7c 100644
--- a/codegen/valagtypemodule.vala
+++ b/codegen/valagtypemodule.vala
@@ -348,7 +348,7 @@ public class Vala.GTypeModule : GErrorModule {
                        }
 
                        var array_type = prop.property_type as ArrayType;
-                       if (array_type != null) {
+                       if (array_type != null && get_ccode_array_length (prop)) {
                                var length_ctype = get_ccode_array_length_type (array_type) + "*";
                                for (int dim = 1; dim <= array_type.rank; dim++) {
                                        vdeclarator.add_parameter (new CCodeParameter (get_array_length_cname 
("result", dim), length_ctype));
@@ -379,7 +379,7 @@ public class Vala.GTypeModule : GErrorModule {
                        vdeclarator.add_parameter (cvalueparam);
 
                        var array_type = prop.property_type as ArrayType;
-                       if (array_type != null) {
+                       if (array_type != null && get_ccode_array_length (prop)) {
                                var length_ctype = get_ccode_array_length_type (array_type);
                                for (int dim = 1; dim <= array_type.rank; dim++) {
                                        vdeclarator.add_parameter (new CCodeParameter (get_array_length_cname 
("value", dim), length_ctype));
@@ -2156,7 +2156,7 @@ public class Vala.GTypeModule : GErrorModule {
                                        }
 
                                        var array_type = prop.property_type as ArrayType;
-                                       if (array_type != null) {
+                                       if (array_type != null && get_ccode_array_length (prop)) {
                                                var length_ctype = get_ccode_array_length_type (array_type) + 
"*";
                                                for (int dim = 1; dim <= array_type.rank; dim++) {
                                                        vdeclarator.add_parameter (new CCodeParameter 
(get_array_length_cname ("result", dim), length_ctype));
@@ -2179,7 +2179,7 @@ public class Vala.GTypeModule : GErrorModule {
                                        }
 
                                        var array_type = prop.property_type as ArrayType;
-                                       if (array_type != null) {
+                                       if (array_type != null && get_ccode_array_length (prop)) {
                                                var length_ctype = get_ccode_array_length_type (array_type);
                                                for (int dim = 1; dim <= array_type.rank; dim++) {
                                                        vdeclarator.add_parameter (new CCodeParameter 
(get_array_length_cname ("value", dim), length_ctype));
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 3efdffbba..bc3f0773e 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -321,6 +321,7 @@ TESTS = \
        objects/paramspec.vala \
        objects/plugin-module-init.vala \
        objects/properties.vala \
+       objects/property-array.vala \
        objects/property-notify.vala \
        objects/property-ownership.vala \
        objects/property-read-only-auto.vala \
diff --git a/tests/objects/property-array.vala b/tests/objects/property-array.vala
new file mode 100644
index 000000000..0c7eaae0c
--- /dev/null
+++ b/tests/objects/property-array.vala
@@ -0,0 +1,84 @@
+public struct Manam {
+       public int i;
+}
+
+public class Foo {
+       public Manam?[] array { get; set; }
+
+       public virtual Manam?[] array_v { get; set; }
+
+       [CCode (array_length = false, array_null_terminated = true)]
+       public Manam?[] array_no_length { get; set; }
+
+       [CCode (array_length = false, array_null_terminated = true)]
+       public virtual Manam?[] array_no_length_v { get; set; }
+
+       [CCode (array_length = false, array_null_terminated = true)]
+       public string[] strv { set; get; }
+
+       [CCode (array_length = false, array_null_terminated = true)]
+       public virtual string[] strv_v { set; get; }
+}
+
+public class Bar : Object {
+       [CCode (array_length = false, array_null_terminated = true)]
+       public Manam?[] array { get; set; }
+
+       [CCode (array_length = false, array_null_terminated = true)]
+       public virtual Manam?[] array_v { get; set; }
+
+       [CCode (array_length = false, array_null_terminated = true)]
+       public string[] strv { set; get; }
+
+       [CCode (array_length = false, array_null_terminated = true)]
+       public virtual string[] strv_v { set; get; }
+}
+
+void main () {
+       Manam?[] manam = { Manam () { i = 23 }, Manam () { i = 42 }, null };
+       string[] minim = { "foo", "bar", null };
+
+       {
+               var foo = new Foo ();
+
+               foo.array = manam;
+               assert (foo.array[0].i == 23);
+               foo.array_v = manam;
+               assert (foo.array_v[1].i == 42);
+
+               foo.array_no_length = manam;
+               assert (foo.array_no_length[0].i == 23);
+               foo.array_no_length_v = manam;
+               assert (foo.array_no_length_v[1].i == 42);
+
+               foo.strv = minim;
+               assert (foo.strv[0] == "foo");
+               foo.strv_v = minim;
+               assert (foo.strv_v[1] == "bar");
+       }
+       {
+               var bar = new Bar ();
+
+               bar.array = manam;
+               assert (bar.array[0].i == 23);
+               bar.array_v = manam;
+               assert (bar.array_v[1].i == 42);
+
+               bar.strv = minim;
+               assert (bar.strv[0] == "foo");
+               bar.strv_v = minim;
+               assert (bar.strv_v[1] == "bar");
+
+               unowned Manam?[] res;
+               bar.get ("array", out res);
+               assert (res[0].i == 23);
+               bar.get ("array-v", out res);
+               assert (res[1].i == 42);
+
+               unowned string[] strv;
+               bar.get ("strv", out strv);
+               assert (strv[0] == "foo");
+               bar.get ("strv-v", out strv);
+               assert (strv[1] == "bar");
+       }
+}
diff --git a/vala/valapropertyaccessor.vala b/vala/valapropertyaccessor.vala
index d98aebc3a..553777afb 100644
--- a/vala/valapropertyaccessor.vala
+++ b/vala/valapropertyaccessor.vala
@@ -156,6 +156,9 @@ public class Vala.PropertyAccessor : Subroutine {
 
                if (writable || construction) {
                        value_parameter = new Parameter ("value", value_type, source_reference);
+                       // Inherit important atttributes
+                       value_parameter.copy_attribute_bool (prop, "CCode", "array_length");
+                       value_parameter.copy_attribute_bool (prop, "CCode", "array_null_terminated");
                }
 
                if (context.profile == Profile.GOBJECT
diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala
index 30c4dadf3..f9eae2b07 100644
--- a/vala/valasemanticanalyzer.vala
+++ b/vala/valasemanticanalyzer.vala
@@ -432,7 +432,12 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                }
 
                if (!is_gobject_property_type (prop.property_type)) {
-                       return false;
+                       if (prop.property_type is ArrayType && (!prop.get_attribute_bool ("CCode", 
"array_length", true)
+                           && prop.get_attribute_bool ("CCode", "array_null_terminated", false))) {
+                               // null-terminated arrays without length are allowed
+                       } else {
+                               return false;
+                       }
                }
 
                if (type_sym is Class && prop.base_interface_property != null &&


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]