]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
codegen: Support gobject property of null-terminated array without length
authorRico Tzschichholz <ricotz@ubuntu.com>
Wed, 2 Oct 2019 07:29:06 +0000 (09:29 +0200)
committerRico Tzschichholz <ricotz@ubuntu.com>
Wed, 2 Oct 2019 10:19:30 +0000 (12:19 +0200)
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
codegen/valagobjectmodule.vala
codegen/valagtypemodule.vala
tests/Makefile.am
tests/objects/property-array.vala [new file with mode: 0644]
vala/valapropertyaccessor.vala
vala/valasemanticanalyzer.vala

index 012c78081b6466d1bf1b568b5de07f32834ce851..548ec58a6dae2ee7fb470aa38d26871946968dc8 100644 (file)
@@ -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;
index a5424288245ab40d61ac3b73b832a4809eb57ea3..65726fe68098740ee95aac6dc63ddc9d880998d7 100644 (file)
@@ -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 {
index 56bf3188d2a6fd65789d6cbb5424079fa64f065a..7f05bfd7c56132b0561b8526ba7375b8eaf6d07b 100644 (file)
@@ -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));
index 3efdffbba81a779b09d50f50d21cf259dca069f4..bc3f0773e7447b22051e0b6e0e2a43956c2ce12a 100644 (file)
@@ -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 (file)
index 0000000..0c7eaae
--- /dev/null
@@ -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");
+       }
+}
index d98aebc3a60e59174512d80999c45e1584f3aeb2..553777afb421fa420e4487127a2ef7eeded59b84 100644 (file)
@@ -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
index 30c4dadf3d9ce6979ad3c2fdf0f26dbfa1a72c83..f9eae2b07aa3304010a647eb46686d9d565d5094 100644 (file)
@@ -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 &&