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

            Line data    Source code
       1              : /* valasignal.vala
       2              :  *
       3              :  * Copyright (C) 2006-2012  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 an object signal. Signals enable objects to provide notifications.
      27              :  */
      28       276518 : public class Vala.Signal : Symbol, Callable {
      29              :         /**
      30              :          * The return type of handlers of this signal.
      31              :          */
      32              :         public DataType return_type {
      33       644109 :                 get { return _return_type; }
      34       160508 :                 set {
      35       289611 :                         _return_type = value;
      36       160508 :                         _return_type.parent_node = this;
      37              :                 }
      38              :         }
      39              : 
      40              :         public Block body {
      41       377368 :                 get { return _body; }
      42           14 :                 set {
      43           28 :                         _body = value;
      44           14 :                         if (_body != null) {
      45           14 :                                 _body.owner = scope;
      46              :                         }
      47              :                 }
      48              :         }
      49              : 
      50              :         /**
      51              :          * Specifies whether this signal has virtual method handler.
      52              :          */
      53       152782 :         public bool is_virtual { get; set; }
      54              : 
      55       273458 :         private List<Parameter> parameters = new ArrayList<Parameter> ();
      56              :         /**
      57              :          * Refers to the default signal handler, which is an anonymous
      58              :          * function in the scope.
      59              :          * */
      60       602635 :         public Method default_handler { get; private set; }
      61              : 
      62              :         /**
      63              :          * Refers to the public signal emitter method, which is an anonymous
      64              :          * function in the scope.
      65              :          * */
      66       173990 :         public Method emitter { get; private set; }
      67              : 
      68       136729 :         private DataType _return_type;
      69              : 
      70       136729 :         private Block _body;
      71              : 
      72              :         /**
      73              :          * Creates a new signal.
      74              :          *
      75              :          * @param name              signal name
      76              :          * @param return_type       signal return type
      77              :          * @param source_reference  reference to source code
      78              :          * @return                  newly created signal
      79              :          */
      80       410176 :         public Signal (string name, DataType return_type, SourceReference? source_reference = null, Comment? comment = null) {
      81       136729 :                 base (name, source_reference, comment);
      82       136729 :                 this.return_type = return_type;
      83              :         }
      84              : 
      85              :         /**
      86              :          * Appends parameter to signal handler.
      87              :          *
      88              :          * @param param a formal parameter
      89              :          */
      90       169091 :         public void add_parameter (Parameter param) {
      91       169091 :                 parameters.add (param);
      92       169091 :                 scope.add (param.name, param);
      93              :         }
      94              : 
      95          975 :         public unowned List<Parameter> get_parameters () {
      96          975 :                 return parameters;
      97              :         }
      98              : 
      99              :         /**
     100              :          * Returns generated delegate to be used for signal handlers.
     101              :          *
     102              :          * @return delegate
     103              :          */
     104          114 :         public Delegate get_delegate (DataType sender_type, CodeNode node_reference) {
     105          114 :                 var actual_return_type = return_type.get_actual_type (sender_type, null, node_reference);
     106              : 
     107          114 :                 var generated_delegate = new Delegate (null, actual_return_type, source_reference);
     108          114 :                 generated_delegate.access = SymbolAccessibility.PUBLIC;
     109          114 :                 generated_delegate.owner = scope;
     110              : 
     111              :                 // sender parameter is never null and doesn't own its value
     112          114 :                 var sender_param_type = sender_type.copy ();
     113          114 :                 sender_param_type.value_owned = false;
     114          114 :                 sender_param_type.nullable = false;
     115              : 
     116          114 :                 generated_delegate.sender_type = sender_param_type;
     117              : 
     118          114 :                 bool is_generic = actual_return_type.is_generic ();
     119              : 
     120          294 :                 foreach (Parameter param in parameters) {
     121           90 :                         var actual_param = param.copy ();
     122           90 :                         actual_param.variable_type = actual_param.variable_type.get_actual_type (sender_type, null, node_reference);
     123           90 :                         generated_delegate.add_parameter (actual_param);
     124              : 
     125           90 :                         if (actual_param.variable_type.is_generic ()) {
     126            2 :                                 is_generic = true;
     127              :                         }
     128              :                 }
     129              : 
     130          114 :                 if (is_generic) {
     131            6 :                         unowned ObjectTypeSymbol cl = (ObjectTypeSymbol) parent_symbol;
     132           26 :                         foreach (var type_param in cl.get_type_parameters ()) {
     133           10 :                                 generated_delegate.add_type_parameter (new TypeParameter (type_param.name, type_param.source_reference));
     134              :                         }
     135              : 
     136              :                         // return type and parameter types must refer to the delegate type parameters
     137              :                         // instead of to the class type parameters
     138           26 :                         foreach (var type_param in generated_delegate.get_type_parameters ()) {
     139           10 :                                 actual_return_type.replace_type_parameter (cl.get_type_parameters ().get (cl.get_type_parameter_index (type_param.name)), type_param);
     140              :                         }
     141           10 :                         foreach (var param in generated_delegate.get_parameters ()) {
     142            6 :                                 foreach (var type_param in generated_delegate.get_type_parameters ()) {
     143            2 :                                         param.variable_type.replace_type_parameter (cl.get_type_parameters ().get (cl.get_type_parameter_index (type_param.name)), type_param);
     144              :                                 }
     145              :                         }
     146              :                 }
     147              : 
     148          114 :                 scope.add (null, generated_delegate);
     149              : 
     150          114 :                 return generated_delegate;
     151              :         }
     152              : 
     153       304034 :         public override void accept (CodeVisitor visitor) {
     154       304034 :                 visitor.visit_signal (this);
     155              :         }
     156              : 
     157       215042 :         public override void accept_children (CodeVisitor visitor) {
     158       215042 :                 return_type.accept (visitor);
     159              : 
     160       744650 :                 foreach (Parameter param in parameters) {
     161       264804 :                         param.accept (visitor);
     162              :                 }
     163       215042 :                 if (default_handler == null && body != null) {
     164           11 :                         body.accept (visitor);
     165       215031 :                 } else if (default_handler != null) {
     166        75519 :                         default_handler.accept (visitor);
     167              :                 }
     168       215042 :                 if (emitter != null) {
     169        12761 :                         emitter.accept (visitor);
     170              :                 }
     171              :         }
     172              : 
     173        23768 :         public override void replace_type (DataType old_type, DataType new_type) {
     174        23768 :                 if (return_type == old_type) {
     175        23768 :                         return_type = new_type;
     176              :                 }
     177              :         }
     178              : 
     179       127576 :         public override bool check (CodeContext context) {
     180       127576 :                 if (checked) {
     181          204 :                         return !error;
     182              :                 }
     183              : 
     184       127372 :                 checked = true;
     185              : 
     186              :                 // parent_symbol may be null for dynamic signals
     187       127372 :                 unowned Class? parent_cl = parent_symbol as Class;
     188        93911 :                 if (parent_cl != null && parent_cl.is_compact) {
     189            1 :                         error = true;
     190            1 :                         Report.error (source_reference, "Signals are not supported in compact classes");
     191            1 :                         return false;
     192              :                 }
     193              : 
     194       127371 :                 if (parent_cl != null) {
     195       418808 :                         foreach (DataType base_type in parent_cl.get_base_types ()) {
     196       162450 :                                 if (SemanticAnalyzer.symbol_lookup_inherited (base_type.type_symbol, name) is Signal) {
     197            1 :                                         error = true;
     198            1 :                                         Report.error (source_reference, "Signals with the same name as a signal in a base type are not supported");
     199            1 :                                         return false;
     200              :                                 }
     201              :                         }
     202              :                 }
     203              : 
     204       127370 :                 if (this is DynamicSignal) {
     205           11 :                         return !error;
     206              :                 }
     207              : 
     208       127359 :                 return_type.check (context);
     209       127359 :                 if (!external_package) {
     210          103 :                         context.analyzer.check_type (return_type);
     211          103 :                         return_type.check_type_arguments (context, !(return_type is DelegateType));
     212              :                 }
     213              : 
     214       127359 :                 if (return_type.type_symbol == context.analyzer.va_list_type.type_symbol) {
     215            1 :                         error = true;
     216            1 :                         Report.error (source_reference, "`%s' not supported as return type", return_type.type_symbol.get_full_name ());
     217            1 :                         return false;
     218              :                 }
     219              : 
     220       441812 :                 foreach (Parameter param in parameters) {
     221       157227 :                         if (param.ellipsis) {
     222            0 :                                 Report.error  (param.source_reference, "Signals with variable argument lists are not supported");
     223            0 :                                 return false;
     224              :                         }
     225              : 
     226       157227 :                         if (!param.check (context)) {
     227            0 :                                 error = true;
     228              :                         }
     229              :                 }
     230              : 
     231       127358 :                 if (body != null || (is_virtual && external_package)) {
     232       110476 :                         default_handler = new Method (name, return_type, source_reference);
     233              : 
     234       110476 :                         default_handler.owner = owner;
     235       110476 :                         default_handler.access = (is_virtual ? access : SymbolAccessibility.PRIVATE);
     236       110476 :                         default_handler.external = external;
     237       110476 :                         default_handler.hides = hides;
     238       110476 :                         default_handler.is_virtual = is_virtual;
     239       110476 :                         default_handler.signal_reference = this;
     240       110476 :                         default_handler.body = body;
     241              : 
     242       383260 :                         foreach (Parameter param in parameters) {
     243       136392 :                                 default_handler.add_parameter (param);
     244              :                         }
     245              : 
     246       110476 :                         unowned ObjectTypeSymbol? cl = parent_symbol as ObjectTypeSymbol;
     247              : 
     248       110476 :                         cl.add_hidden_method (default_handler);
     249       110476 :                         default_handler.check (context);
     250              :                 }
     251              : 
     252       145971 :                 if (has_attribute ("HasEmitter")) {
     253        18613 :                         emitter = new Method (name, return_type, source_reference);
     254              : 
     255        18613 :                         emitter.owner = owner;
     256        18613 :                         emitter.access = access;
     257              : 
     258        18613 :                         var body = new Block (source_reference);
     259        18613 :                         var call = new MethodCall (new MemberAccess.simple (name, source_reference), source_reference);
     260              : 
     261        71505 :                         foreach (Parameter param in parameters) {
     262        26446 :                                 emitter.add_parameter (param);
     263        26446 :                                 call.add_argument (new MemberAccess.simple (param.name, source_reference));
     264              :                         }
     265              : 
     266        18613 :                         if (return_type is VoidType) {
     267        17017 :                                 body.add_statement (new ExpressionStatement (call, source_reference));
     268              :                         } else {
     269         1596 :                                 body.add_statement (new ReturnStatement (call, source_reference));
     270              :                         }
     271        18613 :                         emitter.body = body;
     272              : 
     273        18613 :                         unowned ObjectTypeSymbol? cl = parent_symbol as ObjectTypeSymbol;
     274              : 
     275        18613 :                         cl.add_hidden_method (emitter);
     276        18613 :                         if (!external_package) {
     277            4 :                                 emitter.check (context);
     278              :                         }
     279              :                 }
     280              : 
     281              : 
     282       127358 :                 if (!external_package && !hides && get_hidden_member () != null) {
     283            0 :                         Report.warning (source_reference, "%s hides inherited signal `%s'. Use the `new' keyword if hiding was intentional", get_full_name (), get_hidden_member ().get_full_name ());
     284              :                 }
     285              : 
     286       127358 :                 return !error;
     287              :         }
     288              : }
     289              : 
        

Generated by: LCOV version 2.0-1