LCOV - code coverage report
Current view: top level - codegen - valagobjectmodule.vala (source / functions) Coverage Total Hit
Test: vala 0.57.0.298-a8cae1 Lines: 97.3 % 445 433
Test Date: 2024-04-25 11:34:36 Functions: - 0 0

            Line data    Source code
       1              : /* valagobjectmodule.vala
       2              :  *
       3              :  * Copyright (C) 2006-2011  Jürg Billeter
       4              :  * Copyright (C) 2006-2008  Raffaele Sandrini
       5              :  *
       6              :  * This library is free software; you can redistribute it and/or
       7              :  * modify it under the terms of the GNU Lesser General Public
       8              :  * License as published by the Free Software Foundation; either
       9              :  * version 2.1 of the License, or (at your option) any later version.
      10              : 
      11              :  * This library is distributed in the hope that it will be useful,
      12              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14              :  * Lesser General Public License for more details.
      15              : 
      16              :  * You should have received a copy of the GNU Lesser General Public
      17              :  * License along with this library; if not, write to the Free Software
      18              :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
      19              :  *
      20              :  * Author:
      21              :  *      Jürg Billeter <j@bitron.ch>
      22              :  *      Raffaele Sandrini <raffaele@sandrini.ch>
      23              :  */
      24              : 
      25              : 
      26         4371 : public class Vala.GObjectModule : GTypeModule {
      27              :         int signal_wrapper_id;
      28              : 
      29          780 :         public override void visit_class (Class cl) {
      30          780 :                 base.visit_class (cl);
      31              : 
      32          780 :                 if (!cl.is_subtype_of (gobject_type)) {
      33              :                         return;
      34              :                 }
      35              : 
      36          425 :                 push_line (cl.source_reference);
      37          425 :                 if (class_has_readable_properties (cl) || cl.has_type_parameters ()) {
      38          160 :                         add_get_property_function (cl);
      39              :                 }
      40          425 :                 if (class_has_writable_properties (cl) || cl.has_type_parameters ()) {
      41          135 :                         add_set_property_function (cl);
      42              :                 }
      43          425 :                 pop_line ();
      44              :         }
      45              : 
      46         1159 :         public override void generate_class_init (Class cl) {
      47          734 :                 if (!cl.is_subtype_of (gobject_type)) {
      48              :                         return;
      49              :                 }
      50              : 
      51              :                 /* set property handlers */
      52          425 :                 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
      53          425 :                 ccall.add_argument (new CCodeIdentifier ("klass"));
      54          425 :                 if (class_has_readable_properties (cl) || cl.has_type_parameters ()) {
      55          160 :                         ccode.add_assignment (new CCodeMemberAccess.pointer (ccall, "get_property"), new CCodeIdentifier ("_vala_%s_get_property".printf (get_ccode_lower_case_name (cl, null))));
      56              :                 }
      57          425 :                 if (class_has_writable_properties (cl) || cl.has_type_parameters ()) {
      58          135 :                         ccode.add_assignment (new CCodeMemberAccess.pointer (ccall, "set_property"), new CCodeIdentifier ("_vala_%s_set_property".printf (get_ccode_lower_case_name (cl, null))));
      59              :                 }
      60              : 
      61              :                 /* set constructor */
      62          445 :                 if (cl.constructor != null) {
      63           20 :                         var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
      64           20 :                         ccast.add_argument (new CCodeIdentifier ("klass"));
      65           20 :                         ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, "constructor"), new CCodeIdentifier ("%sconstructor".printf (get_ccode_lower_case_prefix (cl))));
      66              :                 }
      67              : 
      68              :                 /* set finalize function */
      69          630 :                 if (cl.get_fields ().size > 0 || cl.destructor != null) {
      70          205 :                         var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
      71          205 :                         ccast.add_argument (new CCodeIdentifier ("klass"));
      72          205 :                         ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, "finalize"), new CCodeIdentifier ("%sfinalize".printf (get_ccode_lower_case_prefix (cl))));
      73              :                 }
      74              : 
      75              :                 /* create type, dup_func, and destroy_func properties for generic types */
      76          465 :                 foreach (TypeParameter type_param in cl.get_type_parameters ()) {
      77              :                         string func_name, enum_value;
      78              :                         CCodeConstant func_name_constant;
      79              :                         CCodeFunctionCall cinst, cspec;
      80              : 
      81              : 
      82           20 :                         func_name = get_ccode_type_id (type_param);
      83           20 :                         func_name_constant = new CCodeConstant ("\"%s\"".printf (func_name.replace ("_", "-")));
      84           20 :                         enum_value = "%s_%s".printf (get_ccode_lower_case_name (cl, null), func_name).ascii_up ();
      85           20 :                         cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_class_install_property"));
      86           20 :                         cinst.add_argument (ccall);
      87           20 :                         cinst.add_argument (new CCodeConstant (enum_value));
      88           20 :                         cspec = new CCodeFunctionCall (new CCodeIdentifier ("g_param_spec_gtype"));
      89           20 :                         cspec.add_argument (func_name_constant);
      90           20 :                         cspec.add_argument (new CCodeConstant ("\"type\""));
      91           20 :                         cspec.add_argument (new CCodeConstant ("\"type\""));
      92           20 :                         cspec.add_argument (new CCodeIdentifier ("G_TYPE_NONE"));
      93           20 :                         cspec.add_argument (new CCodeConstant ("G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY"));
      94           20 :                         cinst.add_argument (cspec);
      95           20 :                         ccode.add_expression (cinst);
      96           20 :                         prop_enum.add_value (new CCodeEnumValue (enum_value));
      97              : 
      98              : 
      99           20 :                         func_name = get_ccode_copy_function (type_param);
     100           20 :                         func_name_constant = new CCodeConstant ("\"%s\"".printf (func_name.replace ("_", "-")));
     101           20 :                         enum_value = "%s_%s".printf (get_ccode_lower_case_name (cl, null), func_name).ascii_up ();
     102           20 :                         cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_class_install_property"));
     103           20 :                         cinst.add_argument (ccall);
     104           20 :                         cinst.add_argument (new CCodeConstant (enum_value));
     105           20 :                         cspec = new CCodeFunctionCall (new CCodeIdentifier ("g_param_spec_pointer"));
     106           20 :                         cspec.add_argument (func_name_constant);
     107           20 :                         cspec.add_argument (new CCodeConstant ("\"dup func\""));
     108           20 :                         cspec.add_argument (new CCodeConstant ("\"dup func\""));
     109           20 :                         cspec.add_argument (new CCodeConstant ("G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY"));
     110           20 :                         cinst.add_argument (cspec);
     111           20 :                         ccode.add_expression (cinst);
     112           20 :                         prop_enum.add_value (new CCodeEnumValue (enum_value));
     113              : 
     114              : 
     115           20 :                         func_name = get_ccode_destroy_function (type_param);
     116           20 :                         func_name_constant = new CCodeConstant ("\"%s\"".printf (func_name.replace ("_", "-")));
     117           20 :                         enum_value = "%s_%s".printf (get_ccode_lower_case_name (cl, null), func_name).ascii_up ();
     118           20 :                         cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_class_install_property"));
     119           20 :                         cinst.add_argument (ccall);
     120           20 :                         cinst.add_argument (new CCodeConstant (enum_value));
     121           20 :                         cspec = new CCodeFunctionCall (new CCodeIdentifier ("g_param_spec_pointer"));
     122           20 :                         cspec.add_argument (func_name_constant);
     123           20 :                         cspec.add_argument (new CCodeConstant ("\"destroy func\""));
     124           20 :                         cspec.add_argument (new CCodeConstant ("\"destroy func\""));
     125           20 :                         cspec.add_argument (new CCodeConstant ("G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY"));
     126           20 :                         cinst.add_argument (cspec);
     127           20 :                         ccode.add_expression (cinst);
     128           20 :                         prop_enum.add_value (new CCodeEnumValue (enum_value));
     129              :                 }
     130              : 
     131              :                 /* create properties */
     132          720 :                 var props = cl.get_properties ();
     133         1151 :                 foreach (Property prop in props) {
     134          368 :                         if (!context.analyzer.is_gobject_property (prop)) {
     135           10 :                                 if (!context.analyzer.is_gobject_property_type (prop.property_type)) {
     136            6 :                                         Report.warning (prop.source_reference, "Type `%s' can not be used for a GLib.Object property", prop.property_type.to_qualified_string ());
     137              :                                 }
     138           10 :                                 continue;
     139              :                         }
     140              : 
     141          358 :                         if (prop.comment != null) {
     142           91 :                                 ccode.add_statement (new CCodeComment (prop.comment.content));
     143              :                         }
     144              : 
     145          358 :                         var cinst = new CCodeFunctionCall ();
     146          358 :                         cinst.add_argument (ccall);
     147          358 :                         cinst.add_argument (new CCodeConstant ("%s_PROPERTY".printf (get_ccode_upper_case_name (prop))));
     148              : 
     149              :                         //TODO g_object_class_override_property should be used more regulary
     150          358 :                         unowned Property? base_prop = prop.base_interface_property;
     151          360 :                         if (base_prop != null && base_prop.property_type is GenericType) {
     152            2 :                                 cinst.call = new CCodeIdentifier ("g_object_class_override_property");
     153            2 :                                 cinst.add_argument (get_property_canonical_cconstant (prop));
     154              : 
     155            2 :                                 ccode.add_expression (cinst);
     156              : 
     157            2 :                                 var cfind = new CCodeFunctionCall (new CCodeIdentifier ("g_object_class_find_property"));
     158            2 :                                 cfind.add_argument (ccall);
     159            2 :                                 cfind.add_argument (get_property_canonical_cconstant (prop));
     160            2 :                                 ccode.add_expression (new CCodeAssignment (get_param_spec_cexpression (prop), cfind));
     161              :                         } else {
     162          356 :                                 cinst.call = new CCodeIdentifier ("g_object_class_install_property");
     163          356 :                                 cinst.add_argument (get_param_spec (prop));
     164              : 
     165          356 :                                 ccode.add_expression (cinst);
     166              :                         }
     167              :                 }
     168              :         }
     169              : 
     170          850 :         private bool class_has_readable_properties (Class cl) {
     171          850 :                 foreach (Property prop in cl.get_properties ()) {
     172          292 :                         if (prop.get_accessor != null) {
     173          292 :                                 return true;
     174              :                         }
     175              :                 }
     176          850 :                 return false;
     177              :         }
     178              : 
     179          850 :         private bool class_has_writable_properties (Class cl) {
     180         1002 :                 foreach (Property prop in cl.get_properties ()) {
     181          314 :                         if (prop.set_accessor != null) {
     182          238 :                                 return true;
     183              :                         }
     184              :                 }
     185          850 :                 return false;
     186              :         }
     187              : 
     188          623 :         private void add_guarded_expression (Symbol sym, CCodeExpression expression) {
     189              :                 // prevent deprecation warnings
     190          625 :                 if (sym.version.deprecated) {
     191            2 :                         var guard = new CCodeGGnucSection (GGnucSectionType.IGNORE_DEPRECATIONS);
     192            2 :                         ccode.add_statement (guard);
     193            2 :                         guard.append (new CCodeExpressionStatement (expression));
     194              :                 } else {
     195          621 :                         ccode.add_expression (expression);
     196              :                 }
     197              :         }
     198              : 
     199          320 :         private void add_get_property_function (Class cl) {
     200          160 :                 var get_prop = new CCodeFunction ("_vala_%s_get_property".printf (get_ccode_lower_case_name (cl, null)), "void");
     201          160 :                 get_prop.modifiers = CCodeModifiers.STATIC;
     202          160 :                 get_prop.add_parameter (new CCodeParameter ("object", "GObject *"));
     203          160 :                 get_prop.add_parameter (new CCodeParameter ("property_id", "guint"));
     204          160 :                 get_prop.add_parameter (new CCodeParameter ("value", "GValue *"));
     205          160 :                 get_prop.add_parameter (new CCodeParameter ("pspec", "GParamSpec *"));
     206              : 
     207          160 :                 push_function (get_prop);
     208              : 
     209          160 :                 CCodeFunctionCall ccall = generate_instance_cast (new CCodeIdentifier ("object"), cl);
     210          160 :                 ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("self", ccall));
     211              : 
     212          160 :                 ccode.open_switch (new CCodeIdentifier ("property_id"));
     213          320 :                 var props = cl.get_properties ();
     214          876 :                 foreach (Property prop in props) {
     215          368 :                         if (prop.get_accessor == null || prop.is_abstract) {
     216           10 :                                 continue;
     217              :                         }
     218          358 :                         if (!context.analyzer.is_gobject_property (prop)) {
     219              :                                 // don't register private properties
     220           10 :                                 continue;
     221              :                         }
     222              : 
     223        17823 :                         Property base_prop = prop;
     224          348 :                         CCodeExpression cself = new CCodeIdentifier ("self");
     225          383 :                         if (prop.base_property != null) {
     226           35 :                                 var base_type = (Class) prop.base_property.parent_symbol;
     227           70 :                                 base_prop = prop.base_property;
     228           93 :                                 cself = get_cvalue_ (transform_value (new GLibValue (new ObjectType (cl), cself, true), new ObjectType (base_type), prop));
     229              : 
     230           35 :                                 generate_property_accessor_declaration (prop.base_property.get_accessor, cfile);
     231          338 :                         } else if (prop.base_interface_property != null) {
     232           25 :                                 var base_type = (Interface) prop.base_interface_property.parent_symbol;
     233           50 :                                 base_prop = prop.base_interface_property;
     234           50 :                                 cself = get_cvalue_ (transform_value (new GLibValue (new ObjectType (cl), cself, true), new ObjectType (base_type), prop));
     235              : 
     236           25 :                                 generate_property_accessor_declaration (prop.base_interface_property.get_accessor, cfile);
     237              :                         }
     238              : 
     239              :                         CCodeExpression cfunc;
     240          348 :                         if (!get_ccode_no_accessor_method (base_prop) && !get_ccode_concrete_accessor (base_prop)) {
     241          345 :                                 cfunc = new CCodeIdentifier (get_ccode_name (base_prop.get_accessor));
     242              :                         } else {
     243              :                                 // use the static real function as helper
     244            3 :                                 cfunc = new CCodeIdentifier (get_ccode_real_name (prop.get_accessor));
     245              :                         }
     246              : 
     247          348 :                         ccode.add_case (new CCodeIdentifier ("%s_PROPERTY".printf (get_ccode_upper_case_name (prop))));
     248          696 :                         if (prop.property_type.is_real_struct_type ()) {
     249           22 :                                 ccode.open_block ();
     250           22 :                                 ccode.add_declaration (get_ccode_name (prop.property_type), new CCodeVariableDeclarator ("boxed"));
     251              : 
     252           22 :                                 ccall = new CCodeFunctionCall (cfunc);
     253           22 :                                 ccall.add_argument (cself);
     254           22 :                                 if (prop.property_type.nullable) {
     255            3 :                                         ccode.add_assignment (new CCodeIdentifier ("boxed"), ccall);
     256              :                                 } else {
     257           19 :                                         ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("boxed")));
     258           19 :                                         ccode.add_expression (ccall);
     259              :                                 }
     260              : 
     261           22 :                                 var csetcall = new CCodeFunctionCall ();
     262           22 :                                 csetcall.call = get_value_setter_function (prop.property_type);
     263           22 :                                 csetcall.add_argument (new CCodeIdentifier ("value"));
     264           22 :                                 if (prop.property_type.nullable) {
     265            3 :                                         csetcall.add_argument (new CCodeIdentifier ("boxed"));
     266              :                                 } else {
     267           19 :                                         csetcall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("boxed")));
     268              :                                 }
     269           22 :                                 add_guarded_expression (prop, csetcall);
     270              : 
     271           22 :                                 if (requires_destroy (prop.get_accessor.value_type)) {
     272            6 :                                         ccode.add_expression (destroy_value (new GLibValue (prop.get_accessor.value_type, new CCodeIdentifier ("boxed"), true)));
     273              :                                 }
     274           22 :                                 ccode.close ();
     275              :                         } else {
     276          326 :                                 ccall = new CCodeFunctionCall (cfunc);
     277          326 :                                 ccall.add_argument (cself);
     278          326 :                                 var array_type = prop.property_type as ArrayType;
     279           12 :                                 if (array_type != null && get_ccode_array_length (prop) && array_type.element_type.type_symbol == string_type.type_symbol) {
     280              :                                         // G_TYPE_STRV
     281            7 :                                         ccode.open_block ();
     282            7 :                                         ccode.add_declaration ("int", new CCodeVariableDeclarator ("length"));
     283            7 :                                         ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("length")));
     284              :                                 }
     285          326 :                                 var csetcall = new CCodeFunctionCall ();
     286          326 :                                 if (prop.get_accessor.value_type.value_owned) {
     287           16 :                                         csetcall.call = get_value_taker_function (prop.property_type);
     288              :                                 } else {
     289          310 :                                         csetcall.call = get_value_setter_function (prop.property_type);
     290              :                                 }
     291          326 :                                 csetcall.add_argument (new CCodeIdentifier ("value"));
     292          326 :                                 if (base_prop != null && prop != base_prop && base_prop.property_type is GenericType) {
     293            4 :                                         csetcall.add_argument (convert_from_generic_pointer (ccall, prop.property_type));
     294              :                                 } else {
     295          322 :                                         csetcall.add_argument (ccall);
     296              :                                 }
     297          326 :                                 add_guarded_expression (prop, csetcall);
     298          326 :                                 if (array_type != null && get_ccode_array_length (prop) && array_type.element_type.type_symbol == string_type.type_symbol) {
     299            7 :                                         ccode.close ();
     300              :                                 }
     301              :                         }
     302          348 :                         ccode.add_break ();
     303              :                 }
     304              : 
     305              :                 /* type, dup func, and destroy func properties for generic types */
     306          200 :                 foreach (TypeParameter type_param in cl.get_type_parameters ()) {
     307              :                         string func_name, enum_value;
     308              :                         CCodeMemberAccess cfield;
     309              :                         CCodeFunctionCall csetcall;
     310              : 
     311           20 :                         func_name = get_ccode_type_id (type_param);
     312           20 :                         enum_value = "%s_%s".printf (get_ccode_lower_case_name (cl, null), func_name).ascii_up ();
     313           20 :                         ccode.add_case (new CCodeIdentifier (enum_value));
     314           20 :                         cfield = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), func_name);
     315           20 :                         csetcall = new CCodeFunctionCall (new CCodeIdentifier ("g_value_set_gtype"));
     316           20 :                         csetcall.add_argument (new CCodeIdentifier ("value"));
     317           20 :                         csetcall.add_argument (cfield);
     318           20 :                         ccode.add_expression (csetcall);
     319           20 :                         ccode.add_break ();
     320              : 
     321           20 :                         func_name = get_ccode_copy_function (type_param);
     322           20 :                         enum_value = "%s_%s".printf (get_ccode_lower_case_name (cl, null), func_name).ascii_up ();
     323           20 :                         ccode.add_case (new CCodeIdentifier (enum_value));
     324           20 :                         cfield = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), func_name);
     325           20 :                         csetcall = new CCodeFunctionCall (new CCodeIdentifier ("g_value_set_pointer"));
     326           20 :                         csetcall.add_argument (new CCodeIdentifier ("value"));
     327           20 :                         csetcall.add_argument (cfield);
     328           20 :                         ccode.add_expression (csetcall);
     329           20 :                         ccode.add_break ();
     330              : 
     331           20 :                         func_name = get_ccode_destroy_function (type_param);
     332           20 :                         enum_value = "%s_%s".printf (get_ccode_lower_case_name (cl, null), func_name).ascii_up ();
     333           20 :                         ccode.add_case (new CCodeIdentifier (enum_value));
     334           20 :                         cfield = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), func_name);
     335           20 :                         csetcall = new CCodeFunctionCall (new CCodeIdentifier ("g_value_set_pointer"));
     336           20 :                         csetcall.add_argument (new CCodeIdentifier ("value"));
     337           20 :                         csetcall.add_argument (cfield);
     338           20 :                         ccode.add_expression (csetcall);
     339           20 :                         ccode.add_break ();
     340              :                 }
     341          160 :                 ccode.add_default ();
     342          160 :                 emit_invalid_property_id_warn ();
     343          160 :                 ccode.add_break ();
     344              : 
     345          160 :                 ccode.close ();
     346              : 
     347          160 :                 pop_function ();
     348              : 
     349          160 :                 cfile.add_function_declaration (get_prop);
     350          160 :                 cfile.add_function (get_prop);
     351              :         }
     352              : 
     353          270 :         private void add_set_property_function (Class cl) {
     354          135 :                 var set_prop = new CCodeFunction ("_vala_%s_set_property".printf (get_ccode_lower_case_name (cl, null)), "void");
     355          135 :                 set_prop.modifiers = CCodeModifiers.STATIC;
     356          135 :                 set_prop.add_parameter (new CCodeParameter ("object", "GObject *"));
     357          135 :                 set_prop.add_parameter (new CCodeParameter ("property_id", "guint"));
     358          135 :                 set_prop.add_parameter (new CCodeParameter ("value", "const GValue *"));
     359          135 :                 set_prop.add_parameter (new CCodeParameter ("pspec", "GParamSpec *"));
     360              : 
     361          135 :                 push_function (set_prop);
     362              : 
     363          135 :                 CCodeFunctionCall ccall = generate_instance_cast (new CCodeIdentifier ("object"), cl);
     364          135 :                 ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("self", ccall));
     365              : 
     366          135 :                 ccode.open_switch (new CCodeIdentifier ("property_id"));
     367          270 :                 var props = cl.get_properties ();
     368          743 :                 foreach (Property prop in props) {
     369          333 :                         if (prop.set_accessor == null || prop.is_abstract) {
     370           49 :                                 continue;
     371              :                         }
     372          284 :                         if (!context.analyzer.is_gobject_property (prop)) {
     373            9 :                                 continue;
     374              :                         }
     375              : 
     376          275 :                         Property base_prop = prop;
     377          275 :                         CCodeExpression cself = new CCodeIdentifier ("self");
     378          287 :                         if (prop.base_property != null) {
     379           12 :                                 var base_type = (Class) prop.base_property.parent_symbol;
     380           24 :                                 base_prop = prop.base_property;
     381           24 :                                 cself = get_cvalue_ (transform_value (new GLibValue (new ObjectType (cl), cself, true), new ObjectType (base_type), prop));
     382              : 
     383           12 :                                 generate_property_accessor_declaration (prop.base_property.set_accessor, cfile);
     384          284 :                         } else if (prop.base_interface_property != null) {
     385           21 :                                 var base_type = (Interface) prop.base_interface_property.parent_symbol;
     386           42 :                                 base_prop = prop.base_interface_property;
     387           42 :                                 cself = get_cvalue_ (transform_value (new GLibValue (new ObjectType (cl), cself, true), new ObjectType (base_type), prop));
     388              : 
     389           21 :                                 generate_property_accessor_declaration (prop.base_interface_property.set_accessor, cfile);
     390              :                         }
     391              : 
     392              :                         CCodeExpression cfunc;
     393          275 :                         if (!get_ccode_no_accessor_method (base_prop) && !get_ccode_concrete_accessor (base_prop)) {
     394          272 :                                 cfunc = new CCodeIdentifier (get_ccode_name (base_prop.set_accessor));
     395              :                         } else {
     396              :                                 // use the static real function as helper
     397            3 :                                 cfunc = new CCodeIdentifier (get_ccode_real_name (prop.set_accessor));
     398              :                         }
     399              : 
     400          275 :                         ccode.add_case (new CCodeIdentifier ("%s_PROPERTY".printf (get_ccode_upper_case_name (prop))));
     401          275 :                         ccall = new CCodeFunctionCall (cfunc);
     402          275 :                         ccall.add_argument (cself);
     403          550 :                         if (prop.property_type is ArrayType && ((ArrayType)prop.property_type).element_type.type_symbol == string_type.type_symbol) {
     404           10 :                                 ccode.open_block ();
     405           10 :                                 ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("boxed"));
     406              : 
     407           10 :                                 var cgetcall = new CCodeFunctionCall (new CCodeIdentifier ("g_value_get_boxed"));
     408           10 :                                 cgetcall.add_argument (new CCodeIdentifier ("value"));
     409           10 :                                 ccode.add_assignment (new CCodeIdentifier ("boxed"), cgetcall);
     410           10 :                                 ccall.add_argument (new CCodeIdentifier ("boxed"));
     411              : 
     412           17 :                                 if (get_ccode_array_length (prop)) {
     413            7 :                                         var cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier ("boxed"), new CCodeConstant ("NULL"));
     414            7 :                                         var cstrvlen = new CCodeFunctionCall (new CCodeIdentifier ("g_strv_length"));
     415            7 :                                         cstrvlen.add_argument (new CCodeIdentifier ("boxed"));
     416            7 :                                         var ccond = new CCodeConditionalExpression (cisnull, new CCodeConstant ("0"), cstrvlen);
     417              : 
     418            7 :                                         ccall.add_argument (ccond);
     419              :                                 }
     420           10 :                                 add_guarded_expression (prop, ccall);
     421           10 :                                 ccode.close ();
     422              :                         } else {
     423          265 :                                 var cgetcall = new CCodeFunctionCall ();
     424          265 :                                 if (prop.property_type.type_symbol != null) {
     425          261 :                                         cgetcall.call = new CCodeIdentifier (get_ccode_get_value_function (prop.property_type.type_symbol));
     426              :                                 } else {
     427            4 :                                         cgetcall.call = new CCodeIdentifier ("g_value_get_pointer");
     428              :                                 }
     429          265 :                                 cgetcall.add_argument (new CCodeIdentifier ("value"));
     430          265 :                                 if (base_prop != null && prop != base_prop && base_prop.property_type is GenericType) {
     431            4 :                                         ccall.add_argument (convert_to_generic_pointer (cgetcall, prop.property_type));
     432              :                                 } else {
     433          261 :                                         ccall.add_argument (cgetcall);
     434              :                                 }
     435          265 :                                 add_guarded_expression (prop, ccall);
     436              :                         }
     437          275 :                         ccode.add_break ();
     438              :                 }
     439              : 
     440              :                 /* type, dup func, and destroy func properties for generic types */
     441          175 :                 foreach (TypeParameter type_param in cl.get_type_parameters ()) {
     442              :                         string func_name, enum_value;
     443              :                         CCodeMemberAccess cfield;
     444              :                         CCodeFunctionCall cgetcall;
     445              : 
     446           20 :                         func_name = get_ccode_type_id (type_param);
     447           20 :                         enum_value = "%s_%s".printf (get_ccode_lower_case_name (cl, null), func_name).ascii_up ();
     448           20 :                         ccode.add_case (new CCodeIdentifier (enum_value));
     449           20 :                         cfield = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), func_name);
     450           20 :                         cgetcall = new CCodeFunctionCall (new CCodeIdentifier ("g_value_get_gtype"));
     451           20 :                         cgetcall.add_argument (new CCodeIdentifier ("value"));
     452           20 :                         ccode.add_assignment (cfield, cgetcall);
     453           20 :                         ccode.add_break ();
     454              : 
     455           20 :                         func_name = get_ccode_copy_function (type_param);
     456           20 :                         enum_value = "%s_%s".printf (get_ccode_lower_case_name (cl, null), func_name).ascii_up ();
     457           20 :                         ccode.add_case (new CCodeIdentifier (enum_value));
     458           20 :                         cfield = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), func_name);
     459           20 :                         cgetcall = new CCodeFunctionCall (new CCodeIdentifier ("g_value_get_pointer"));
     460           20 :                         cgetcall.add_argument (new CCodeIdentifier ("value"));
     461           20 :                         ccode.add_assignment (cfield, cgetcall);
     462           20 :                         ccode.add_break ();
     463              : 
     464           20 :                         func_name = get_ccode_destroy_function (type_param);
     465           20 :                         enum_value = "%s_%s".printf (get_ccode_lower_case_name (cl, null), func_name).ascii_up ();
     466           20 :                         ccode.add_case (new CCodeIdentifier (enum_value));
     467           20 :                         cfield = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), func_name);
     468           20 :                         cgetcall = new CCodeFunctionCall (new CCodeIdentifier ("g_value_get_pointer"));
     469           20 :                         cgetcall.add_argument (new CCodeIdentifier ("value"));
     470           20 :                         ccode.add_assignment (cfield, cgetcall);
     471           20 :                         ccode.add_break ();
     472              :                 }
     473          135 :                 ccode.add_default ();
     474          135 :                 emit_invalid_property_id_warn ();
     475          135 :                 ccode.add_break ();
     476              : 
     477          135 :                 ccode.close ();
     478              : 
     479          135 :                 pop_function ();
     480              : 
     481          135 :                 cfile.add_function_declaration (set_prop);
     482          135 :                 cfile.add_function (set_prop);
     483              :         }
     484              : 
     485          590 :         private void emit_invalid_property_id_warn () {
     486              :                 // warn on invalid property id
     487          295 :                 var cwarn = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_WARN_INVALID_PROPERTY_ID"));
     488          295 :                 cwarn.add_argument (new CCodeIdentifier ("object"));
     489          295 :                 cwarn.add_argument (new CCodeIdentifier ("property_id"));
     490          295 :                 cwarn.add_argument (new CCodeIdentifier ("pspec"));
     491          295 :                 ccode.add_expression (cwarn);
     492              :         }
     493              : 
     494           69 :         public override void visit_constructor (Constructor c) {
     495           35 :                 push_line (c.source_reference);
     496              : 
     497           35 :                 var cl = (Class) c.parent_symbol;
     498              : 
     499           55 :                 if (c.binding == MemberBinding.INSTANCE) {
     500           21 :                         if (!cl.is_subtype_of (gobject_type)) {
     501            1 :                                 Report.error (c.source_reference, "construct blocks require GLib.Object");
     502            1 :                                 c.error = true;
     503            1 :                                 return;
     504              :                         }
     505              : 
     506           20 :                         push_context (new EmitContext (c));
     507              : 
     508           20 :                         var function = new CCodeFunction ("%sconstructor".printf (get_ccode_lower_case_prefix (cl)), "GObject *");
     509           20 :                         function.modifiers = CCodeModifiers.STATIC;
     510              : 
     511           20 :                         function.add_parameter (new CCodeParameter ("type", "GType"));
     512           20 :                         function.add_parameter (new CCodeParameter ("n_construct_properties", "guint"));
     513           20 :                         function.add_parameter (new CCodeParameter ("construct_properties", "GObjectConstructParam *"));
     514              : 
     515           20 :                         cfile.add_function_declaration (function);
     516              : 
     517           20 :                         push_function (function);
     518              : 
     519           20 :                         ccode.add_declaration ("GObject *", new CCodeVariableDeclarator ("obj"));
     520           20 :                         ccode.add_declaration ("GObjectClass *", new CCodeVariableDeclarator ("parent_class"));
     521              : 
     522           23 :                         if (cl.is_singleton) {
     523            3 :                                 var singleton_ref_name = "%s_singleton__ref".printf (get_ccode_name (cl));
     524            3 :                                 var singleton_lock_name = "%s_singleton__lock".printf (get_ccode_name (cl));
     525              : 
     526            3 :                                 var singleton_ref = new CCodeDeclaration("GWeakRef");
     527            3 :                                 singleton_ref.add_declarator (new CCodeVariableDeclarator (singleton_ref_name));
     528            3 :                                 singleton_ref.modifiers = CCodeModifiers.STATIC;
     529            3 :                                 ccode.add_statement (singleton_ref);
     530              : 
     531            3 :                                 var mutex_lock = new CCodeDeclaration("GMutex");
     532            3 :                                 mutex_lock.add_declarator (new CCodeVariableDeclarator (singleton_lock_name));
     533            3 :                                 mutex_lock.modifiers = CCodeModifiers.STATIC;
     534            3 :                                 ccode.add_statement (mutex_lock);
     535              : 
     536            3 :                                 var singleton_mutex_lock = new CCodeFunctionCall (new CCodeIdentifier ("g_mutex_lock"));
     537            3 :                                 singleton_mutex_lock.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (singleton_lock_name)));
     538            3 :                                 ccode.add_statement (new CCodeExpressionStatement (singleton_mutex_lock));
     539              : 
     540            3 :                                 var get_from_singleton = new CCodeFunctionCall (new CCodeIdentifier ("g_weak_ref_get"));
     541            3 :                                 get_from_singleton.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (singleton_ref_name)));
     542            3 :                                 ccode.add_assignment (new CCodeIdentifier ("obj"), get_from_singleton);
     543              : 
     544            3 :                                 var check_existance = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("obj"), new CCodeConstant ("NULL"));
     545            3 :                                 var return_singleton = new CCodeBlock();
     546              : 
     547            3 :                                 var singleton_mutex_unlock = new CCodeFunctionCall (new CCodeIdentifier ("g_mutex_unlock"));
     548            3 :                                 singleton_mutex_unlock.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (singleton_lock_name)));
     549            3 :                                 return_singleton.add_statement (new CCodeExpressionStatement (singleton_mutex_unlock));
     550            3 :                                 return_singleton.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("obj")));
     551              : 
     552            3 :                                 var if_singleton_alive = new CCodeIfStatement (check_existance, return_singleton);
     553            3 :                                 ccode.add_statement (if_singleton_alive);
     554              :                         }
     555              : 
     556           20 :                         var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
     557           20 :                         ccast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (get_ccode_lower_case_name (cl, null))));
     558           20 :                         ccode.add_assignment (new CCodeIdentifier ("parent_class"), ccast);
     559              : 
     560           20 :                         var ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (new CCodeIdentifier ("parent_class"), "constructor"));
     561           20 :                         ccall.add_argument (new CCodeIdentifier ("type"));
     562           20 :                         ccall.add_argument (new CCodeIdentifier ("n_construct_properties"));
     563           20 :                         ccall.add_argument (new CCodeIdentifier ("construct_properties"));
     564           20 :                         ccode.add_assignment (new CCodeIdentifier ("obj"), ccall);
     565              : 
     566              : 
     567           20 :                         ccall = generate_instance_cast (new CCodeIdentifier ("obj"), cl);
     568              : 
     569           20 :                         ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("self"));
     570           20 :                         ccode.add_assignment (new CCodeIdentifier ("self"), ccall);
     571              : 
     572           20 :                         c.body.emit (this);
     573              : 
     574           20 :                         if (current_method_inner_error) {
     575              :                                 /* always separate error parameter and inner_error local variable
     576              :                                  * as error may be set to NULL but we're always interested in inner errors
     577              :                                  */
     578            2 :                                 ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("_inner_error%d_".printf (current_inner_error_id), new CCodeConstant ("NULL")));
     579              :                         }
     580              : 
     581           23 :                         if (cl.is_singleton) {
     582            3 :                                 var singleton_ref_name = "%s_singleton__ref".printf (get_ccode_name (cl));
     583            3 :                                 var singleton_lock_name = "%s_singleton__lock".printf (get_ccode_name (cl));
     584              : 
     585            3 :                                 var set_singleton_reference = new CCodeFunctionCall (new CCodeIdentifier ("g_weak_ref_set"));
     586            3 :                                 set_singleton_reference.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (singleton_ref_name)));
     587            3 :                                 set_singleton_reference.add_argument (new CCodeIdentifier ("obj"));
     588            3 :                                 ccode.add_statement (new CCodeExpressionStatement (set_singleton_reference));
     589              : 
     590            3 :                                 var final_singleton_mutex_unlock = new CCodeFunctionCall (new CCodeIdentifier ("g_mutex_unlock"));
     591            3 :                                 final_singleton_mutex_unlock.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (singleton_lock_name)));
     592            3 :                                 ccode.add_statement (new CCodeExpressionStatement (final_singleton_mutex_unlock));
     593              :                         }
     594              : 
     595           20 :                         ccode.add_return (new CCodeIdentifier ("obj"));
     596              : 
     597           20 :                         pop_function ();
     598           20 :                         cfile.add_function (function);
     599              : 
     600           20 :                         pop_context ();
     601           14 :                 } else if (c.binding == MemberBinding.CLASS) {
     602              :                         // class constructor
     603              : 
     604            7 :                         if (cl.is_compact) {
     605            0 :                                 Report.error (c.source_reference, "class constructors are not supported in compact classes");
     606            0 :                                 c.error = true;
     607            0 :                                 return;
     608              :                         }
     609              : 
     610            7 :                         push_context (base_init_context);
     611              : 
     612            7 :                         c.body.emit (this);
     613              : 
     614            7 :                         if (current_method_inner_error) {
     615              :                                 /* always separate error parameter and inner_error local variable
     616              :                                  * as error may be set to NULL but we're always interested in inner errors
     617              :                                  */
     618            2 :                                 ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("_inner_error%d_".printf (current_inner_error_id), new CCodeConstant ("NULL")));
     619              :                         }
     620              : 
     621            7 :                         pop_context ();
     622            7 :                 } else if (c.binding == MemberBinding.STATIC) {
     623              :                         // static class constructor
     624              :                         // add to class_init
     625              : 
     626            7 :                         if (cl.is_compact) {
     627            0 :                                 Report.error (c.source_reference, "static constructors are not supported in compact classes");
     628            0 :                                 c.error = true;
     629            0 :                                 return;
     630              :                         }
     631              : 
     632            7 :                         push_context (class_init_context);
     633              : 
     634            7 :                         c.body.emit (this);
     635              : 
     636            7 :                         if (current_method_inner_error) {
     637              :                                 /* always separate error parameter and inner_error local variable
     638              :                                  * as error may be set to NULL but we're always interested in inner errors
     639              :                                  */
     640            2 :                                 ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("_inner_error%d_".printf (current_inner_error_id), new CCodeConstant ("NULL")));
     641              :                         }
     642              : 
     643            7 :                         pop_context ();
     644              :                 } else {
     645            0 :                         Report.error (c.source_reference, "internal error: constructors must have instance, class, or static binding");
     646              :                 }
     647              : 
     648           34 :                 pop_line ();
     649              :         }
     650              : 
     651            6 :         public override string get_dynamic_signal_cname (DynamicSignal node) {
     652            6 :                 return "dynamic_%s%d_".printf (node.name, signal_wrapper_id++);
     653              :         }
     654              : 
     655          510 :         public override void visit_property (Property prop) {
     656          510 :                 base.visit_property (prop);
     657              : 
     658          510 :                 if (context.analyzer.is_gobject_property (prop) && prop.parent_symbol is Class) {
     659          358 :                         prop_enum.add_value (new CCodeEnumValue ("%s_PROPERTY".printf (get_ccode_upper_case_name (prop))));
     660              :                 }
     661              :         }
     662              : 
     663        17445 :         public override void visit_method_call (MethodCall expr) {
     664        34395 :                 if (expr.call is MemberAccess) {
     665        16959 :                         push_line (expr.source_reference);
     666              : 
     667        16959 :                         var ma = expr.call as MemberAccess;
     668        16959 :                         if (ma.inner != null && ma.inner.symbol_reference == gobject_type &&
     669            9 :                             (ma.member_name == "new" || ma.member_name == "newv"
     670            0 :                              || ma.member_name == "new_valist" || ma.member_name == "new_with_properties")) {
     671              :                                 // Object.new (...) creation
     672              :                                 // runtime check to ref_sink the instance if it's a floating type
     673            9 :                                 base.visit_method_call (expr);
     674              : 
     675            9 :                                 var initiallyunowned_ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_IS_INITIALLY_UNOWNED"));
     676            9 :                                 initiallyunowned_ccall.add_argument (get_cvalue (expr));
     677            9 :                                 var sink_ref_ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_ref_sink"));
     678            9 :                                 sink_ref_ccall.add_argument (get_cvalue (expr));
     679            9 :                                 var cexpr = new CCodeConditionalExpression (initiallyunowned_ccall, sink_ref_ccall, get_cvalue (expr));
     680              : 
     681            9 :                                 expr.target_value = store_temp_value (new GLibValue (expr.value_type, cexpr), expr);
     682            9 :                                 return;
     683        16950 :                         } else if (ma.symbol_reference == gobject_type) {
     684              :                                 // Object (...) chain up
     685              :                                 // check it's only used with valid properties
     686           30 :                                 foreach (var arg in expr.get_argument_list ()) {
     687            8 :                                         var named_argument = arg as NamedArgument;
     688            8 :                                         if (named_argument == null) {
     689            0 :                                                 Report.error (arg.source_reference, "Named argument expected");
     690            0 :                                                 break;
     691              :                                         }
     692            8 :                                         var prop = SemanticAnalyzer.symbol_lookup_inherited (current_class, named_argument.name) as Property;
     693            1 :                                         if (prop == null) {
     694            1 :                                                 Report.error (arg.source_reference, "Property `%s' not found in `%s'", named_argument.name, current_class.get_full_name ());
     695            1 :                                                 break;
     696              :                                         }
     697            7 :                                         if (!context.analyzer.is_gobject_property (prop)) {
     698            0 :                                                 Report.error (arg.source_reference, "Property `%s' not supported in Object (property: value) constructor chain up", named_argument.name);
     699            0 :                                                 break;
     700              :                                         }
     701            7 :                                         if (!arg.value_type.compatible (prop.property_type)) {
     702            1 :                                                 Report.error (arg.source_reference, "Cannot convert from `%s' to `%s'", arg.value_type.to_string (), prop.property_type.to_string ());
     703            1 :                                                 break;
     704              :                                         }
     705              :                                 }
     706              :                         }
     707              : 
     708        16950 :                         pop_line ();
     709              :                 }
     710              : 
     711        17436 :                 base.visit_method_call (expr);
     712              :         }
     713              : }
     714              : 
        

Generated by: LCOV version 2.0-1