[vala] codegen: Support non-auto property initializer in gobjects



commit 73e553ac3488d641fb08b275bcf2636e3cf0de67
Author: Luca Bruno <lucabru src gnome org>
Date:   Tue Jun 11 23:02:44 2013 +0200

    codegen: Support non-auto property initializer in gobjects
    
    Fixes bug 701978

 codegen/valaccodeattribute.vala |   85 +++++++++++++++++++++++++++++++--------
 codegen/valagobjectmodule.vala  |   21 ++++++++++
 codegen/valagtypemodule.vala    |   27 ++++++------
 tests/Makefile.am               |    1 +
 tests/objects/bug701978.vala    |   22 ++++++++++
 vala/valaproperty.vala          |   18 ++++++++-
 6 files changed, 143 insertions(+), 31 deletions(-)
---
diff --git a/codegen/valaccodeattribute.vala b/codegen/valaccodeattribute.vala
index d11021b..82a74f7 100644
--- a/codegen/valaccodeattribute.vala
+++ b/codegen/valaccodeattribute.vala
@@ -1113,27 +1113,78 @@ public class Vala.CCodeAttribute : AttributeCache {
        }
 
        private string get_default_param_spec_function () {
-               if (sym is Class) {
-                       var cl = (Class) sym;
-                       if (cl.is_fundamental ()) {
-                               return CCodeBaseModule.get_ccode_lower_case_name (cl, "param_spec_");
-                       } else if (cl.base_class != null) {
-                               return CCodeBaseModule.get_ccode_param_spec_function (cl.base_class);
-                       } else if (type_id == "G_TYPE_POINTER") {
+               if (node is Symbol) {
+                       if (sym is Class) {
+                               var cl = (Class) sym;
+                               if (cl.is_fundamental ()) {
+                                       return CCodeBaseModule.get_ccode_lower_case_name (cl, "param_spec_");
+                               } else if (cl.base_class != null) {
+                                       return CCodeBaseModule.get_ccode_param_spec_function (cl.base_class);
+                               } else if (type_id == "G_TYPE_POINTER") {
+                                       return "g_param_spec_pointer";
+                               } else {
+                                       return "g_param_spec_boxed";
+                               }
+                       } else if (sym is Interface) {
+                               foreach (var prereq in ((Interface) sym).get_prerequisites ()) {
+                                       var func = CCodeBaseModule.get_ccode_param_spec_function 
(prereq.data_type);
+                                       if (func != "") {
+                                               return func;
+                                       }
+                               }
                                return "g_param_spec_pointer";
-                       } else {
-                               return "g_param_spec_boxed";
-                       }
-               } else if (sym is Interface) {
-                       foreach (var prereq in ((Interface) sym).get_prerequisites ()) {
-                               var func = CCodeBaseModule.get_ccode_param_spec_function (prereq.data_type);
-                               if (func != "") {
-                                       return func;
+                       } else if (sym is Enum) {
+                               var e = sym as Enum;
+                               if (CCodeBaseModule.get_ccode_has_type_id (e)) {
+                                       if (e.is_flags) {
+                                               return "g_param_spec_flags";
+                                       } else {
+                                               return "g_param_spec_enum";
+                                       }
+                               } else {
+                                       if (e.is_flags) {
+                                               return "g_param_spec_uint";
+                                       } else {
+                                               return "g_param_spec_int";
+                                       }
+                               }
+                       } else if (sym is Struct) {
+                               var type_id = CCodeBaseModule.get_ccode_type_id (sym);
+                               if (type_id == "G_TYPE_INT") {
+                                       return "g_param_spec_int";
+                               } else if (type_id == "G_TYPE_UINT") {
+                                       return "g_param_spec_uint";
+                               } else if (type_id == "G_TYPE_INT64") {
+                                       return "g_param_spec_int64";
+                               } else if (type_id == "G_TYPE_UINT64") {
+                                       return "g_param_spec_uint64";
+                               } else if (type_id == "G_TYPE_LONG") {
+                                       return "g_param_spec_long";
+                               } else if (type_id == "G_TYPE_ULONG") {
+                                       return "g_param_spec_ulong";
+                               } else if (type_id == "G_TYPE_BOOLEAN") {
+                                       return "g_param_spec_boolean";
+                               } else if (type_id == "G_TYPE_CHAR") {
+                                       return "g_param_spec_char";
+                               } else if (type_id == "G_TYPE_UCHAR") {
+                                       return "g_param_spec_uchar";
+                               }else if (type_id == "G_TYPE_FLOAT") {
+                                       return "g_param_spec_float";
+                               } else if (type_id == "G_TYPE_DOUBLE") {
+                                       return "g_param_spec_double";
+                               } else if (type_id == "G_TYPE_GTYPE") {
+                                       return "g_param_spec_gtype";
+                               } else {
+                                       return "g_param_spec_boxed";
                                }
                        }
-                       return "g_param_spec_pointer";
+               } else if (node is ArrayType && ((ArrayType)node).element_type.data_type == 
CodeContext.get().analyzer.string_type.data_type) {
+                       return "g_param_spec_boxed";
+               } else if (node is DataType && ((DataType) node).data_type != null) {
+                       return CCodeBaseModule.get_ccode_param_spec_function (((DataType) node).data_type);
                }
-               return "";
+
+               return "g_param_spec_pointer";
        }
 
        private string get_default_default_value () {
diff --git a/codegen/valagobjectmodule.vala b/codegen/valagobjectmodule.vala
index d2e81e3..cddbc5e 100644
--- a/codegen/valagobjectmodule.vala
+++ b/codegen/valagobjectmodule.vala
@@ -668,6 +668,27 @@ public class Vala.GObjectModule : GTypeModule {
 
                if (is_gobject_property (prop) && prop.parent_symbol is Class) {
                        prop_enum.add_value (new CCodeEnumValue (get_ccode_upper_case_name (prop)));
+
+                       if (prop.initializer != null && prop.set_accessor != null && 
!prop.set_accessor.automatic_body) {
+                               // generate a custom initializer if it couldn't be done at class_init time
+                               bool has_spec_initializer = prop.property_type.data_type is Enum;
+                               if (!has_spec_initializer && prop.property_type.data_type is Struct) {
+                                       var param_spec_func = get_ccode_param_spec_function 
(prop.property_type.data_type);
+                                       has_spec_initializer = param_spec_func != "g_param_spec_boxed";
+                               }
+                               if (!has_spec_initializer) {
+                                       push_context (instance_init_context);
+
+                                       prop.initializer.emit (this);
+
+                                       var inst_ma = new MemberAccess.simple ("this");
+                                       inst_ma.target_value = new GLibValue (get_data_type_for_symbol 
((Class) prop.parent_symbol), new CCodeIdentifier ("self"), true);
+                                       store_property (prop, inst_ma, prop.initializer.target_value);
+
+                                       temp_ref_values.clear ();                       
+                                       pop_context ();
+                               }
+                       }
                }
        }
 
diff --git a/codegen/valagtypemodule.vala b/codegen/valagtypemodule.vala
index 604456a..552d4e6 100644
--- a/codegen/valagtypemodule.vala
+++ b/codegen/valagtypemodule.vala
@@ -1785,7 +1785,8 @@ public class Vala.GTypeModule : GErrorModule {
                        }
                } else if (prop.property_type.data_type is Struct) {
                        var st = (Struct) prop.property_type.data_type;
-                       if (get_ccode_type_id (st) == "G_TYPE_INT") {
+                       var type_id = get_ccode_type_id (st);
+                       if (type_id == "G_TYPE_INT") {
                                cspec.call = new CCodeIdentifier ("g_param_spec_int");
                                cspec.add_argument (new CCodeConstant ("G_MININT"));
                                cspec.add_argument (new CCodeConstant ("G_MAXINT"));
@@ -1794,7 +1795,7 @@ public class Vala.GTypeModule : GErrorModule {
                                } else {
                                        cspec.add_argument (new CCodeConstant ("0"));
                                }
-                       } else if (get_ccode_type_id (st) == "G_TYPE_UINT") {
+                       } else if (type_id == "G_TYPE_UINT") {
                                cspec.call = new CCodeIdentifier ("g_param_spec_uint");
                                cspec.add_argument (new CCodeConstant ("0"));
                                cspec.add_argument (new CCodeConstant ("G_MAXUINT"));
@@ -1803,7 +1804,7 @@ public class Vala.GTypeModule : GErrorModule {
                                } else {
                                        cspec.add_argument (new CCodeConstant ("0U"));
                                }
-                       } else if (get_ccode_type_id (st) == "G_TYPE_INT64") {
+                       } else if (type_id == "G_TYPE_INT64") {
                                cspec.call = new CCodeIdentifier ("g_param_spec_int64");
                                cspec.add_argument (new CCodeConstant ("G_MININT64"));
                                cspec.add_argument (new CCodeConstant ("G_MAXINT64"));
@@ -1812,7 +1813,7 @@ public class Vala.GTypeModule : GErrorModule {
                                } else {
                                        cspec.add_argument (new CCodeConstant ("0"));
                                }
-                       } else if (get_ccode_type_id (st) == "G_TYPE_UINT64") {
+                       } else if (type_id == "G_TYPE_UINT64") {
                                cspec.call = new CCodeIdentifier ("g_param_spec_uint64");
                                cspec.add_argument (new CCodeConstant ("0"));
                                cspec.add_argument (new CCodeConstant ("G_MAXUINT64"));
@@ -1821,7 +1822,7 @@ public class Vala.GTypeModule : GErrorModule {
                                } else {
                                        cspec.add_argument (new CCodeConstant ("0U"));
                                }
-                       } else if (get_ccode_type_id (st) == "G_TYPE_LONG") {
+                       } else if (type_id == "G_TYPE_LONG") {
                                cspec.call = new CCodeIdentifier ("g_param_spec_long");
                                cspec.add_argument (new CCodeConstant ("G_MINLONG"));
                                cspec.add_argument (new CCodeConstant ("G_MAXLONG"));
@@ -1830,7 +1831,7 @@ public class Vala.GTypeModule : GErrorModule {
                                } else {
                                        cspec.add_argument (new CCodeConstant ("0L"));
                                }
-                       } else if (get_ccode_type_id (st) == "G_TYPE_ULONG") {
+                       } else if (type_id == "G_TYPE_ULONG") {
                                cspec.call = new CCodeIdentifier ("g_param_spec_ulong");
                                cspec.add_argument (new CCodeConstant ("0"));
                                cspec.add_argument (new CCodeConstant ("G_MAXULONG"));
@@ -1839,14 +1840,14 @@ public class Vala.GTypeModule : GErrorModule {
                                } else {
                                        cspec.add_argument (new CCodeConstant ("0UL"));
                                }
-                       } else if (get_ccode_type_id (st) == "G_TYPE_BOOLEAN") {
+                       } else if (type_id == "G_TYPE_BOOLEAN") {
                                cspec.call = new CCodeIdentifier ("g_param_spec_boolean");
                                if (prop.initializer != null) {
                                        cspec.add_argument ((CCodeExpression) get_ccodenode 
(prop.initializer));
                                } else {
                                        cspec.add_argument (new CCodeConstant ("FALSE"));
                                }
-                       } else if (get_ccode_type_id (st) == "G_TYPE_CHAR") {
+                       } else if (type_id == "G_TYPE_CHAR") {
                                cspec.call = new CCodeIdentifier ("g_param_spec_char");
                                cspec.add_argument (new CCodeConstant ("G_MININT8"));
                                cspec.add_argument (new CCodeConstant ("G_MAXINT8"));
@@ -1855,7 +1856,7 @@ public class Vala.GTypeModule : GErrorModule {
                                } else {
                                        cspec.add_argument (new CCodeConstant ("0"));
                                }
-                       } else if (get_ccode_type_id (st) == "G_TYPE_UCHAR") {
+                       } else if (type_id == "G_TYPE_UCHAR") {
                                cspec.call = new CCodeIdentifier ("g_param_spec_uchar");
                                cspec.add_argument (new CCodeConstant ("0"));
                                cspec.add_argument (new CCodeConstant ("G_MAXUINT8"));
@@ -1864,7 +1865,7 @@ public class Vala.GTypeModule : GErrorModule {
                                } else {
                                        cspec.add_argument (new CCodeConstant ("0"));
                                }
-                       }else if (get_ccode_type_id (st) == "G_TYPE_FLOAT") {
+                       } else if (type_id == "G_TYPE_FLOAT") {
                                cspec.call = new CCodeIdentifier ("g_param_spec_float");
                                cspec.add_argument (new CCodeConstant ("-G_MAXFLOAT"));
                                cspec.add_argument (new CCodeConstant ("G_MAXFLOAT"));
@@ -1873,7 +1874,7 @@ public class Vala.GTypeModule : GErrorModule {
                                } else {
                                        cspec.add_argument (new CCodeConstant ("0.0F"));
                                }
-                       } else if (get_ccode_type_id (st) == "G_TYPE_DOUBLE") {
+                       } else if (type_id == "G_TYPE_DOUBLE") {
                                cspec.call = new CCodeIdentifier ("g_param_spec_double");
                                cspec.add_argument (new CCodeConstant ("-G_MAXDOUBLE"));
                                cspec.add_argument (new CCodeConstant ("G_MAXDOUBLE"));
@@ -1882,7 +1883,7 @@ public class Vala.GTypeModule : GErrorModule {
                                } else {
                                        cspec.add_argument (new CCodeConstant ("0.0"));
                                }
-                       } else if (get_ccode_type_id (st) == "G_TYPE_GTYPE") {
+                       } else if (type_id == "G_TYPE_GTYPE") {
                                cspec.call = new CCodeIdentifier ("g_param_spec_gtype");
                                if (prop.initializer != null) {
                                        cspec.add_argument ((CCodeExpression) get_ccodenode 
(prop.initializer));
@@ -1891,7 +1892,7 @@ public class Vala.GTypeModule : GErrorModule {
                                }
                        } else {
                                cspec.call = new CCodeIdentifier ("g_param_spec_boxed");
-                               cspec.add_argument (new CCodeIdentifier (get_ccode_type_id (st)));
+                               cspec.add_argument (new CCodeIdentifier (type_id));
                        }
                } else if (prop.property_type is ArrayType && 
((ArrayType)prop.property_type).element_type.data_type == string_type.data_type) {
                        cspec.call = new CCodeIdentifier ("g_param_spec_boxed");
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 06ca778..d9c7c96 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -135,6 +135,7 @@ TESTS = \
        objects/bug667668.vala \
        objects/bug683646.vala \
        objects/bug695671.vala \
+       objects/bug701978.vala \
        errors/errors.vala \
        errors/bug567181.vala \
        errors/bug579101.vala \
diff --git a/tests/objects/bug701978.vala b/tests/objects/bug701978.vala
new file mode 100644
index 0000000..22fcfaf
--- /dev/null
+++ b/tests/objects/bug701978.vala
@@ -0,0 +1,22 @@
+public struct Foo {
+       public int val { get; set; }
+
+       public Foo () {
+               val = 55;
+       }
+}
+
+public class Bar : Object {
+       private Foo _foo;
+
+       public Foo foo {
+               get { return _foo; }
+               set { _foo = value; }
+               default = Foo ();
+       }
+}
+
+void main () {
+       var bar = new Bar();
+       assert (bar.foo.val == 55);
+}
diff --git a/vala/valaproperty.vala b/vala/valaproperty.vala
index 82cfff1..8a8ced4 100644
--- a/vala/valaproperty.vala
+++ b/vala/valaproperty.vala
@@ -132,7 +132,17 @@ public class Vala.Property : Symbol, Lockable {
        /**
         * Specifies the default value of this property.
         */
-       public Expression initializer { get; set; }
+       public Expression initializer {
+               get {
+                       return _initializer;
+               }
+               set {
+                       _initializer = value;
+                       _initializer.parent_node = this;
+               }
+       }
+
+       private Expression _initializer;
 
        private bool lock_used = false;
 
@@ -250,6 +260,12 @@ public class Vala.Property : Symbol, Lockable {
                }
        }
 
+       public override void replace_expression (Expression old_node, Expression new_node) {
+               if (initializer == old_node) {
+                       initializer = new_node;
+               }
+       }
+
        private void find_base_properties () {
                if (base_properties_valid) {
                        return;


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