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

            Line data    Source code
       1              : /* valadatatype.vala
       2              :  *
       3              :  * Copyright (C) 2006-2010  Jürg Billeter
       4              :  * Copyright (C) 2006-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              :  *      Jürg Billeter <j@bitron.ch>
      22              :  *      Raffaele Sandrini <raffaele@sandrini.ch>
      23              :  */
      24              : 
      25              : using GLib;
      26              : 
      27              : /**
      28              :  * A reference to a data type. This is used to specify static types of
      29              :  * expressions.
      30              :  */
      31     78777389 : public abstract class Vala.DataType : CodeNode {
      32              :         /**
      33              :          * Specifies that the expression or variable owns the value.
      34              :          */
      35     79513488 :         public bool value_owned { get; set; }
      36              : 
      37              :         /**
      38              :          * Specifies that the expression may be null.
      39              :          */
      40     76691479 :         public bool nullable { get; set; }
      41              : 
      42              :         /**
      43              :          * The referred symbol.
      44              :          */
      45     41463267 :         public weak Symbol? symbol { get; private set; }
      46              : 
      47              :         /**
      48              :          * The referred symbol in the current context.
      49              :          */
      50        98045 :         public weak Symbol? context_symbol { get; set; }
      51              : 
      52              :         /**
      53              :          * The referred type symbol.
      54              :          */
      55              :         public weak TypeSymbol? type_symbol {
      56    214509992 :                 get {
      57    214509992 :                         return symbol as TypeSymbol;
      58              :                 }
      59              :         }
      60              : 
      61              :         /**
      62              :          * Specifies that the expression transfers a floating reference.
      63              :          */
      64     13199174 :         public bool floating_reference { get; set; }
      65              : 
      66              :         /**
      67              :          * Specifies that the type supports dynamic lookup.
      68              :          */
      69     59920181 :         public bool is_dynamic { get; set; }
      70              : 
      71     56053671 :         private List<DataType> type_argument_list;
      72              :         private static List<DataType> _empty_type_list;
      73              : 
      74     33331498 :         protected DataType.with_symbol (Symbol? symbol, SourceReference? source_reference = null) {
      75     33331498 :                 this.symbol = symbol;
      76     33331498 :                 this.source_reference = source_reference;
      77              :         }
      78              : 
      79              :         /**
      80              :          * Appends the specified type as generic type argument.
      81              :          *
      82              :          * @param arg a type reference
      83              :          */
      84      2355486 :         public void add_type_argument (DataType arg) {
      85      2355486 :                 if (type_argument_list == null) {
      86      2127305 :                         type_argument_list = new ArrayList<DataType> ();
      87              :                 }
      88      2355486 :                 type_argument_list.add (arg);
      89      2355486 :                 arg.parent_node = this;
      90              :         }
      91              : 
      92              :         /**
      93              :          * Returns the list of generic type arguments.
      94              :          *
      95              :          * @return type argument list
      96              :          */
      97    120944466 :         public unowned List<DataType> get_type_arguments () {
      98    120944466 :                 if (type_argument_list != null) {
      99    120944466 :                         return type_argument_list;
     100              :                 }
     101    114887597 :                 if (_empty_type_list == null) {
     102         1538 :                         _empty_type_list = new ArrayList<DataType> ();
     103              :                 }
     104    114887597 :                 return _empty_type_list;
     105              :         }
     106              : 
     107       135655 :         public bool has_type_arguments () {
     108       135655 :                 if (type_argument_list == null) {
     109       112604 :                         return false;
     110              :                 }
     111              : 
     112        23051 :                 return type_argument_list.size > 0;
     113              :         }
     114              : 
     115              :         /**
     116              :          * Removes all generic type arguments.
     117              :          */
     118            0 :         public void remove_all_type_arguments () {
     119            0 :                 type_argument_list = null;
     120              :         }
     121              : 
     122     40866479 :         public override void accept (CodeVisitor visitor) {
     123     40866479 :                 visitor.visit_data_type (this);
     124              :         }
     125              : 
     126     32422371 :         public override void accept_children (CodeVisitor visitor) {
     127     32422371 :                 if (type_argument_list != null && type_argument_list.size > 0) {
     128      3014735 :                         foreach (DataType type_arg in type_argument_list) {
     129      1035396 :                                 type_arg.accept (visitor);
     130              :                         }
     131              :                 }
     132              :         }
     133              : 
     134          587 :         public override string to_string () {
     135          587 :                 return to_qualified_string (null);
     136              :         }
     137              : 
     138        32999 :         public virtual string to_qualified_string (Scope? scope = null) {
     139              :                 string s;
     140              : 
     141        52501 :                 if (type_symbol != null) {
     142        38569 :                         Symbol global_symbol = type_symbol;
     143        38569 :                         while (global_symbol.parent_symbol != null && global_symbol.parent_symbol.name != null) {
     144        24638 :                                 global_symbol = global_symbol.parent_symbol;
     145              :                         }
     146              : 
     147        26250 :                         Symbol sym = null;
     148        99457 :                         Scope parent_scope = scope;
     149        99457 :                         while (sym == null && parent_scope != null) {
     150        73207 :                                 sym = parent_scope.lookup (global_symbol.name);
     151       120562 :                                 parent_scope = parent_scope.parent_scope;
     152              :                         }
     153              : 
     154        26250 :                         if (sym != null && global_symbol != sym) {
     155            4 :                                 s = "global::" + type_symbol.get_full_name ();;
     156              :                         } else {
     157        26246 :                                 s = type_symbol.get_full_name ();
     158              :                         }
     159              :                 } else {
     160            1 :                         s = "null";
     161              :                 }
     162              : 
     163      3487645 :                 var type_args = get_type_arguments ();
     164        26251 :                 if (type_args.size > 0) {
     165          214 :                         s += "<";
     166          214 :                         bool first = true;
     167          718 :                         foreach (DataType type_arg in type_args) {
     168          252 :                                 if (!first) {
     169           38 :                                         s += ",";
     170              :                                 } else {
     171              :                                         first = false;
     172              :                                 }
     173          252 :                                 if (type_arg.is_weak ()) {
     174           30 :                                         s += "weak ";
     175              :                                 }
     176          252 :                                 s += type_arg.to_qualified_string (scope);
     177              :                         }
     178          214 :                         s += ">";
     179              :                 }
     180        26251 :                 if (nullable) {
     181          853 :                         s += "?";
     182              :                 }
     183              : 
     184        26251 :                 return s;
     185              :         }
     186              : 
     187              :         /**
     188              :          * Creates a shallow copy of this type reference.
     189              :          *
     190              :          * @return copy of this type reference
     191              :          */
     192     10899269 :         public abstract DataType copy ();
     193              : 
     194              :         /**
     195              :          * Checks two type references for equality. May only be used with
     196              :          * resolved type references.
     197              :          *
     198              :          * @param type2 a type reference
     199              :          * @return      true if this type reference is equal to type2, false
     200              :          *              otherwise
     201              :          */
     202       116502 :         public virtual bool equals (DataType type2) {
     203        58034 :                 if (type2.is_disposable () != is_disposable ()) {
     204           55 :                         return false;
     205              :                 }
     206        58019 :                 if (type2.nullable != nullable) {
     207              :                         //TODO Allow equality between nullable and non-nullable generic-types
     208              :                         // This mitigation allows fixing affected source code without breaking it.
     209              :                         // It has to be removed at some point
     210            0 :                         var context = CodeContext.get ();
     211            0 :                         return !context.experimental_non_null && this is GenericType == type2 is GenericType;
     212              :                 }
     213        58019 :                 if (type2.type_symbol != type_symbol) {
     214           55 :                         return false;
     215              :                 }
     216        57982 :                 if (type2 is GenericType || this is GenericType) {
     217          255 :                         if (!(type2 is GenericType) || !(this is GenericType)) {
     218           55 :                                 return false;
     219              :                         }
     220          255 :                         if (!((GenericType) type2).type_parameter.equals (((GenericType) this).type_parameter)) {
     221           55 :                                 return false;
     222              :                         }
     223              :                 }
     224        57982 :                 if (type2.floating_reference != floating_reference) {
     225           55 :                         return false;
     226              :                 }
     227              : 
     228        57982 :                 var type_args = get_type_arguments ();
     229        57982 :                 var type2_args = type2.get_type_arguments ();
     230        57982 :                 if (type2_args.size != type_args.size) {
     231            0 :                         return false;
     232              :                 }
     233              : 
     234        58967 :                 for (int i = 0; i < type_args.size; i++) {
     235          988 :                         if (!type2_args[i].equals (type_args[i]))
     236            3 :                                 return false;
     237              :                 }
     238              : 
     239        57979 :                 return true;
     240              :         }
     241              : 
     242              :         /**
     243              :          * Checks whether this type reference is at least as strict as the
     244              :          * specified type reference type2.
     245              :          *
     246              :          * @param type2 a type reference
     247              :          * @return      true if this type reference is stricter or equal
     248              :          */
     249        28337 :         public virtual bool stricter (DataType type2) {
     250         7385 :                 if (type2.is_disposable () != is_disposable ()) {
     251              :                         return false;
     252              :                 }
     253              : 
     254         7385 :                 if (!type2.nullable && nullable) {
     255              :                         return false;
     256              :                 }
     257              : 
     258              :                 /* temporarily ignore type parameters */
     259         7385 :                 if (this is GenericType || type2 is GenericType) {
     260              :                         return true;
     261              :                 }
     262              : 
     263         4553 :                 if (type2.type_symbol != type_symbol) {
     264              :                         // FIXME: allow this type reference to refer to a
     265              :                         //        subtype of the type type2 is referring to
     266              :                         return false;
     267              :                 }
     268              : 
     269         4553 :                 if (type2.floating_reference != floating_reference) {
     270              :                         return false;
     271              :                 }
     272              : 
     273              :                 return true;
     274              :         }
     275              : 
     276       538631 :         public override void replace_type (DataType old_type, DataType new_type) {
     277       538631 :                 if (type_argument_list != null) {
     278       585922 :                         for (int i = 0; i < type_argument_list.size; i++) {
     279       585922 :                                 if (type_argument_list[i] == old_type) {
     280       538631 :                                         type_argument_list[i] = new_type;
     281       538631 :                                         return;
     282              :                                 }
     283              :                         }
     284              :                 }
     285              :         }
     286              : 
     287      3494419 :         public virtual bool compatible (DataType target_type) {
     288      1255119 :                 var context = CodeContext.get ();
     289              : 
     290      1255119 :                 if (context.experimental_non_null && nullable && !target_type.nullable) {
     291            7 :                         return false;
     292              :                 }
     293              : 
     294      1255112 :                 if (context.profile == Profile.GOBJECT && target_type.type_symbol != null) {
     295      1232317 :                         unowned DataType? gvalue_type = context.analyzer.gvalue_type;
     296      1232317 :                         if (gvalue_type != null && target_type.type_symbol.is_subtype_of (gvalue_type.type_symbol)) {
     297              :                                 // allow implicit conversion to GValue
     298          167 :                                 return true;
     299              :                         }
     300              : 
     301      1232150 :                         unowned DataType? gvariant_type = context.analyzer.gvariant_type;
     302      1232150 :                         if (gvariant_type != null && target_type.type_symbol.is_subtype_of (gvariant_type.type_symbol)) {
     303              :                                 // allow implicit conversion to GVariant
     304          116 :                                 return true;
     305              :                         }
     306              :                 }
     307              : 
     308      1254829 :                 if (target_type is PointerType) {
     309              :                         /* any reference or array type or pointer type can be cast to a generic pointer */
     310        19844 :                         if (this is GenericType ||
     311         9938 :                                 (type_symbol != null && (
     312              :                                         type_symbol.is_reference_type () ||
     313            0 :                                         this is DelegateType))) {
     314        19844 :                                 return true;
     315              :                         }
     316              : 
     317            0 :                         return false;
     318              :                 }
     319              : 
     320              :                 /* temporarily ignore type parameters */
     321      1234985 :                 if (target_type is GenericType) {
     322        80787 :                         return true;
     323              :                 }
     324              : 
     325      1154198 :                 if (this is ArrayType != target_type is ArrayType) {
     326            1 :                         return false;
     327              :                 }
     328              : 
     329      1154197 :                 if (type_symbol is Enum && target_type.type_symbol is Struct && ((Struct) target_type.type_symbol).is_integer_type ()) {
     330           88 :                         return true;
     331      1154109 :                 } else if (target_type.type_symbol is Enum && type_symbol is Struct && ((Struct) type_symbol).is_integer_type ()) {
     332              :                         //FIXME Drop this unsafe direction in the future?
     333           17 :                         return true;
     334              :                 }
     335              : 
     336              :                 // check for matching ownership of type-arguments
     337      1154092 :                 var type_args = get_type_arguments ();
     338      1154092 :                 var target_type_args = target_type.get_type_arguments ();
     339      1154092 :                 if (type_args.size == target_type_args.size) {
     340      1224543 :                         for (int i = 0; i < type_args.size; i++) {
     341        36996 :                                 var type_arg = type_args[i];
     342        36996 :                                 var target_type_arg = target_type_args[i];
     343              :                                 // Ignore non-boxed simple-type structs
     344        36996 :                                 if (!type_arg.is_non_null_simple_type ()
     345        36846 :                                     && type_arg.is_weak () != target_type_arg.is_weak ()) {
     346            1 :                                         return false;
     347              :                                 }
     348              :                         }
     349              :                 }
     350              : 
     351      1154091 :                 if (type_symbol != null && target_type.type_symbol != null && type_symbol.is_subtype_of (target_type.type_symbol)) {
     352      1036256 :                         var base_type = SemanticAnalyzer.get_instance_base_type_for_member(this, target_type.type_symbol, this);
     353              :                         // check compatibility of generic type arguments
     354      1036256 :                         var base_type_args = base_type.get_type_arguments();
     355      1036256 :                         if (base_type_args.size == target_type_args.size) {
     356      1073157 :                                 for (int i = 0; i < base_type_args.size; i++) {
     357              :                                         // mutable generic types require type argument equality,
     358              :                                         // not just one way compatibility
     359              :                                         // as we do not currently have immutable generic container types,
     360              :                                         // the additional check would be very inconvenient, so we
     361              :                                         // skip the additional check for now
     362        36995 :                                         if (!base_type_args[i].compatible (target_type_args[i])) {
     363            2 :                                                 return false;
     364              :                                         }
     365              :                                 }
     366              :                         }
     367      1036254 :                         return true;
     368              :                 }
     369              : 
     370       117835 :                 if (type_symbol is Struct && target_type.type_symbol is Struct) {
     371        26122 :                         unowned Struct expr_struct = (Struct) type_symbol;
     372        26122 :                         unowned Struct target_struct = (Struct) target_type.type_symbol;
     373              : 
     374              :                         // Allow compatibility of struct subtypes in both ways
     375        26122 :                         if (target_struct.is_subtype_of (expr_struct)) {
     376            2 :                                 return true;
     377              :                         }
     378              : 
     379              :                         // Negative ranks are used for handle types that are not implicitly convertible
     380        26120 :                         if ((expr_struct.is_integer_type () || expr_struct.is_floating_type ()) && expr_struct.rank < 0) {
     381            2 :                                 return false;
     382        26118 :                         } else if ((target_struct.is_integer_type () || target_struct.is_floating_type ()) && target_struct.rank < 0) {
     383            1 :                                 return false;
     384              :                         }
     385              : 
     386              :                         /* integer types may be implicitly cast to floating point types */
     387        26117 :                         if (expr_struct.is_integer_type () && target_struct.is_floating_type ()) {
     388         1478 :                                 return true;
     389              :                         }
     390              : 
     391        24639 :                         if ((expr_struct.is_integer_type () && target_struct.is_integer_type ()) ||
     392          137 :                             (expr_struct.is_floating_type () && target_struct.is_floating_type ())) {
     393        24560 :                                 if (expr_struct.rank <= target_struct.rank) {
     394        24551 :                                         return true;
     395              :                                 }
     396              :                         }
     397              : 
     398           88 :                         if (expr_struct.is_boolean_type () && target_struct.is_boolean_type ()) {
     399            6 :                                 return true;
     400              :                         }
     401              :                 }
     402              : 
     403        91795 :                 return false;
     404              :         }
     405              : 
     406              :         /**
     407              :          * Returns whether instances of this type are invokable.
     408              :          *
     409              :          * @return true if invokable, false otherwise
     410              :          */
     411       191425 :         public virtual bool is_invokable () {
     412            0 :                 return false;
     413              :         }
     414              : 
     415              :         /**
     416              :          * Returns the return type of this invokable.
     417              :          *
     418              :          * @return return type
     419              :          */
     420       234869 :         public virtual unowned DataType? get_return_type () {
     421            0 :                 return null;
     422              :         }
     423              : 
     424              :         /**
     425              :          * Returns the list of invocation parameters.
     426              :          *
     427              :          * @return parameter list
     428              :          */
     429       221546 :         public virtual unowned List<Parameter>? get_parameters () {
     430            0 :                 return null;
     431              :         }
     432              : 
     433       284500 :         public virtual bool is_reference_type_or_type_parameter () {
     434       527349 :                 return (type_symbol != null &&
     435       256451 :                         type_symbol.is_reference_type ()) ||
     436       177834 :                        this is GenericType;
     437              :         }
     438              : 
     439              :         // check whether this type is at least as accessible as the specified symbol
     440     47982093 :         public virtual bool is_accessible (Symbol sym) {
     441     25146898 :                 foreach (var type_arg in get_type_arguments ()) {
     442       943326 :                         if (!type_arg.is_accessible (sym)) {
     443            0 :                                 return false;
     444              :                         }
     445              :                 }
     446     23260246 :                 if (type_symbol != null) {
     447     21310942 :                         return type_symbol.is_accessible (sym);
     448              :                 }
     449     23260246 :                 return true;
     450              :         }
     451              : 
     452       523889 :         public virtual Symbol? get_member (string member_name) {
     453       252371 :                 Symbol? member = null;
     454       252371 :                 if (context_symbol != null) {
     455           50 :                         member = SemanticAnalyzer.symbol_lookup_inherited (context_symbol, member_name);
     456              :                 }
     457       252371 :                 if (member == null && type_symbol != null) {
     458       252323 :                         member = SemanticAnalyzer.symbol_lookup_inherited (type_symbol, member_name);
     459              :                 }
     460              :                 return member;
     461              :         }
     462              : 
     463            2 :         public virtual Symbol? get_pointer_member (string member_name) {
     464              :                 return null;
     465              :         }
     466              : 
     467              :         /**
     468              :          * Checks whether this data type references a real struct. A real struct
     469              :          * is a struct which is not a simple (fundamental) type.
     470              :          */
     471       533368 :         public virtual bool is_real_struct_type () {
     472       533368 :                 unowned Struct? s = type_symbol as Struct;
     473       142450 :                 if (s != null && !s.is_simple_type ()) {
     474              :                         return true;
     475              :                 }
     476              :                 return false;
     477              :         }
     478              : 
     479       153806 :         public bool is_real_non_null_struct_type () {
     480       153806 :                 return is_real_struct_type () && !nullable;
     481              :         }
     482              : 
     483       479836 :         public bool is_non_null_simple_type () {
     484       479836 :                 unowned Struct? s = type_symbol as Struct;
     485       111249 :                 if (s != null && s.is_simple_type ()) {
     486       109955 :                         return !nullable;
     487              :                 }
     488       369881 :                 if (type_symbol is Enum) {
     489         1136 :                         return !nullable;
     490              :                 }
     491       479836 :                 return false;
     492              :         }
     493              : 
     494              :         /**
     495              :          * Returns whether the value needs to be disposed, i.e. whether
     496              :          * allocated memory or other resources need to be released when
     497              :          * the value is no longer needed.
     498              :          */
     499      1024655 :         public virtual bool is_disposable () {
     500       355309 :                 if (!value_owned) {
     501              :                         return false;
     502              :                 }
     503              : 
     504       115617 :                 if (is_reference_type_or_type_parameter ()) {
     505              :                         return true;
     506              :                 }
     507              :                 return false;
     508              :         }
     509              : 
     510      1091645 :         public virtual DataType get_actual_type (DataType? derived_instance_type, List<DataType>? method_type_arguments, CodeNode? node_reference) {
     511       842693 :                 DataType result = this.copy ();
     512              : 
     513       842693 :                 if (derived_instance_type == null && method_type_arguments == null) {
     514              :                         return result;
     515              :                 }
     516              : 
     517       675616 :                 if (result.type_argument_list != null) {
     518              :                         // recursely get actual types for type arguments
     519       139026 :                         for (int i = 0; i < result.type_argument_list.size; i++) {
     520        70700 :                                 result.type_argument_list[i] = result.type_argument_list[i].get_actual_type (derived_instance_type, method_type_arguments, node_reference);
     521              :                         }
     522              :                 }
     523              : 
     524              :                 return result;
     525              :         }
     526              : 
     527          206 :         public bool is_generic () {
     528          206 :                 if (this is GenericType) {
     529            7 :                         return true;
     530              :                 }
     531              : 
     532          200 :                 if (!has_type_arguments ()) {
     533          199 :                         return false;
     534              :                 }
     535            3 :                 foreach (var type_arg in type_argument_list) {
     536            2 :                         if (type_arg.is_generic ()) {
     537            1 :                                 return true;
     538              :                         }
     539              :                 }
     540          206 :                 return false;
     541              :         }
     542              : 
     543           14 :         public void replace_type_parameter (TypeParameter old_type_param, TypeParameter new_type_param) {
     544           14 :                 if (this is GenericType) {
     545           10 :                         if (symbol == old_type_param) {
     546            6 :                                 symbol = new_type_param;
     547              :                         }
     548           10 :                         return;
     549              :                 }
     550            4 :                 if (!has_type_arguments ()) {
     551              :                         return;
     552              :                 }
     553            5 :                 foreach (var type_arg in type_argument_list) {
     554            2 :                         type_arg.replace_type_parameter (old_type_param, new_type_param);
     555              :                 }
     556              :         }
     557              : 
     558              :         /**
     559              :          * Search for the type parameter in this formal type and match it in
     560              :          * value_type.
     561              :          */
     562          313 :         public virtual DataType? infer_type_argument (TypeParameter type_param, DataType value_type) {
     563          105 :                 var value_type_arg_it = value_type.get_type_arguments ().iterator ();
     564          109 :                 foreach (var formal_type_arg in this.get_type_arguments ()) {
     565           11 :                         if (value_type_arg_it.next ()) {
     566           11 :                                 var inferred_type = formal_type_arg.infer_type_argument (type_param, value_type_arg_it.get ());
     567           11 :                                 if (inferred_type != null) {
     568            9 :                                         return inferred_type;
     569              :                                 }
     570              :                         }
     571              :                 }
     572              : 
     573           96 :                 return null;
     574              :         }
     575              : 
     576              :         /**
     577              :          * Returns a stringified representation used for detailed error output
     578              :          *
     579              :          * @param override_name used as name if given
     580              :          * @return stringified representation
     581              :          */
     582           58 :         public virtual string to_prototype_string (string? override_name = null) {
     583           40 :                 return "%s%s".printf (is_weak () ? "unowned " : "", to_qualified_string ());
     584              :         }
     585              : 
     586        88827 :         public bool is_weak () {
     587        88827 :                 if (this.value_owned) {
     588              :                         return false;
     589        10397 :                 } else if (this is VoidType || this is PointerType) {
     590              :                         return false;
     591         6502 :                 } else if (this is ValueType) {
     592         3509 :                         if (this.nullable) {
     593              :                                 // nullable structs are heap allocated
     594              :                                 return true;
     595              :                         }
     596              : 
     597              :                         // TODO return true for structs with destroy
     598              :                         return false;
     599              :                 }
     600              : 
     601              :                 return true;
     602              :         }
     603              : 
     604         1228 :         public string? get_type_signature (Symbol? symbol = null) {
     605         1469 :                 if (symbol != null) {
     606          251 :                         string sig = symbol.get_attribute_string ("DBus", "signature");
     607          251 :                         if (sig != null) {
     608              :                                 // allow overriding signature in attribute, used for raw GVariants
     609         1228 :                                 return sig;
     610              :                         }
     611              :                 }
     612              : 
     613         1218 :                 unowned ArrayType? array_type = this as ArrayType;
     614              : 
     615         1218 :                 if (array_type != null) {
     616          218 :                         string element_type_signature = array_type.element_type.get_type_signature ();
     617              : 
     618          218 :                         if (element_type_signature == null) {
     619            3 :                                 return null;
     620              :                         }
     621              : 
     622          215 :                         return string.nfill (array_type.rank, 'a') + element_type_signature;
     623         1000 :                 } else if (type_symbol is Enum && type_symbol.get_attribute_bool ("DBus", "use_string_marshalling")) {
     624            6 :                         return "s";
     625          994 :                 } else if (type_symbol != null) {
     626          994 :                         string sig = type_symbol.get_attribute_string ("CCode", "type_signature");
     627              : 
     628          994 :                         unowned Struct? st = type_symbol as Struct;
     629          994 :                         unowned Enum? en = type_symbol as Enum;
     630          994 :                         if (sig == null && st != null) {
     631           42 :                                 var str = new StringBuilder ();
     632           84 :                                 str.append_c ('(');
     633          206 :                                 foreach (Field f in st.get_fields ()) {
     634           86 :                                         if (f.binding == MemberBinding.INSTANCE) {
     635           86 :                                                 var s = f.variable_type.get_type_signature (f);
     636           86 :                                                 if (s != null) {
     637          164 :                                                         str.append (s);
     638              :                                                 } else {
     639            4 :                                                         return null;
     640              :                                                 }
     641              :                                         }
     642              :                                 }
     643           38 :                                 str.append_c (')');
     644           76 :                                 sig = str.str;
     645          952 :                         } else if (sig == null && en != null) {
     646            0 :                                 if (en.is_flags) {
     647            0 :                                         return "u";
     648              :                                 } else {
     649            0 :                                         return "i";
     650              :                                 }
     651              :                         }
     652              : 
     653          990 :                         var type_args = get_type_arguments ();
     654          990 :                         if (sig != null && "%s" in sig && type_args.size > 0) {
     655           38 :                                 string element_sig = "";
     656          190 :                                 foreach (DataType type_arg in type_args) {
     657           76 :                                         var s = type_arg.get_type_signature ();
     658           76 :                                         if (s != null) {
     659           76 :                                                 element_sig += s;
     660              :                                         }
     661              :                                 }
     662              : 
     663           38 :                                 sig = sig.replace ("%s", element_sig);
     664              :                         }
     665              : 
     666          990 :                         if (sig == null &&
     667           20 :                             (type_symbol.get_full_name () == "GLib.UnixInputStream" ||
     668            8 :                              type_symbol.get_full_name () == "GLib.UnixOutputStream" ||
     669            6 :                              type_symbol.get_full_name () == "GLib.Socket")) {
     670           14 :                                 return "h";
     671              :                         }
     672              : 
     673          976 :                         return sig;
     674              :                 } else {
     675            7 :                         return null;
     676              :                 }
     677              :         }
     678              : 
     679              :         /**
     680              :          * Returns whether the given amount of type-argument matches the symbol's count of type-parameters
     681              :          *
     682              :          * @param context a CodeContext
     683              :          * @param allow_none whether no type-argments are allowed
     684              :          * @return true if successful
     685              :          */
     686     37102840 :         public bool check_type_arguments (CodeContext context, bool allow_none = false) {
     687     37102840 :                 int n_type_args = get_type_arguments ().size;
     688     37102840 :                 int expected_n_type_args = 0;
     689              : 
     690     37102840 :                 if (type_symbol is GenericSymbol) {
     691     35589704 :                         expected_n_type_args = ((GenericSymbol) type_symbol).get_type_parameters ().size;
     692      1513136 :                 } else if (n_type_args > 0) {
     693            0 :                         Report.error (source_reference, "`%s' does not support type arguments", type_symbol.get_full_name ());
     694            0 :                         error = true;
     695            0 :                         return false;
     696              :                 } else {
     697              :                         // nothing to do here
     698     37102789 :                         return true;
     699              :                 }
     700              : 
     701     35589704 :                 if ((!allow_none || n_type_args > 0) && n_type_args < expected_n_type_args) {
     702           26 :                         error = true;
     703           26 :                         Report.error (source_reference, "too few type arguments for `%s'", type_symbol.to_string ());
     704           26 :                         return false;
     705     35589678 :                 } else if ((!allow_none || n_type_args > 0) && n_type_args > expected_n_type_args) {
     706           23 :                         error = true;
     707           23 :                         Report.error (source_reference, "too many type arguments for `%s'", type_symbol.to_string ());
     708           23 :                         return false;
     709              :                 }
     710              : 
     711     39999499 :                 foreach (DataType type in get_type_arguments ()) {
     712      2204924 :                         if (!type.check (context)) {
     713            2 :                                 return false;
     714              :                         }
     715              :                 }
     716              : 
     717     37102840 :                 return true;
     718              :         }
     719              : }
        

Generated by: LCOV version 2.0-1