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

            Line data    Source code
       1              : /* valacreationmethod.vala
       2              :  *
       3              :  * Copyright (C) 2007-2010  Jürg Billeter
       4              :  * Copyright (C) 2007-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              :  *      Raffaele Sandrini <raffaele@sandrini.ch>
      22              :  *      Jürg Billeter <j@bitron.ch>
      23              :  */
      24              : 
      25              : using GLib;
      26              : 
      27              : /**
      28              :  * Represents a type creation method.
      29              :  */
      30         1538 : public class Vala.CreationMethod : Method {
      31              :         /**
      32              :          * Specifies the name of the type this creation method belongs to.
      33              :          */
      34      2832087 :         public string class_name { get; set; }
      35              : 
      36              :         /**
      37              :          * Specifies whether this constructor chains up to a base
      38              :          * constructor or a different constructor of the same class.
      39              :          */
      40         4568 :         public bool chain_up { get; set; }
      41              : 
      42              :         /**
      43              :          * Creates a new method.
      44              :          *
      45              :          * @param name             method name
      46              :          * @param source_reference reference to source code
      47              :          * @return                 newly created method
      48              :          */
      49       566546 :         public CreationMethod (string? class_name, string? name, SourceReference? source_reference = null, Comment? comment = null) {
      50       566546 :                 base (name, new VoidType (), source_reference, comment);
      51       566546 :                 this.class_name = class_name;
      52              :         }
      53              : 
      54      1244520 :         public override void accept (CodeVisitor visitor) {
      55      1244520 :                 visitor.visit_creation_method (this);
      56              :         }
      57              : 
      58       884400 :         public override void accept_children (CodeVisitor visitor) {
      59      3938296 :                 foreach (Parameter param in get_parameters()) {
      60      1526948 :                         param.accept (visitor);
      61              :                 }
      62              : 
      63       884400 :                 if (error_types != null) {
      64       287019 :                         foreach (DataType error_type in error_types) {
      65        95673 :                                 error_type.accept (visitor);
      66              :                         }
      67              :                 }
      68              : 
      69       884412 :                 foreach (Expression precondition in get_preconditions ()) {
      70            6 :                         precondition.accept (visitor);
      71              :                 }
      72              : 
      73       884412 :                 foreach (Expression postcondition in get_postconditions ()) {
      74            6 :                         postcondition.accept (visitor);
      75              :                 }
      76              : 
      77       884400 :                 if (body != null) {
      78         6435 :                         body.accept (visitor);
      79              :                 }
      80              :         }
      81              : 
      82       532664 :         public override bool check (CodeContext context) {
      83       532664 :                 if (checked) {
      84         7398 :                         return !error;
      85              :                 }
      86              : 
      87       525266 :                 checked = true;
      88              : 
      89       525266 :                 if (class_name != null && class_name != parent_symbol.name) {
      90              :                         // class_name is null for constructors generated by GIdlParser
      91            0 :                         Report.error (source_reference, "missing return type in method `%s.%s´", context.analyzer.current_symbol.get_full_name (), class_name);
      92            0 :                         error = true;
      93            0 :                         return false;
      94              :                 }
      95              : 
      96       525266 :                 if (this_parameter != null) {
      97       525266 :                         this_parameter.check (context);
      98              :                 }
      99              : 
     100       525266 :                 if (coroutine && !external_package && !context.has_package ("gio-2.0")) {
     101            0 :                         error = true;
     102            0 :                         Report.error (source_reference, "gio-2.0 package required for async constructors");
     103            0 :                         return false;
     104              :                 }
     105              : 
     106       525266 :                 var old_source_file = context.analyzer.current_source_file;
     107       526985 :                 var old_symbol = context.analyzer.current_symbol;
     108              : 
     109       525266 :                 if (source_reference != null) {
     110       525266 :                         context.analyzer.current_source_file = source_reference.file;
     111              :                 }
     112       525266 :                 context.analyzer.current_symbol = this;
     113              : 
     114       525266 :                 int i = 0;
     115      2342275 :                 foreach (Parameter param in get_parameters()) {
     116       908505 :                         if (!param.check (context)) {
     117            1 :                                 error = true;
     118              :                         }
     119       908505 :                         if (i == 0 && param.ellipsis && body != null) {
     120            1 :                                 error = true;
     121            1 :                                 Report.error (param.source_reference, "Named parameter required before `...'");
     122              :                         }
     123       908505 :                         i++;
     124              : 
     125              :                         // Add local variable to provide access to params arrays which will be constructed out of the given va-args
     126       908513 :                         if (param.params_array && body != null) {
     127            9 :                                 if (params_array_var != null) {
     128            1 :                                         error = true;
     129            1 :                                         Report.error (param.source_reference, "Only one params-array parameter is allowed");
     130            1 :                                         continue;
     131              :                                 }
     132            8 :                                 if (!context.experimental) {
     133            8 :                                         Report.warning (param.source_reference, "Support of params-arrays is experimental");
     134              :                                 }
     135            8 :                                 var type = (ArrayType) param.variable_type.copy ();
     136            8 :                                 type.element_type.value_owned = type.value_owned;
     137            8 :                                 type.value_owned = true;
     138            8 :                                 if (type.element_type.is_real_struct_type () && !type.element_type.nullable) {
     139            1 :                                         error = true;
     140            1 :                                         Report.error (param.source_reference, "Only nullable struct elements are supported in params-array");
     141              :                                 }
     142            8 :                                 if (type.length != null) {
     143            1 :                                         error = true;
     144            1 :                                         Report.error (param.source_reference, "Passing length to params-array is not supported yet");
     145              :                                 }
     146            8 :                                 params_array_var = new LocalVariable (type, param.name, null, param.source_reference);
     147            8 :                                 body.insert_statement (0, new DeclarationStatement (params_array_var, param.source_reference));
     148              :                         }
     149              :                 }
     150              : 
     151       525266 :                 if (error_types != null) {
     152       169720 :                         foreach (DataType error_type in error_types) {
     153        56574 :                                 error_type.check (context);
     154              : 
     155              :                                 // check whether error type is at least as accessible as the creation method
     156        56574 :                                 if (!error_type.is_accessible (this)) {
     157            1 :                                         error = true;
     158            1 :                                         Report.error (source_reference, "error type `%s' is less accessible than creation method `%s'", error_type.to_string (), get_full_name ());
     159            1 :                                         return false;
     160              :                                 }
     161              :                         }
     162              :                 }
     163              : 
     164       525269 :                 foreach (Expression precondition in get_preconditions ()) {
     165            2 :                         precondition.check (context);
     166              :                 }
     167              : 
     168       525269 :                 foreach (Expression postcondition in get_postconditions ()) {
     169            2 :                         postcondition.check (context);
     170              :                 }
     171              : 
     172       525265 :                 if (body != null) {
     173         2604 :                         body.check (context);
     174              : 
     175         2604 :                         unowned Class? cl = parent_symbol as Class;
     176              : 
     177              :                         // ensure we chain up to base constructor
     178         2604 :                         if (!chain_up && cl != null && cl.base_class != null) {
     179          592 :                                 if (context.profile == Profile.GOBJECT
     180          575 :                                     && cl.base_class.default_construction_method != null
     181          575 :                                     && !cl.base_class.default_construction_method.has_construct_function) {
     182              :                                         // directly chain up to Object
     183           17 :                                         var old_insert_block = context.analyzer.insert_block;
     184           17 :                                         context.analyzer.current_symbol = body;
     185           34 :                                         context.analyzer.insert_block = body;
     186              : 
     187           17 :                                         var stmt = new ExpressionStatement (new MethodCall (new MemberAccess (new MemberAccess.simple ("GLib", source_reference), "Object", source_reference), source_reference), source_reference);
     188           17 :                                         body.insert_statement (0, stmt);
     189           17 :                                         stmt.check (context);
     190              : 
     191           17 :                                         context.analyzer.current_symbol = this;
     192           17 :                                         context.analyzer.insert_block = old_insert_block;
     193          558 :                                 } else if (cl.base_class.default_construction_method == null
     194          558 :                                     || cl.base_class.default_construction_method.access == SymbolAccessibility.PRIVATE) {
     195            1 :                                         Report.error (source_reference, "unable to chain up to private base constructor");
     196         1113 :                                 } else if (cl.base_class.default_construction_method.get_required_arguments () > 0) {
     197            1 :                                         Report.error (source_reference, "unable to chain up to base constructor requiring arguments");
     198              :                                 } else {
     199          556 :                                         var old_insert_block = context.analyzer.insert_block;
     200          556 :                                         context.analyzer.current_symbol = body;
     201         1112 :                                         context.analyzer.insert_block = body;
     202              : 
     203          556 :                                         var base_call = new MethodCall (new BaseAccess (source_reference), source_reference);
     204          556 :                                         if (coroutine && cl.base_class.default_construction_method.coroutine) {
     205            0 :                                                 base_call.is_yield_expression = true;
     206              :                                         }
     207          556 :                                         var stmt = new ExpressionStatement (base_call, source_reference);
     208          556 :                                         body.insert_statement (0, stmt);
     209          556 :                                         stmt.check (context);
     210              : 
     211          556 :                                         context.analyzer.current_symbol = this;
     212          653 :                                         context.analyzer.insert_block = old_insert_block;
     213              :                                 }
     214              :                         }
     215              :                 }
     216              : 
     217       525265 :                 context.analyzer.current_source_file = old_source_file;
     218       525265 :                 context.analyzer.current_symbol = old_symbol;
     219              : 
     220              :                 // check that all errors that can be thrown in the method body are declared
     221       527863 :                 if (body != null && !body.error) {
     222         2598 :                         var body_errors = new ArrayList<DataType> ();
     223         2598 :                         body.get_error_types (body_errors);
     224         5442 :                         foreach (DataType body_error_type in body_errors) {
     225         1422 :                                 bool can_propagate_error = false;
     226         1422 :                                 if (error_types != null) {
     227         4263 :                                         foreach (DataType method_error_type in error_types) {
     228         1421 :                                                 if (body_error_type.compatible (method_error_type)) {
     229         1421 :                                                         can_propagate_error = true;
     230              :                                                 }
     231              :                                         }
     232              :                                 }
     233         1422 :                                 if (!can_propagate_error && !((ErrorType) body_error_type).dynamic_error) {
     234            1 :                                         Report.warning (body_error_type.source_reference, "unhandled error `%s'", body_error_type.to_string());
     235              :                                 }
     236              :                         }
     237              :                 }
     238              : 
     239       525265 :                 return !error;
     240              :         }
     241              : }
        

Generated by: LCOV version 2.0-1