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

            Line data    Source code
       1              : /* valasymbol.vala
       2              :  *
       3              :  * Copyright (C) 2006-2010  Jürg Billeter
       4              :  *
       5              :  * This library is free software; you can redistribute it and/or
       6              :  * modify it under the terms of the GNU Lesser General Public
       7              :  * License as published by the Free Software Foundation; either
       8              :  * version 2.1 of the License, or (at your option) any later version.
       9              : 
      10              :  * This library is distributed in the hope that it will be useful,
      11              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13              :  * Lesser General Public License for more details.
      14              : 
      15              :  * You should have received a copy of the GNU Lesser General Public
      16              :  * License along with this library; if not, write to the Free Software
      17              :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
      18              :  *
      19              :  * Author:
      20              :  *      Jürg Billeter <j@bitron.ch>
      21              :  */
      22              : 
      23              : using GLib;
      24              : 
      25              : /**
      26              :  * Represents a node in the symbol tree.
      27              :  */
      28         1538 : public abstract class Vala.Symbol : CodeNode {
      29              :         /**
      30              :          * The parent of this symbol.
      31              :          */
      32              :         public weak Symbol? parent_symbol {
      33    370545137 :                 get {
      34    370545137 :                         if (owner == null) {
      35     49341363 :                                 return null;
      36              :                         } else {
      37    321203774 :                                 return owner.owner;
      38              :                         }
      39              :                 }
      40              :         }
      41              : 
      42              :         /**
      43              :          * The scope this symbol is a part of
      44              :          */
      45              :         public weak Scope owner {
      46    695940773 :                 get {
      47    695940773 :                         return _owner;
      48              :                 }
      49     29039353 :                 set {
      50     29039353 :                         _owner = value;
      51     29039353 :                         _scope.parent_scope = value;
      52              :                 }
      53              :         }
      54              : 
      55              :         /**
      56              :          * The symbol name.
      57              :          */
      58    303076706 :         public string? name { get; set; }
      59              : 
      60              :         /**
      61              :          * Specifies whether this symbol is active.
      62              :          *
      63              :          * Symbols may become inactive when they only apply to a part of a
      64              :          * scope. This is used for local variables not declared at the beginning
      65              :          * of the block to determine which variables need to be freed before
      66              :          * jump statements.
      67              :          */
      68     26402324 :         public bool active { get; set; default = true; }
      69              : 
      70              :         /**
      71              :          * Specifies whether this symbol has been accessed.
      72              :          */
      73     23194294 :         public bool used { get; set; }
      74              : 
      75              :         /**
      76              :          * Specifies whether this symbol is anonymous and has no public definition.
      77              :          */
      78        57912 :         public bool anonymous { get; set; }
      79              : 
      80              :         /**
      81              :          * Specifies the accessibility of this symbol. Public accessibility
      82              :          * doesn't limit access. Default accessibility limits access to this
      83              :          * program or library. Private accessibility limits access to instances
      84              :          * of the contained type.
      85              :          */
      86     45019276 :         public SymbolAccessibility access { get; set; }
      87              : 
      88    120517084 :         public Comment? comment { get; set; }
      89              : 
      90              : 
      91     60047056 :         private VersionAttribute _version;
      92              : 
      93              :         /**
      94              :          * The associated [Version] attribute
      95              :          */
      96              :         public VersionAttribute version {
      97      1768563 :                 get {
      98      1768563 :                         if (_version == null) {
      99       643926 :                                 _version = new VersionAttribute (this);
     100              :                         }
     101              : 
     102      1768563 :                         return _version;
     103              :                 }
     104              :         }
     105              : 
     106              :         /**
     107              :          * Specifies whether this method explicitly hides a member of a base
     108              :          * type.
     109              :          */
     110      3627006 :         public bool hides { get; set; }
     111              : 
     112              :         /**
     113              :          * Check if this symbol is just internal API (and therefore doesn't need
     114              :          * to be listed in header files for instance) by traversing parent symbols
     115              :          * and checking their accessibility.
     116              :          */
     117      5472707 :         public bool is_internal_symbol () {
     118      5472707 :                 if (!external && external_package) {
     119              :                         // non-external symbols in VAPI files are internal symbols
     120       129435 :                         return true;
     121              :                 }
     122              : 
     123     46637128 :                 for (Symbol sym = this; null != sym; sym = sym.parent_symbol) {
     124     41172898 :                         if (sym.access == SymbolAccessibility.PRIVATE
     125     20567410 :                             || sym.access == SymbolAccessibility.INTERNAL) {
     126        50232 :                                 return true;
     127              :                         }
     128              :                 }
     129              : 
     130      5472707 :                 return false;
     131              :         }
     132              : 
     133        34341 :         public bool is_private_symbol () {
     134        34341 :                 if (!external && external_package) {
     135              :                         // non-external symbols in VAPI files are private symbols
     136         4479 :                         return true;
     137              :                 }
     138              : 
     139       263255 :                 for (Symbol sym = this; null != sym; sym = sym.parent_symbol) {
     140        90419 :                         if (sym.access == SymbolAccessibility.PRIVATE) {
     141         4001 :                                 return true;
     142              :                         }
     143              :                 }
     144              : 
     145        34341 :                 return false;
     146              :         }
     147              : 
     148              :         /**
     149              :          * The scope this symbol opens.
     150              :          */
     151              :         public Scope scope {
     152     51056541 :                 get { return _scope; }
     153              :         }
     154              : 
     155      6409633 :         public bool is_extern { get; set; }
     156              : 
     157              :         /**
     158              :          * Specifies whether the implementation is external, for example in
     159              :          * a separate C source file or in an external library.
     160              :          */
     161              :         public bool external {
     162     12360139 :                 get {
     163     12360139 :                         if (_external != null) {
     164       798808 :                                 return _external;
     165              :                         }
     166     11561331 :                         return is_extern || external_package;
     167              :                 }
     168       678813 :                 set {
     169      1357626 :                         _external = value;
     170              :                 }
     171              :         }
     172              : 
     173              :         /**
     174              :          * Specifies whether the implementation is in an external library.
     175              :          */
     176              :         public bool external_package {
     177     60278735 :                 get {
     178     60278735 :                         return source_type == SourceFileType.PACKAGE;
     179              :                 }
     180              :         }
     181              : 
     182              :         /**
     183              :          * Specifies whether the implementation came from the commandline.
     184              :          */
     185              :         public bool from_commandline {
     186        20154 :                 get {
     187        20154 :                         if (source_reference != null) {
     188        20154 :                                 return source_reference.file.from_commandline;
     189              :                         } else {
     190            0 :                                 return false;
     191              :                         }
     192              :                 }
     193              :         }
     194              : 
     195              :         /**
     196              :          * Gets the SourceFileType of the source file that this symbol
     197              :          * came from, or SourceFileType.NONE.
     198              :          */
     199              :         public SourceFileType source_type {
     200     61849608 :                 get {
     201     61849608 :                         if (source_reference != null) {
     202     61846743 :                                 return source_reference.file.file_type;
     203              :                         } else {
     204         2865 :                                 return SourceFileType.NONE;
     205              :                         }
     206              :                 }
     207              :         }
     208              : 
     209              :         private weak Scope _owner;
     210     60047056 :         private Scope _scope;
     211     60047056 :         private bool? _external;
     212              : 
     213     60047066 :         protected Symbol (string? name, SourceReference? source_reference = null, Comment? comment = null) {
     214     60047066 :                 this.name = name;
     215     60047066 :                 this.source_reference = source_reference;
     216     60047066 :                 this.comment = comment;
     217     60047066 :                 _scope = new Scope (this);
     218              :         }
     219              : 
     220              :         /**
     221              :          * Returns the fully expanded name of this symbol for use in
     222              :          * human-readable messages.
     223              :          *
     224              :          * @return full name
     225              :          */
     226       118990 :         public string get_full_name () {
     227       118990 :                 if (parent_symbol == null) {
     228        99164 :                         return name;
     229              :                 }
     230              : 
     231        69408 :                 if (name == null) {
     232           93 :                         return parent_symbol.get_full_name ();
     233              :                 }
     234              : 
     235        69315 :                 if (parent_symbol.get_full_name () == null) {
     236        99158 :                         return name;
     237              :                 }
     238              : 
     239        19736 :                 if (name.has_prefix (".")) {
     240            3 :                         return "%s%s".printf (parent_symbol.get_full_name (), name);
     241              :                 } else {
     242        19733 :                         return "%s.%s".printf (parent_symbol.get_full_name (), name);
     243              :                 }
     244              :         }
     245              : 
     246              :         /**
     247              :          * Converts a string from CamelCase to lower_case.
     248              :          *
     249              :          * @param camel_case a string in camel case
     250              :          * @return           the specified string converted to lower case
     251              :          */
     252        23562 :         public static string camel_case_to_lower_case (string camel_case) {
     253        23562 :                 if ("_" in camel_case) {
     254              :                         // do not insert additional underscores if input is not real camel case
     255         2178 :                         return camel_case.ascii_down ();
     256              :                 }
     257              : 
     258        21384 :                 var result_builder = new StringBuilder ("");
     259              : 
     260        21384 :                 weak string i = camel_case;
     261              : 
     262        21384 :                 bool first = true;
     263       162840 :                 while (i.length > 0) {
     264       141456 :                         unichar c = i.get_char ();
     265       141456 :                         if (c.isupper () && !first) {
     266              :                                 /* current character is upper case and
     267              :                                  * we're not at the beginning */
     268        10143 :                                 weak string t = i.prev_char ();
     269        10143 :                                 bool prev_upper = t.get_char ().isupper ();
     270        10143 :                                 t = i.next_char ();
     271        10143 :                                 bool next_upper = t.get_char ().isupper ();
     272        10143 :                                 if (!prev_upper || (i.length >= 2 && !next_upper)) {
     273              :                                         /* previous character wasn't upper case or
     274              :                                          * next character isn't upper case*/
     275         8464 :                                         long len = result_builder.str.length;
     276         8464 :                                         if (len != 1 && result_builder.str.get_char (len - 2) != '_') {
     277              :                                                 /* we're not creating 1 character words */
     278         7829 :                                                 result_builder.append_c ('_');
     279              :                                         }
     280              :                                 }
     281              :                         }
     282              : 
     283       141456 :                         result_builder.append_unichar (c.tolower ());
     284              : 
     285       141456 :                         first = false;
     286       141456 :                         i = i.next_char ();
     287              :                 }
     288              : 
     289        42768 :                 return result_builder.str;
     290              :         }
     291              : 
     292              :         /**
     293              :          * Converts a string from lower_case to CamelCase.
     294              :          *
     295              :          * @param lower_case a string in lower case
     296              :          * @return           the specified string converted to camel case
     297              :          */
     298         1126 :         public static string lower_case_to_camel_case (string lower_case) {
     299         1126 :                 var result_builder = new StringBuilder ("");
     300              : 
     301         1126 :                 weak string i = lower_case;
     302              : 
     303         1126 :                 bool last_underscore = true;
     304        13119 :                 while (i.length > 0) {
     305        11993 :                         unichar c = i.get_char ();
     306        11993 :                         if (c == '_') {
     307              :                                 last_underscore = true;
     308        10583 :                         } else if (c.isupper ()) {
     309              :                                 // original string is not lower_case, don't apply transformation
     310            0 :                                 return lower_case;
     311        10583 :                         } else if (last_underscore) {
     312         2509 :                                 result_builder.append_unichar (c.toupper ());
     313         2509 :                                 last_underscore = false;
     314              :                         } else {
     315         8074 :                                 result_builder.append_unichar (c);
     316              :                         }
     317              : 
     318        11993 :                         i = i.next_char ();
     319              :                 }
     320              : 
     321         2252 :                 return result_builder.str;
     322              :         }
     323              : 
     324              :         /**
     325              :          * Implementation of GLib.EqualFunc to use with e.g. HashMap
     326              :          *
     327              :          * @param a a symbol
     328              :          * @param b a symbol
     329              :          * @return whether the given instances represent the same symbol
     330              :          */
     331            0 :         public static bool equal_func (Symbol a, Symbol b) {
     332            0 :                 return str_equal (a.get_full_name (), b.get_full_name ());
     333              :         }
     334              : 
     335              :         /**
     336              :          * Implementation of GLib.HashFunc to use with e.g. HashMap
     337              :          *
     338              :          * @param s a symbol
     339              :          * @return a hash value
     340              :          */
     341            4 :         public static uint hash_func (Symbol s) {
     342            4 :                 return str_hash (s.get_full_name ());
     343              :         }
     344              : 
     345              :         // get the top scope from where this symbol is still accessible
     346    156053703 :         public Scope? get_top_accessible_scope (bool is_internal = false) {
     347    156053703 :                 if (access == SymbolAccessibility.PRIVATE) {
     348              :                         // private symbols are accessible within the scope where the symbol has been declared
     349       564393 :                         return owner;
     350              :                 }
     351              : 
     352    155509873 :                 if (access == SymbolAccessibility.INTERNAL) {
     353        20566 :                         is_internal = true;
     354              :                 }
     355              : 
     356    155509873 :                 if (parent_symbol == null) {
     357              :                         // this is the root symbol
     358     43648016 :                         if (is_internal) {
     359              :                                 // only accessible within the same library
     360              :                                 // return root scope
     361        41126 :                                 return scope;
     362              :                         } else {
     363              :                                 // unlimited access
     364     43627453 :                                 return null;
     365              :                         }
     366              :                 }
     367              : 
     368              :                 // if this is a public symbol, it's equally accessible as the parent symbol
     369    111861857 :                 return parent_symbol.get_top_accessible_scope (is_internal);
     370              :         }
     371              : 
     372          343 :         public virtual bool is_instance_member () {
     373          343 :                 bool instance = true;
     374          411 :                 if (this is Field) {
     375           68 :                         var f = (Field) this;
     376           68 :                         instance = (f.binding == MemberBinding.INSTANCE);
     377          275 :                 } else if (this is Method) {
     378            0 :                         var m = (Method) this;
     379            0 :                         if (!(m is CreationMethod)) {
     380            0 :                                 instance = (m.binding == MemberBinding.INSTANCE);
     381              :                         }
     382          284 :                 } else if (this is Property) {
     383            9 :                         var prop = (Property) this;
     384            9 :                         instance = (prop.binding == MemberBinding.INSTANCE);
     385          266 :                 } else if (this is EnumValue) {
     386              :                         instance = false;
     387            9 :                 } else if (this is ErrorCode) {
     388          343 :                         instance = false;
     389              :                 }
     390              : 
     391          343 :                 return instance;
     392              :         }
     393              : 
     394           63 :         public virtual bool is_class_member () {
     395           63 :                 bool isclass = true;
     396          102 :                 if (this is Field) {
     397           39 :                         var f = (Field) this;
     398           39 :                         isclass = (f.binding == MemberBinding.CLASS);
     399           48 :                 } else if (this is Method) {
     400           24 :                         var m = (Method) this;
     401           24 :                         if (!(m is CreationMethod)) {
     402           24 :                                 isclass = (m.binding == MemberBinding.CLASS);
     403              :                         }
     404            0 :                 } else if (this is Property) {
     405            0 :                         var prop = (Property) this;
     406            0 :                         isclass = (prop.binding == MemberBinding.CLASS);
     407            0 :                 } else if (this is EnumValue) {
     408              :                         isclass = false;
     409            0 :                 } else if (this is ErrorCode) {
     410           63 :                         isclass = false;
     411              :                 }
     412              : 
     413           63 :                 return isclass;
     414              :         }
     415              : 
     416         8496 :         public Symbol? get_hidden_member () {
     417         8496 :                 Symbol sym = null;
     418              : 
     419         8496 :                 if (parent_symbol is Class) {
     420         4468 :                         var cl = ((Class) parent_symbol).base_class;
     421        12378 :                         while (cl != null) {
     422         7924 :                                 sym = cl.scope.lookup (name);
     423         7924 :                                 if (sym != null && sym.access != SymbolAccessibility.PRIVATE) {
     424           14 :                                         return sym;
     425              :                                 }
     426        12434 :                                 cl = cl.base_class;
     427              :                         }
     428         4028 :                 } else if (parent_symbol is Struct) {
     429          306 :                         var st = ((Struct) parent_symbol).base_struct;
     430          313 :                         while (st != null) {
     431            7 :                                 sym = st.scope.lookup (name);
     432            7 :                                 if (sym != null && sym.access != SymbolAccessibility.PRIVATE) {
     433            0 :                                         return sym;
     434              :                                 }
     435            7 :                                 st = st.base_struct;
     436              :                         }
     437              :                 }
     438              : 
     439         4760 :                 return null;
     440              :         }
     441              : 
     442              :         // check whether this symbol is at least as accessible as the specified symbol
     443     22095923 :         public  bool is_accessible (Symbol sym) {
     444     22095923 :                 Scope sym_scope = sym.get_top_accessible_scope ();
     445     22095923 :                 Scope this_scope = this.get_top_accessible_scope ();
     446     22095923 :                 if ((sym_scope == null && this_scope != null)
     447     22095909 :                     || (sym_scope != null && !sym_scope.is_subscope_of (this_scope))) {
     448           14 :                         return false;
     449              :                 }
     450              : 
     451     22095909 :                 return true;
     452              :         }
     453              : 
     454        77829 :         public virtual void add_namespace (Namespace ns) {
     455            0 :                 Report.error (ns.source_reference, "inner `%s' is not supported in `%s'", "namespace", get_full_name ());
     456              :         }
     457              : 
     458       624567 :         public virtual void add_class (Class cl) {
     459            0 :                 Report.error (cl.source_reference, "inner `%s' types are not supported in `%s'", "class", get_full_name ());
     460              :         }
     461              : 
     462       116017 :         public virtual void add_interface (Interface iface) {
     463            0 :                 Report.error (iface.source_reference, "inner `%s' types are not supported in `%s'", "interface", get_full_name ());
     464              :         }
     465              : 
     466       180505 :         public virtual void add_struct (Struct st) {
     467            0 :                 Report.error (st.source_reference, "inner `%s' types are not supported in `%s'", "struct", get_full_name ());
     468              :         }
     469              : 
     470       338025 :         public virtual void add_enum (Enum en) {
     471            0 :                 Report.error (en.source_reference, "inner `%s' types are not supported in `%s'", "enum", get_full_name ());
     472              :         }
     473              : 
     474        39937 :         public virtual void add_error_domain (ErrorDomain edomain) {
     475            0 :                 Report.error (edomain.source_reference, "inner `%s' types are not supported in `%s'", "errordomain", get_full_name ());
     476              :         }
     477              : 
     478       283923 :         public virtual void add_delegate (Delegate d) {
     479            0 :                 Report.error (d.source_reference, "inner `%s' types are not supported in `%s'", "delegate", get_full_name ());
     480              :         }
     481              : 
     482       656309 :         public virtual void add_constant (Constant constant) {
     483            0 :                 Report.error (constant.source_reference, "constants are not allowed in `%s'", get_full_name ());
     484              :         }
     485              : 
     486       581511 :         public virtual void add_field (Field f) {
     487            0 :                 Report.error (f.source_reference, "fields are not allowed in `%s'", get_full_name ());
     488              :         }
     489              : 
     490      6589647 :         public virtual void add_method (Method m) {
     491            0 :                 Report.error (m.source_reference, "methods are not allowed in `%s'", get_full_name ());
     492              :         }
     493              : 
     494       449363 :         public virtual void add_property (Property prop) {
     495            0 :                 Report.error (prop.source_reference, "properties are not allowed in `%s'", get_full_name ());
     496              :         }
     497              : 
     498       136715 :         public virtual void add_signal (Signal sig) {
     499            0 :                 Report.error (sig.source_reference, "signals are not allowed in `%s'", get_full_name ());
     500              :         }
     501              : 
     502           47 :         public virtual void add_constructor (Constructor c) {
     503            0 :                 Report.error (c.source_reference, "constructors are not allowed in `%s'", get_full_name ());
     504              :         }
     505              : 
     506           26 :         public virtual void add_destructor (Destructor d) {
     507            0 :                 Report.error (d.source_reference, "destructors are not allowed in `%s'", get_full_name ());
     508              :         }
     509              : 
     510           51 :         public override string to_string () {
     511           51 :                 var builder = new StringBuilder (get_full_name ());
     512              : 
     513           51 :                 unowned List<TypeParameter>? type_params = null;
     514           51 :                 if (this is GenericSymbol) {
     515           51 :                         type_params = ((GenericSymbol) this).get_type_parameters ();
     516              :                 }
     517           51 :                 if (type_params != null && type_params.size > 0) {
     518           46 :                         builder.append_c ('<');
     519           46 :                         bool first = true;
     520          113 :                         foreach (var type_param in type_params) {
     521           67 :                                 if (!first) {
     522           21 :                                         builder.append_c (',');
     523              :                                 } else {
     524              :                                         first = false;
     525              :                                 }
     526          134 :                                 builder.append (type_param.name);
     527              :                         }
     528           46 :                         builder.append_c ('>');
     529              :                 }
     530              : 
     531          102 :                 return builder.str;
     532              :         }
     533              : }
     534              : 
     535              : public enum Vala.SymbolAccessibility {
     536              :         PRIVATE,
     537              :         INTERNAL,
     538              :         PROTECTED,
     539              :         PUBLIC;
     540              : 
     541              :         public unowned string to_string () {
     542        18800 :                 switch (this) {
     543        18800 :                 case PROTECTED: return "protected";
     544            9 :                 case INTERNAL: return "internal";
     545           64 :                 case PRIVATE: return "private";
     546        18454 :                 case PUBLIC: return "public";
     547            0 :                 default: assert_not_reached ();
     548              :                 }
     549              :         }
     550              : }
     551              : 
     552              : public enum Vala.MemberBinding {
     553              :         INSTANCE,
     554              :         CLASS,
     555              :         STATIC
     556              : }
        

Generated by: LCOV version 2.0-1