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

            Line data    Source code
       1              : /* valalockstatement.vala
       2              :  *
       3              :  * Copyright (C) 2009  Jiří Zárevúcky
       4              :  * Copyright (C) 2006-2010  Jürg Billeter
       5              :  * Copyright (C) 2006-2007  Raffaele Sandrini
       6              :  *
       7              :  * This library is free software; you can redistribute it and/or
       8              :  * modify it under the terms of the GNU Lesser General Public
       9              :  * License as published by the Free Software Foundation; either
      10              :  * version 2.1 of the License, or (at your option) any later version.
      11              : 
      12              :  * This library is distributed in the hope that it will be useful,
      13              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15              :  * Lesser General Public License for more details.
      16              : 
      17              :  * You should have received a copy of the GNU Lesser General Public
      18              :  * License along with this library; if not, write to the Free Software
      19              :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
      20              :  *
      21              :  * Authors:
      22              :  *      Raffaele Sandrini <raffaele@sandrini.ch>
      23              :  *      Jiří Zárevúcky <zarevucky.jiri@gmail.com>
      24              :  */
      25              : 
      26              : using GLib;
      27              : 
      28              : /**
      29              :  * Represents a lock statement.
      30              :  *
      31              :  * {{{ lock (foo); }}} or {{{ lock (foo) { ... } }}}
      32              :  *
      33              :  * If the statement is empty, the mutex remains locked until a corresponding
      34              :  * {@link Vala.UnlockStatement} occurs. Otherwise it's translated into a
      35              :  * try/finally statement which unlocks the mutex after the block is finished.
      36              :  */
      37           73 : public class Vala.LockStatement : CodeNode, Statement {
      38              :         /**
      39              :          * Expression representing the resource to be locked.
      40              :          */
      41              :         public Expression resource {
      42          306 :                 get { return _resource; }
      43           55 :                 private set {
      44          136 :                         _resource = value;
      45           55 :                         _resource.parent_node = this;
      46              :                 }
      47              :         }
      48              : 
      49              :         /**
      50              :          * The statement during its execution the resource is locked.
      51              :          */
      52              :         public Block? body {
      53          214 :                 get { return _body; }
      54           55 :                 private set {
      55           81 :                         _body = value;
      56           55 :                         if (_body != null) {
      57           26 :                                 _body.parent_node = this;
      58              :                         }
      59              :                 }
      60              :         }
      61              : 
      62           55 :         private Expression _resource;
      63           55 :         private Block _body;
      64              : 
      65          165 :         public LockStatement (Expression resource, Block? body, SourceReference? source_reference = null) {
      66           55 :                 this.body = body;
      67           55 :                 this.source_reference = source_reference;
      68           55 :                 this.resource = resource;
      69              :         }
      70              : 
      71           55 :         public override void accept (CodeVisitor visitor) {
      72           55 :                 resource.accept (visitor);
      73           55 :                 if (body != null) {
      74           26 :                         body.accept (visitor);
      75              :                 }
      76           55 :                 visitor.visit_lock_statement (this);
      77              :         }
      78              : 
      79            0 :         public override void replace_expression (Expression old_node, Expression new_node) {
      80            0 :                 if (resource == old_node) {
      81            0 :                         resource = new_node;
      82              :                 }
      83              :         }
      84              : 
      85           55 :         public override bool check (CodeContext context) {
      86           55 :                 if (body != null) {
      87           26 :                         if (!body.check (context)) {
      88            3 :                                 return false;
      89              :                         }
      90              : 
      91              :                         // if the statement isn't empty, it is converted into a try statement
      92           26 :                         var fin_body = new Block (source_reference);
      93           26 :                         fin_body.add_statement (new UnlockStatement (resource, source_reference));
      94              : 
      95           26 :                         var try_stmt = new TryStatement (body, fin_body, source_reference);
      96           27 :                         if (body.tree_can_fail) {
      97            1 :                                 var catch_body = new Block (source_reference);
      98            1 :                                 catch_body.add_statement (new ThrowStatement (new ReferenceTransferExpression (new MemberAccess.simple ("_lock_error_")), source_reference));
      99            1 :                                 var catch_clause = new CatchClause (new ErrorType (null, null), "_lock_error_", catch_body, source_reference);
     100            1 :                                 catch_clause.error_type.value_owned = true;
     101            1 :                                 try_stmt.add_catch_clause (catch_clause);
     102              :                         }
     103              : 
     104           26 :                         var block = new Block (source_reference);
     105           26 :                         block.add_statement (new LockStatement (resource, null, source_reference));
     106           26 :                         block.add_statement (try_stmt);
     107              : 
     108           26 :                         var parent_block = (Block) parent_node;
     109           26 :                         parent_block.replace_statement (this, block);
     110              : 
     111           26 :                         return block.check (context);
     112              :                 }
     113              : 
     114           29 :                 if (checked) {
     115            0 :                         return !error;
     116              :                 }
     117              : 
     118           29 :                 checked = true;
     119              : 
     120           29 :                 resource.check (context);
     121              : 
     122              :                 /* resource must be a member access and denote a Lockable */
     123           29 :                 if (!(resource is MemberAccess && resource.symbol_reference is Lockable)) {
     124            1 :                         error = true;
     125            1 :                         resource.error = true;
     126            1 :                         Report.error (resource.source_reference, "Expression is either not a member access or does not denote a lockable member");
     127            1 :                         return false;
     128              :                 }
     129              : 
     130              :                 /* parent symbol must be the current class */
     131           28 :                 if (resource.symbol_reference.parent_symbol != context.analyzer.current_class) {
     132            1 :                         error = true;
     133            1 :                         resource.error = true;
     134            1 :                         Report.error (resource.source_reference, "Only members of the current class are lockable");
     135            1 :                         return false;
     136              :                 }
     137              : 
     138              :                 /* parent class must not be compact */
     139           27 :                 if (context.analyzer.current_class.is_compact) {
     140            1 :                         error = true;
     141            1 :                         resource.error = true;
     142            1 :                         Report.error (resource.source_reference, "Only members of the non-compact classes are lockable");
     143            1 :                         return false;
     144              :                 }
     145              : 
     146           26 :                 ((Lockable) resource.symbol_reference).lock_used = true;
     147              : 
     148           26 :                 return !error;
     149              :         }
     150              : 
     151           26 :         public override void emit (CodeGenerator codegen) {
     152           26 :                 resource.emit (codegen);
     153           26 :                 codegen.visit_lock_statement (this);
     154              :         }
     155              : }
        

Generated by: LCOV version 2.0-1