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

            Line data    Source code
       1              : /* valaproperty.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              :  *      Raffaele Sandrini <raffaele@sandrini.ch>
      22              :  */
      23              : 
      24              : using GLib;
      25              : 
      26              : /**
      27              :  * Represents a property declaration in the source code.
      28              :  */
      29       452507 : public class Vala.Property : Symbol, Lockable {
      30              :         /**
      31              :          * The property type.
      32              :          */
      33              :         public DataType? property_type {
      34      2680443 :                 get { return _data_type; }
      35       852084 :                 set {
      36      3381524 :                         _data_type = value;
      37       852084 :                         if (value != null) {
      38       852025 :                                 _data_type.parent_node = this;
      39              :                         }
      40              :                 }
      41              :         }
      42              : 
      43              :         /**
      44              :          * The get accessor of this property if available.
      45              :          */
      46              :         public PropertyAccessor? get_accessor {
      47      4121638 :                 get { return _get_accessor; }
      48       870923 :                 set {
      49      1292415 :                         _get_accessor = value;
      50       870923 :                         if (value != null) {
      51       421492 :                                 value.owner = scope;
      52              :                         }
      53              :                 }
      54              :         }
      55              : 
      56              :         /**
      57              :          * The set/construct accessor of this property if available.
      58              :          */
      59              :         public PropertyAccessor? set_accessor {
      60      3763726 :                 get { return _set_accessor; }
      61       784742 :                 set {
      62      1120053 :                         _set_accessor = value;
      63       784742 :                         if (value != null) {
      64       335311 :                                 value.owner = scope;
      65              :                         }
      66              :                 }
      67              :         }
      68              : 
      69              :         /**
      70              :          * Represents the generated `this` parameter in this property.
      71              :          */
      72      2257100 :         public Parameter? this_parameter { get; set; }
      73              : 
      74              :         /**
      75              :          * Specifies whether automatic accessor code generation should be
      76              :          * disabled.
      77              :          */
      78         2457 :         public bool interface_only { get; set; }
      79              : 
      80              :         /**
      81              :          * Specifies whether this property is abstract. Abstract properties have
      82              :          * no accessor bodies, may only be specified within abstract classes and
      83              :          * interfaces, and must be overridden by derived non-abstract classes.
      84              :          */
      85      1728094 :         public bool is_abstract { get; set; }
      86              : 
      87              :         /**
      88              :          * Specifies whether this property is virtual. Virtual properties may be
      89              :          * overridden by derived classes.
      90              :          */
      91      1185103 :         public bool is_virtual { get; set; }
      92              : 
      93              :         /**
      94              :          * Specifies whether this property overrides a virtual or abstract
      95              :          * property of a base type.
      96              :          */
      97       688143 :         public bool overrides { get; set; }
      98              : 
      99              :         /**
     100              :          * Reference the Field that holds this property
     101              :          */
     102              :         public Field? field {
     103       869084 :                 get {
     104       869084 :                         if (!_field_checked) {
     105       449363 :                                 if (!is_abstract && source_type == SourceFileType.SOURCE) {
     106          687 :                                         bool has_get = (get_accessor != null);
     107          687 :                                         bool get_has_body = (has_get && get_accessor.body != null);
     108          687 :                                         bool has_set = (set_accessor != null);
     109          687 :                                         bool set_has_body = (has_set && set_accessor.body != null);
     110          535 :                                         if (set_has_body && (has_get && !get_has_body)) {
     111            1 :                                                 error = true;
     112            1 :                                                 Report.error (source_reference, "Property getter must have a body");
     113              :                                         }
     114          687 :                                         if (get_has_body && (has_set && !set_has_body)) {
     115            1 :                                                 error = true;
     116            1 :                                                 Report.error (source_reference, "Property setter must have a body");
     117              :                                         }
     118          687 :                                         if (!get_has_body && !set_has_body) {
     119          505 :                                                 if (has_attribute ("GtkChild") && property_type.value_owned) {
     120            1 :                                                         Report.warning (source_reference, "[GtkChild] properties must be declared as `unowned'");
     121            1 :                                                         property_type.value_owned = false;
     122              :                                                 }
     123              : 
     124              :                                                 /* automatic property accessor body generation */
     125          505 :                                                 _field = new Field ("_%s".printf (name), property_type.copy (), initializer, source_reference);
     126          505 :                                                 _field.access = SymbolAccessibility.PRIVATE;
     127          505 :                                                 _field.binding = binding;
     128              :                                                 // apply gtk-child attribute to backing field for gtk-template support
     129          505 :                                                 if (has_attribute ("GtkChild")) {
     130            3 :                                                         _field.set_attribute_string ("GtkChild", "name", get_attribute_string ("GtkChild", "name", name));
     131            3 :                                                         _field.set_attribute_bool ("GtkChild", "internal", get_attribute_bool ("GtkChild", "internal"));
     132              :                                                 }
     133              :                                                 // Inherit important attributes
     134          505 :                                                 _field.copy_attribute_bool (this, "CCode", "array_length");
     135          505 :                                                 _field.copy_attribute_string (this, "CCode", "array_length_type");
     136          505 :                                                 _field.copy_attribute_bool (this, "CCode", "array_null_terminated");
     137          505 :                                                 _field.copy_attribute_bool (this, "CCode", "delegate_target");
     138              :                                         }
     139              :                                 }
     140       449363 :                                 _field_checked = true;
     141              :                         }
     142       869084 :                         return _field;
     143              :                 }
     144              :         }
     145              : 
     146              :         /**
     147              :          * Specifies whether this field may only be accessed with an instance of
     148              :          * the contained type.
     149              :          */
     150      1238179 :         public MemberBinding binding { get; set; default = MemberBinding.INSTANCE; }
     151              : 
     152              :         /**
     153              :          * The nick of this property
     154              :          */
     155              :         public string nick {
     156          371 :                 get {
     157          371 :                         if (_nick == null) {
     158          371 :                                 _nick = get_attribute_string ("Description", "nick");
     159          371 :                                 if (_nick == null) {
     160          370 :                                         _nick = name.replace ("_", "-");
     161              :                                 }
     162              :                         }
     163          371 :                         return _nick;
     164              :                 }
     165              :         }
     166              : 
     167              :         /**
     168              :          * The blurb of this property
     169              :          */
     170              :         public string blurb {
     171          371 :                 get {
     172          371 :                         if (_blurb == null) {
     173          371 :                                 _blurb = get_attribute_string ("Description", "blurb");
     174          371 :                                 if (_blurb == null) {
     175          370 :                                         _blurb = name.replace ("_", "-");
     176              :                                 }
     177              :                         }
     178          371 :                         return _blurb;
     179              :                 }
     180              :         }
     181              : 
     182              :         /**
     183              :          * Specifies whether this a property triggers a notify.
     184              :          */
     185              :         public bool notify {
     186          994 :                 get {
     187          994 :                         if (_notify == null) {
     188          746 :                                 _notify = get_attribute_bool ("CCode", "notify", true);
     189              :                         }
     190          994 :                         return _notify;
     191              :                 }
     192              :         }
     193              : 
     194              :         /**
     195              :          * Specifies the virtual or abstract property this property overrides.
     196              :          * Reference must be weak as virtual properties set base_property to
     197              :          * themselves.
     198              :          */
     199              :         public Property base_property {
     200        58597 :                 get {
     201        58597 :                         find_base_properties ();
     202        58597 :                         return _base_property;
     203              :                 }
     204              :         }
     205              : 
     206              :         /**
     207              :          * Specifies the abstract interface property this property implements.
     208              :          */
     209              :         public Property base_interface_property {
     210       254194 :                 get {
     211       254194 :                         find_base_properties ();
     212       254194 :                         return _base_interface_property;
     213              :                 }
     214              :         }
     215              : 
     216              :         /**
     217              :          * Specifies the default value of this property.
     218              :          */
     219              :         public Expression initializer {
     220      1965569 :                 get {
     221      1965569 :                         return _initializer;
     222              :                 }
     223           42 :                 set {
     224           84 :                         _initializer = value;
     225           42 :                         _initializer.parent_node = this;
     226              :                 }
     227              :         }
     228              : 
     229         1288 :         public bool lock_used { get; set; }
     230              : 
     231       449431 :         private Expression _initializer;
     232              : 
     233       449431 :         private DataType _data_type;
     234              : 
     235              :         private weak Property _base_property;
     236              :         private weak Property _base_interface_property;
     237              :         private bool base_properties_valid;
     238       449431 :         PropertyAccessor? _get_accessor;
     239       449431 :         PropertyAccessor? _set_accessor;
     240       449431 :         private string? _nick;
     241       449431 :         private string? _blurb;
     242       449431 :         private bool? _notify;
     243       449431 :         private Field? _field;
     244              :         private bool _field_checked;
     245              : 
     246              :         /**
     247              :          * Creates a new property.
     248              :          *
     249              :          * @param name              property name
     250              :          * @param property_type     property type
     251              :          * @param get_accessor      get accessor
     252              :          * @param set_accessor      set/construct accessor
     253              :          * @param source_reference  reference to source code
     254              :          * @return                  newly created property
     255              :          */
     256      1348234 :         public Property (string name, DataType? property_type, PropertyAccessor? get_accessor, PropertyAccessor? set_accessor, SourceReference? source_reference = null, Comment? comment = null) {
     257       449431 :                 base (name, source_reference, comment);
     258       449431 :                 this.property_type = property_type;
     259       449431 :                 this.get_accessor = get_accessor;
     260       449431 :                 this.set_accessor = set_accessor;
     261              :         }
     262              : 
     263       998631 :         public override void accept (CodeVisitor visitor) {
     264       998631 :                 visitor.visit_property (this);
     265              :         }
     266              : 
     267       710270 :         public override void accept_children (CodeVisitor visitor) {
     268       710270 :                 property_type.accept (visitor);
     269              : 
     270       710270 :                 if (get_accessor != null) {
     271       666685 :                         get_accessor.accept (visitor);
     272              :                 }
     273       710270 :                 if (set_accessor != null) {
     274       531737 :                         set_accessor.accept (visitor);
     275              :                 }
     276              : 
     277       710270 :                 if (initializer != null) {
     278           77 :                         initializer.accept (visitor);
     279              :                 }
     280              :         }
     281              : 
     282              :         /**
     283              :          * Checks whether the accessors of this property are compatible
     284              :          * with the specified base property.
     285              :          *
     286              :          * @param base_property a property
     287              :          * @param invalid_match error string about which check failed
     288              :          * @return true if the specified property is compatible to this property
     289              :          */
     290          310 :         public bool compatible (Property base_property, out string? invalid_match) {
     291          310 :                 if ((get_accessor == null && base_property.get_accessor != null) ||
     292          310 :                     (get_accessor != null && base_property.get_accessor == null)) {
     293            1 :                         invalid_match = "incompatible get accessor";
     294            1 :                         return false;
     295              :                 }
     296              : 
     297          309 :                 if ((set_accessor == null && base_property.set_accessor != null) ||
     298          309 :                     (set_accessor != null && base_property.set_accessor == null)) {
     299            0 :                         invalid_match = "incompatible set accessor";
     300            0 :                         return false;
     301              :                 }
     302              : 
     303          309 :                 var object_type = SemanticAnalyzer.get_data_type_for_symbol (parent_symbol);
     304              : 
     305          614 :                 if (get_accessor != null) {
     306              :                         // check accessor value_type instead of property_type
     307              :                         // due to possible ownership differences
     308          309 :                         var actual_base_type = base_property.get_accessor.value_type.get_actual_type (object_type, null, this);
     309          309 :                         if (!actual_base_type.equals (get_accessor.value_type)) {
     310            4 :                                 invalid_match = "incompatible get accessor type";
     311            4 :                                 return false;
     312              :                         }
     313              :                 }
     314              : 
     315          397 :                 if (set_accessor != null) {
     316              :                         // check accessor value_type instead of property_type
     317              :                         // due to possible ownership differences
     318           93 :                         var actual_base_type = base_property.set_accessor.value_type.get_actual_type (object_type, null, this);
     319           93 :                         if (!actual_base_type.equals (set_accessor.value_type)) {
     320            0 :                                 invalid_match = "incompatible set accessor type";
     321            0 :                                 return false;
     322              :                         }
     323              : 
     324           93 :                         if (set_accessor.writable != base_property.set_accessor.writable) {
     325            1 :                                 invalid_match = "incompatible set accessor";
     326            1 :                                 return false;
     327              :                         }
     328           92 :                         if (set_accessor.construction != base_property.set_accessor.construction) {
     329            0 :                                 invalid_match = "incompatible set accessor";
     330            0 :                                 return false;
     331              :                         }
     332              :                 }
     333              : 
     334          304 :                 invalid_match = null;
     335          304 :                 return true;
     336              :         }
     337              : 
     338       402632 :         public override void replace_type (DataType old_type, DataType new_type) {
     339       402632 :                 if (property_type == old_type) {
     340       402632 :                         property_type = new_type;
     341              :                 }
     342              :         }
     343              : 
     344            0 :         public override void replace_expression (Expression old_node, Expression new_node) {
     345            0 :                 if (initializer == old_node) {
     346            0 :                         initializer = new_node;
     347              :                 }
     348              :         }
     349              : 
     350       312791 :         private void find_base_properties () {
     351       312791 :                 if (base_properties_valid) {
     352              :                         return;
     353              :                 }
     354              : 
     355       196370 :                 if (parent_symbol is Class) {
     356       196267 :                         find_base_interface_property ((Class) parent_symbol);
     357       196267 :                         if (is_virtual || overrides) {
     358          236 :                                 find_base_class_property ((Class) parent_symbol);
     359              :                         }
     360          103 :                 } else if (parent_symbol is Interface) {
     361           93 :                         if (is_virtual || is_abstract) {
     362           49 :                                 _base_interface_property = this;
     363              :                         }
     364              :                 }
     365              : 
     366       196370 :                 base_properties_valid = true;
     367              :         }
     368              : 
     369         1000 :         private void find_base_class_property (Class cl) {
     370          616 :                 var sym = cl.scope.lookup (name);
     371          837 :                 if (sym is Property) {
     372          453 :                         var base_property = (Property) sym;
     373          453 :                         if (base_property.is_abstract || base_property.is_virtual) {
     374              :                                 string invalid_match;
     375          232 :                                 if (!compatible (base_property, out invalid_match)) {
     376            1 :                                         error = true;
     377            1 :                                         Report.error (source_reference, "Type and/or accessors of overriding property `%s' do not match overridden property `%s': %s.", get_full_name (), base_property.get_full_name (), invalid_match);
     378            1 :                                         return;
     379              :                                 }
     380              : 
     381          231 :                                 _base_property = base_property;
     382          231 :                                 return;
     383              :                         }
     384              :                 }
     385              : 
     386          384 :                 if (cl.base_class != null) {
     387          380 :                         find_base_class_property (cl.base_class);
     388              :                 }
     389              :         }
     390              : 
     391       196267 :         private void find_base_interface_property (Class cl) {
     392              :                 // FIXME report error if multiple possible base properties are found
     393       957371 :                 foreach (DataType type in cl.get_base_types ()) {
     394       566549 :                         if (type.type_symbol is Interface) {
     395       185997 :                                 var sym = type.type_symbol.scope.lookup (name);
     396       185997 :                                 if (sym is Property) {
     397           38 :                                         var base_property = (Property) sym;
     398           38 :                                         if (base_property.is_abstract || base_property.is_virtual) {
     399              :                                                 string invalid_match;
     400           38 :                                                 if (!compatible (base_property, out invalid_match)) {
     401            1 :                                                         error = true;
     402            1 :                                                         Report.error (source_reference, "Type and/or accessors of overriding property `%s' do not match overridden property `%s': %s.", get_full_name (), base_property.get_full_name (), invalid_match);
     403            1 :                                                         return;
     404              :                                                 }
     405              : 
     406           37 :                                                 _base_interface_property = base_property;
     407           37 :                                                 return;
     408              :                                         }
     409              :                                 }
     410              :                         }
     411              :                 }
     412              :         }
     413              : 
     414       490790 :         public override bool check (CodeContext context) {
     415       490790 :                 if (checked) {
     416        72677 :                         return !error;
     417              :                 }
     418              : 
     419       418113 :                 checked = true;
     420              : 
     421       836202 :                 if (context.profile == Profile.GOBJECT && parent_symbol is ObjectTypeSymbol
     422       418089 :                     && ((ObjectTypeSymbol) parent_symbol).is_subtype_of (context.analyzer.object_type)) {
     423       400916 :                         if (!is_valid_name (name)) {
     424            2 :                                 error = true;
     425            2 :                                 Report.error (source_reference, "Name `%s' is not valid for a GLib.Object property", name);
     426              :                         }
     427              :                 }
     428              : 
     429       418113 :                 if (this_parameter != null) {
     430       418104 :                         this_parameter.check (context);
     431              :                 }
     432              : 
     433       421040 :                 if (parent_symbol is Class && (is_abstract || is_virtual)) {
     434         2929 :                         var cl = (Class) parent_symbol;
     435         2929 :                         if (cl.is_compact && cl.base_class != null) {
     436            1 :                                 error = true;
     437            1 :                                 Report.error (source_reference, "Abstract and virtual properties may not be declared in derived compact classes");
     438            1 :                                 return false;
     439              :                         }
     440         2928 :                         if (cl.is_opaque) {
     441            1 :                                 error = true;
     442            1 :                                 Report.error (source_reference, "Abstract and virtual properties may not be declared in opaque compact classes");
     443            1 :                                 return false;
     444              :                         }
     445              :                 }
     446              : 
     447       418111 :                 if (is_abstract) {
     448        50426 :                         if (parent_symbol is Class) {
     449         2853 :                                 var cl = (Class) parent_symbol;
     450         2853 :                                 if (!cl.is_abstract) {
     451            1 :                                         error = true;
     452            1 :                                         Report.error (source_reference, "Abstract properties may not be declared in non-abstract classes");
     453            1 :                                         return false;
     454              :                                 }
     455        44721 :                         } else if (!(parent_symbol is Interface)) {
     456            1 :                                 error = true;
     457            1 :                                 Report.error (source_reference, "Abstract properties may not be declared outside of classes and interfaces");
     458            1 :                                 return false;
     459              :                         }
     460       370537 :                 } else if (is_virtual) {
     461           77 :                         if (!(parent_symbol is Class) && !(parent_symbol is Interface)) {
     462            1 :                                 error = true;
     463            1 :                                 Report.error (source_reference, "Virtual properties may not be declared outside of classes and interfaces");
     464            1 :                                 return false;
     465              :                         }
     466       370460 :                 } else if (overrides) {
     467          220 :                         if (!(parent_symbol is Class)) {
     468            1 :                                 error = true;
     469            1 :                                 Report.error (source_reference, "Properties may not be overridden outside of classes");
     470            1 :                                 return false;
     471              :                         }
     472       370240 :                 } else if (access == SymbolAccessibility.PROTECTED) {
     473            2 :                         if (!(parent_symbol is Class) && !(parent_symbol is Interface)) {
     474            1 :                                 error = true;
     475            1 :                                 Report.error (source_reference, "Protected properties may not be declared outside of classes and interfaces");
     476            1 :                                 return false;
     477              :                         }
     478              :                 }
     479              : 
     480       418106 :                 var old_source_file = context.analyzer.current_source_file;
     481       418106 :                 var old_symbol = context.analyzer.current_symbol;
     482              : 
     483       418106 :                 if (source_reference != null) {
     484       418106 :                         context.analyzer.current_source_file = source_reference.file;
     485              :                 }
     486       418106 :                 context.analyzer.current_symbol = this;
     487              : 
     488       418106 :                 if (property_type is VoidType) {
     489            1 :                         error = true;
     490            1 :                         Report.error (source_reference, "'void' not supported as property type");
     491            1 :                         return false;
     492              :                 }
     493              : 
     494       418105 :                 if (field != null) {
     495          490 :                         field.check (context);
     496              :                 }
     497              : 
     498       418105 :                 property_type.check (context);
     499       418105 :                 if (!external_package) {
     500          722 :                         context.analyzer.check_type (property_type);
     501          722 :                         property_type.check_type_arguments (context, true);
     502              :                 }
     503              : 
     504       418105 :                 if (get_accessor == null && set_accessor == null) {
     505            2 :                         error = true;
     506            2 :                         Report.error (source_reference, "Property `%s' must have a `get' accessor and/or a `set' mutator", get_full_name ());
     507            2 :                         return false;
     508              :                 }
     509              : 
     510       418103 :                 if (get_accessor != null) {
     511       392263 :                         get_accessor.check (context);
     512              :                 }
     513       418103 :                 if (set_accessor != null) {
     514       312370 :                         if (has_attribute ("GtkChild")) {
     515            1 :                                 Report.warning (set_accessor.source_reference, "[GtkChild] property `%s' is not allowed to have `set' accessor", get_full_name ());
     516              :                         }
     517       312370 :                         set_accessor.check (context);
     518              :                 }
     519              : 
     520       418103 :                 if (initializer != null && field == null && !is_abstract) {
     521            3 :                         Report.error (source_reference, "Property `%s' with custom `get' accessor and/or `set' mutator cannot have `default' value", get_full_name ());
     522              :                 }
     523              : 
     524       418103 :                 if (initializer != null) {
     525           41 :                         initializer.check (context);
     526              :                 }
     527              : 
     528              :                 // check whether property type is at least as accessible as the property
     529       418103 :                 if (!property_type.is_accessible (this)) {
     530            1 :                         error = true;
     531            1 :                         Report.error (source_reference, "property type `%s' is less accessible than property `%s'", property_type.to_string (), get_full_name ());
     532              :                 }
     533              : 
     534       418103 :                 if (overrides && base_property == null && base_interface_property == null) {
     535            3 :                         Report.error (source_reference, "%s: no suitable property found to override", get_full_name ());
     536              :                 }
     537              : 
     538       418103 :                 if (!external_package && !overrides && !hides && get_hidden_member () != null) {
     539            0 :                         Report.warning (source_reference, "%s hides inherited property `%s'. Use the `new' keyword if hiding was intentional", get_full_name (), get_hidden_member ().get_full_name ());
     540              :                 }
     541              : 
     542              :                 /* construct properties must be public */
     543       418103 :                 if (set_accessor != null && set_accessor.construction) {
     544       204704 :                         if (access != SymbolAccessibility.PUBLIC) {
     545            1 :                                 error = true;
     546            1 :                                 Report.error (source_reference, "%s: construct properties must be public", get_full_name ());
     547              :                         }
     548              :                 }
     549              : 
     550       418103 :                 if (initializer != null && !initializer.error && initializer.value_type != null && !(initializer.value_type.compatible (property_type))) {
     551            1 :                         error = true;
     552            1 :                         Report.error (initializer.source_reference, "Expected initializer of type `%s' but got `%s'", property_type.to_string (), initializer.value_type.to_string ());
     553              :                 }
     554              : 
     555       418103 :                 context.analyzer.current_source_file = old_source_file;
     556       418103 :                 context.analyzer.current_symbol = old_symbol;
     557              : 
     558       418103 :                 return !error;
     559              :         }
     560              : 
     561              :         // Ported from glib's "g_param_spec_is_valid_name"
     562       400916 :         static bool is_valid_name (string name) {
     563              :                 char* p;
     564              : 
     565       801830 :                 if ((name[0] < 'A' || name[0] > 'Z')
     566       400916 :                     && (name[0] < 'a' || name[0] > 'z')) {
     567            2 :                         return false;
     568              :                 }
     569              : 
     570      4754576 :                 for (p = name; *p != '\0'; p++) {
     571      4353662 :                         char c = *p;
     572      8389282 :                         if (c != '-' && c != '_' && (c < '0' || c > '9')
     573      4035620 :                             && (c < 'A' || c > 'Z') && (c < 'a' || c > 'z')) {
     574            2 :                                 return false;
     575              :                         }
     576              :                 }
     577              : 
     578       400916 :                 return true;
     579              :         }
     580              : }
        

Generated by: LCOV version 2.0-1