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

            Line data    Source code
       1              : /* valamemberinitializer.vala
       2              :  *
       3              :  * Copyright (C) 2007-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 member initializer, i.e. an element of an object initializer, in
      27              :  * the source code.
      28              :  */
      29          140 : public class Vala.MemberInitializer : Expression {
      30              :         /**
      31              :          * Member name.
      32              :          */
      33          333 :         public string name { get; private set; }
      34              : 
      35              :         /**
      36              :          * Initializer expression.
      37              :          */
      38              :         public Expression initializer {
      39         1552 :                 get { return _initializer; }
      40          111 :                 private set {
      41          221 :                         _initializer = value;
      42          111 :                         _initializer.parent_node = this;
      43              :                 }
      44              :         }
      45              : 
      46          108 :         Expression _initializer;
      47              : 
      48              :         /**
      49              :          * Creates a new member initializer.
      50              :          *
      51              :          * @param name             member name
      52              :          * @param initializer      initializer expression
      53              :          * @param source_reference reference to source code
      54              :          * @return                 newly created member initializer
      55              :          */
      56          324 :         public MemberInitializer (string name, Expression initializer, SourceReference? source_reference = null) {
      57          108 :                 this.initializer = initializer;
      58          108 :                 this.source_reference = source_reference;
      59          108 :                 this.name = name;
      60              :         }
      61              : 
      62            0 :         public override bool is_pure () {
      63            0 :                 return false;
      64              :         }
      65              : 
      66          469 :         public override void accept (CodeVisitor visitor) {
      67          469 :                 initializer.accept (visitor);
      68              :         }
      69              : 
      70           99 :         public override bool check (CodeContext context) {
      71           99 :                 if (checked) {
      72            0 :                         return !error;
      73              :                 }
      74              : 
      75           99 :                 checked = true;
      76              : 
      77           99 :                 unowned ObjectCreationExpression? oce = parent_node as ObjectCreationExpression;
      78            0 :                 if (oce == null) {
      79            0 :                         error = true;
      80            0 :                         Report.error (source_reference, "internal: Invalid member initializer");
      81            0 :                         return false;
      82              :                 }
      83              : 
      84           99 :                 unowned DataType type = oce.type_reference;
      85              : 
      86           99 :                 symbol_reference = SemanticAnalyzer.symbol_lookup_inherited (type.type_symbol, name);
      87           99 :                 if (!(symbol_reference is Field || symbol_reference is Property)) {
      88            1 :                         error = true;
      89            1 :                         Report.error (source_reference, "Invalid member `%s' in `%s'", name, type.type_symbol.get_full_name ());
      90            1 :                         return false;
      91              :                 }
      92              : 
      93              :                 // FIXME Code duplication with MemberAccess.check()
      94           98 :                 if (symbol_reference.access == SymbolAccessibility.PROTECTED && symbol_reference.parent_symbol is TypeSymbol) {
      95            2 :                         unowned TypeSymbol target_type = (TypeSymbol) symbol_reference.parent_symbol;
      96              : 
      97            2 :                         bool in_subtype = false;
      98           19 :                         for (Symbol this_symbol = context.analyzer.current_symbol; this_symbol != null; this_symbol = this_symbol.parent_symbol) {
      99            6 :                                 if (this_symbol == target_type) {
     100              :                                         // required for interfaces with non-abstract methods
     101              :                                         // accessing protected interface members
     102              :                                         in_subtype = true;
     103              :                                         break;
     104              :                                 }
     105              : 
     106            5 :                                 unowned Class? cl = this_symbol as Class;
     107            5 :                                 if (cl != null && cl.is_subtype_of (target_type)) {
     108              :                                         in_subtype = true;
     109              :                                         break;
     110              :                                 }
     111              :                         }
     112              : 
     113            2 :                         if (!in_subtype) {
     114            1 :                                 error = true;
     115            1 :                                 Report.error (source_reference, "Access to protected member `%s' denied", symbol_reference.get_full_name ());
     116            1 :                                 return false;
     117              :                         }
     118           96 :                 } else if (symbol_reference.access == SymbolAccessibility.PRIVATE) {
     119            2 :                         unowned Symbol? target_type = symbol_reference.parent_symbol;
     120              : 
     121            2 :                         bool in_target_type = false;
     122           19 :                         for (Symbol this_symbol = context.analyzer.current_symbol; this_symbol != null; this_symbol = this_symbol.parent_symbol) {
     123            6 :                                 if (target_type == this_symbol) {
     124              :                                         in_target_type = true;
     125              :                                         break;
     126              :                                 }
     127              :                         }
     128              : 
     129            2 :                         if (!in_target_type) {
     130            1 :                                 error = true;
     131            1 :                                 Report.error (source_reference, "Access to private member `%s' denied", symbol_reference.get_full_name ());
     132            1 :                                 return false;
     133              :                         }
     134              :                 }
     135              : 
     136           96 :                 DataType member_type = null;
     137           96 :                 if (symbol_reference is Field) {
     138           79 :                         unowned Field f = (Field) symbol_reference;
     139           79 :                         member_type = f.variable_type;
     140           17 :                 } else if (symbol_reference is Property) {
     141           17 :                         unowned Property prop = (Property) symbol_reference;
     142           17 :                         member_type = prop.property_type;
     143           17 :                         if (prop.set_accessor == null || !prop.set_accessor.writable) {
     144            1 :                                 error = true;
     145            1 :                                 Report.error (source_reference, "Property `%s' is read-only", prop.get_full_name ());
     146            1 :                                 return false;
     147              :                         }
     148              :                 }
     149              : 
     150           95 :                 initializer.formal_target_type = member_type;
     151           95 :                 initializer.target_type = initializer.formal_target_type.get_actual_type (type, null, this);
     152              : 
     153           95 :                 if (!initializer.check (context)) {
     154            0 :                         return false;
     155              :                 }
     156              : 
     157           95 :                 if (initializer.value_type == null || !initializer.value_type.compatible (initializer.target_type)) {
     158            1 :                         error = true;
     159            1 :                         Report.error (source_reference, "Invalid type for member `%s'", name);
     160            1 :                         return false;
     161              :                 }
     162              : 
     163           94 :                 return !error;
     164              :         }
     165              : 
     166           94 :         public override void emit (CodeGenerator codegen) {
     167           94 :                 initializer.emit (codegen);
     168              :         }
     169              : 
     170           93 :         public override void get_used_variables (Collection<Variable> collection) {
     171           93 :                 initializer.get_used_variables (collection);
     172              :         }
     173              : 
     174            3 :         public override void replace_expression (Expression old_node, Expression new_node) {
     175            3 :                 if (initializer == old_node) {
     176            3 :                         initializer = new_node;
     177              :                 }
     178              :         }
     179              : }
     180              : 
        

Generated by: LCOV version 2.0-1