LCOV - code coverage report
Current view: top level - vala - valapropertyaccessor.vala (source / functions) Coverage Total Hit
Test: vala 0.57.0.298-a8cae1 Lines: 95.3 % 128 122
Test Date: 2024-04-25 11:34:36 Functions: - 0 0

            Line data    Source code
       1              : /* valapropertyaccessor.vala
       2              :  *
       3              :  * Copyright (C) 2006-2010  Jürg Billeter
       4              :  *
       5              :  * This library is free software; you can redistribute it and/or
       6              :  * modify it under the terms of the GNU Lesser General Public
       7              :  * License as published by the Free Software Foundation; either
       8              :  * version 2.1 of the License, or (at your option) any later version.
       9              : 
      10              :  * This library is distributed in the hope that it will be useful,
      11              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13              :  * Lesser General Public License for more details.
      14              : 
      15              :  * You should have received a copy of the GNU Lesser General Public
      16              :  * License along with this library; if not, write to the Free Software
      17              :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
      18              :  *
      19              :  * Author:
      20              :  *      Jürg Billeter <j@bitron.ch>
      21              :  */
      22              : 
      23              : using GLib;
      24              : 
      25              : /**
      26              :  * Represents a get or set accessor of a property in the source code.
      27              :  */
      28       758341 : public class Vala.PropertyAccessor : Subroutine {
      29              :         /**
      30              :          * The corresponding property.
      31              :          */
      32              :         public Property prop {
      33      5125838 :                 get { return parent_symbol as Property; }
      34              :         }
      35              : 
      36              :         /**
      37              :          * The property type.
      38              :          */
      39              :         public DataType? value_type {
      40      3588561 :                 get { return _value_type; }
      41      1434193 :                 private set {
      42      2451190 :                         _value_type = value;
      43      1434193 :                         if (value != null) {
      44      1434189 :                                 _value_type.parent_node = this;
      45              :                         }
      46              :                 }
      47              :         }
      48              : 
      49              :         /**
      50              :          * Specifies whether this accessor may be used to get the property.
      51              :          */
      52       801225 :         public bool readable { get; private set; }
      53              : 
      54              :         /**
      55              :          * Specifies whether this accessor may be used to set the property.
      56              :          */
      57       767852 :         public bool writable { get; private set; }
      58              : 
      59              :         /**
      60              :          * Specifies whether this accessor may be used to construct the
      61              :          * property.
      62              :          */
      63      1073781 :         public bool construction { get; private set; }
      64              : 
      65              :         /**
      66              :          * True if the body was automatically generated
      67              :          */
      68        13546 :         public bool automatic_body { get; private set; }
      69              : 
      70              :         public override bool has_result {
      71          477 :                 get { return readable; }
      72              :         }
      73              : 
      74              :         /**
      75              :          * Represents the generated value parameter in a set accessor.
      76              :          */
      77      1383615 :         public Parameter value_parameter { get; private set; }
      78              : 
      79       756803 :         private DataType _value_type;
      80              : 
      81              :         /**
      82              :          * Creates a new property accessor.
      83              :          *
      84              :          * @param readable           true if get accessor, false otherwise
      85              :          * @param writable           true if set accessor, false otherwise
      86              :          * @param construction       true if construct accessor, false otherwise
      87              :          * @param body               accessor body
      88              :          * @param source_reference   reference to source code
      89              :          * @return                   newly created property accessor
      90              :          */
      91       756803 :         public PropertyAccessor (bool readable, bool writable, bool construction, DataType? value_type, Block? body, SourceReference? source_reference = null, Comment? comment = null) {
      92       756803 :                 base (null, source_reference, comment);
      93       756803 :                 this.readable = readable;
      94       756803 :                 this.writable = writable;
      95       756803 :                 this.construction = construction;
      96       756803 :                 this.value_type = value_type;
      97       756803 :                 this.body = body;
      98       756803 :                 this.access = SymbolAccessibility.PUBLIC;
      99              :         }
     100              : 
     101      1199588 :         public override void accept (CodeVisitor visitor) {
     102      1199588 :                 visitor.visit_property_accessor (this);
     103              :         }
     104              : 
     105       712337 :         public override void accept_children (CodeVisitor visitor) {
     106       712337 :                 value_type.accept (visitor);
     107              : 
     108       712337 :                 if (result_var != null) {
     109            0 :                         result_var.accept (visitor);
     110              :                 }
     111              : 
     112       712337 :                 if (body != null) {
     113        10841 :                         body.accept (visitor);
     114              :                 }
     115              :         }
     116              : 
     117              :         /**
     118              :          * Get the method representing this property accessor
     119              :          * @return   null if the accessor is neither readable nor writable
     120              :          */
     121          215 :         public Method? get_method () {
     122          215 :                 Method? m = null;
     123          215 :                 if (readable) {
     124          178 :                         m = new Method ("get_%s".printf (prop.name), value_type, source_reference, comment);
     125              : 
     126              :                         // Inherit important attributes
     127          178 :                         m.copy_attribute_bool (prop, "CCode", "array_length");
     128          178 :                         m.copy_attribute_string (prop, "CCode", "array_length_type");
     129          178 :                         m.copy_attribute_bool (prop, "CCode", "array_null_terminated");
     130          178 :                         m.copy_attribute_bool (prop, "CCode", "delegate_target");
     131           37 :                 } else if (writable || construction) {
     132           37 :                         m = new Method ("set_%s".printf (prop.name), new VoidType(), source_reference, comment);
     133           37 :                         m.add_parameter (value_parameter.copy ());
     134              :                 }
     135              : 
     136          215 :                 if (m != null) {
     137          215 :                         m.owner = prop.owner;
     138          215 :                         m.access = access;
     139          215 :                         m.binding = prop.binding;
     140          215 :                         m.is_abstract = prop.is_abstract;
     141          215 :                         m.is_virtual = prop.is_virtual;
     142          215 :                         m.this_parameter = prop.this_parameter;
     143              : 
     144              :                         // Inherit important attributes
     145          215 :                         m.copy_attribute_bool (prop, "GIR", "visible");
     146              :                 }
     147              : 
     148              :                 return m;
     149              :         }
     150              : 
     151       704633 :         public override bool check (CodeContext context) {
     152       704633 :                 if (checked) {
     153            0 :                         return !error;
     154              :                 }
     155              : 
     156       704633 :                 checked = true;
     157              : 
     158       704633 :                 if (!value_type.check (context)) {
     159            4 :                         error = true;
     160            4 :                         return false;
     161              :                 }
     162              : 
     163       704629 :                 var old_symbol = context.analyzer.current_symbol;
     164              : 
     165       704629 :                 context.analyzer.current_symbol = this;
     166              : 
     167       704629 :                 if (writable || construction) {
     168       312368 :                         value_parameter = new Parameter ("value", value_type, source_reference);
     169              :                         // Inherit important attributes
     170       312368 :                         value_parameter.copy_attribute_bool (prop, "CCode", "array_length");
     171       312368 :                         value_parameter.copy_attribute_string (prop, "CCode", "array_length_type");
     172       312368 :                         value_parameter.copy_attribute_bool (prop, "CCode", "array_null_terminated");
     173       312368 :                         value_parameter.copy_attribute_bool (prop, "CCode", "delegate_target");
     174              :                 }
     175              : 
     176      1096882 :                 if (context.profile == Profile.GOBJECT
     177       704621 :                     && readable && ((TypeSymbol) prop.parent_symbol).is_subtype_of (context.analyzer.object_type)) {
     178              :                         //FIXME Code duplication with CCodeMemberAccessModule.visit_member_access()
     179       375158 :                         if (prop.has_attribute ("NoAccessorMethod")) {
     180       120916 :                                 if (value_type.is_real_struct_type ()) {
     181          388 :                                         if (source_reference == null || source_reference.file == null) {
     182              :                                                 // Hopefully good as is
     183          380 :                                         } else if (!value_type.value_owned && source_reference.file.file_type == SourceFileType.SOURCE) {
     184            1 :                                                 error = true;
     185            1 :                                                 Report.error (source_reference, "unowned return value for getter of property `%s' not supported without accessor", prop.get_full_name ());
     186              :                                         }
     187       120528 :                                 } else if (value_type.value_owned && (source_reference == null || source_reference.file == null)) {
     188          785 :                                         if (value_type is DelegateType || value_type is PointerType || (value_type is ValueType && !value_type.nullable)) {
     189          592 :                                                 value_type.value_owned = false;
     190              :                                         }
     191              :                                 }
     192              :                         }
     193              :                 }
     194              : 
     195       704629 :                 if (prop.source_type == SourceFileType.SOURCE) {
     196         2213 :                         if (body == null && !prop.interface_only && !prop.is_abstract) {
     197              :                                 /* no accessor body specified, insert default body */
     198              : 
     199          958 :                                 automatic_body = true;
     200          958 :                                 body = new Block (source_reference);
     201          958 :                                 var ma = new MemberAccess.simple ("_%s".printf (prop.name), source_reference);
     202         1437 :                                 if (readable) {
     203          479 :                                         body.add_statement (new ReturnStatement (ma, source_reference));
     204              :                                 } else {
     205          479 :                                         Expression value = new MemberAccess.simple ("value", source_reference);
     206          479 :                                         if (value_type.value_owned) {
     207           11 :                                                 value = new ReferenceTransferExpression (value, source_reference);
     208              :                                         }
     209          479 :                                         var assignment = new Assignment (ma, value, AssignmentOperator.SIMPLE, source_reference);
     210          479 :                                         body.add_statement (new ExpressionStatement (assignment));
     211              :                                 }
     212              :                         }
     213              :                 }
     214              : 
     215       704629 :                 if ((prop.is_abstract || prop.is_virtual || prop.overrides) && access == SymbolAccessibility.PRIVATE) {
     216            2 :                         error = true;
     217            2 :                         Report.error (source_reference, "Property `%s' with private accessor cannot be marked as abstract, virtual or override", prop.get_full_name ());
     218            2 :                         return false;
     219              :                 }
     220              : 
     221       704627 :                 if (value_type.value_owned && value_type.is_non_null_simple_type ()) {
     222            2 :                         error = true;
     223            2 :                         Report.error (source_reference, "`owned' accessor not allowed for specified property type");
     224            2 :                         return false;
     225              :                 }
     226              : 
     227       704625 :                 if (context.profile == Profile.POSIX && construction) {
     228            0 :                         error = true;
     229            0 :                         Report.error (source_reference, "`construct' is not supported in POSIX profile");
     230            0 :                         return false;
     231       704625 :                 } else if (construction && !((TypeSymbol) prop.parent_symbol).is_subtype_of (context.analyzer.object_type)) {
     232            2 :                         error = true;
     233            2 :                         Report.error (source_reference, "construct properties require `GLib.Object'");
     234            2 :                         return false;
     235       704623 :                 } else if (construction && !context.analyzer.is_gobject_property (prop)) {
     236              :                         //TODO Report an error for external property too
     237            2 :                         if (external_package) {
     238            0 :                                 Report.warning (source_reference, "construct properties not supported for specified property type");
     239              :                         } else {
     240            2 :                                 error = true;
     241            2 :                                 Report.error (source_reference, "construct properties not supported for specified property type");
     242            2 :                                 return false;
     243              :                         }
     244              :                 }
     245              : 
     246       704621 :                 if (body != null && prop.is_abstract) {
     247            1 :                         error = true;
     248            1 :                         Report.error (source_reference, "Accessor of abstract property `%s' cannot have body", prop.get_full_name ());
     249            1 :                         return false;
     250              :                 }
     251              : 
     252       704620 :                 if (body != null) {
     253         6821 :                         if (writable || construction) {
     254          510 :                                 body.scope.add (value_parameter.name, value_parameter);
     255              :                         }
     256              : 
     257         6821 :                         body.check (context);
     258              :                 }
     259              : 
     260       711437 :                 if (body != null && !body.error) {
     261         6817 :                         var error_types = new ArrayList<DataType> ();
     262         6817 :                         body.get_error_types (error_types);
     263         6821 :                         foreach (DataType body_error_type in error_types) {
     264            2 :                                 if (!((ErrorType) body_error_type).dynamic_error) {
     265            2 :                                         Report.warning (body_error_type.source_reference, "unhandled error `%s'", body_error_type.to_string ());
     266              :                                 }
     267              :                         }
     268              :                 }
     269              : 
     270       704620 :                 context.analyzer.current_symbol = old_symbol;
     271              : 
     272       704620 :                 return !error;
     273              :         }
     274              : 
     275       677390 :         public override void replace_type (DataType old_type, DataType new_type) {
     276       677390 :                 if (value_type == old_type) {
     277       677390 :                         value_type = new_type;
     278              :                 }
     279              :         }
     280              : }
        

Generated by: LCOV version 2.0-1