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

            Line data    Source code
       1              : /* valainterface.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 an interface declaration in the source code.
      27              :  */
      28       118682 : public class Vala.Interface : ObjectTypeSymbol {
      29       117152 :         private List<DataType> prerequisites = new ArrayList<DataType> ();
      30              : 
      31       117152 :         private List<Symbol> virtuals = new ArrayList<Symbol> ();
      32              : 
      33              :         /**
      34              :          * Creates a new interface.
      35              :          *
      36              :          * @param name              type name
      37              :          * @param source_reference  reference to source code
      38              :          * @return                  newly created interface
      39              :          */
      40       175728 :         public Interface (string name, SourceReference? source_reference = null, Comment? comment = null) {
      41        58576 :                 base (name, source_reference, comment);
      42              :         }
      43              : 
      44              :         /**
      45              :          * Adds the specified interface or class to the list of prerequisites of
      46              :          * this interface.
      47              :          *
      48              :          * @param type an interface or class reference
      49              :          */
      50        73594 :         public void add_prerequisite (DataType type) {
      51        73594 :                 prerequisites.add (type);
      52        73594 :                 type.parent_node = this;
      53              :         }
      54              : 
      55              :         /**
      56              :          * Returns the base type list.
      57              :          *
      58              :          * @return list of base types
      59              :          */
      60       577079 :         public unowned List<DataType> get_prerequisites () {
      61       577079 :                 return prerequisites;
      62              :         }
      63              : 
      64              :         /**
      65              :          * Adds the specified method as a member to this interface.
      66              :          *
      67              :          * @param m a method
      68              :          */
      69       573779 :         public override void add_method (Method m) {
      70       573779 :                 if (m is CreationMethod) {
      71            1 :                         Report.error (m.source_reference, "construction methods may only be declared within classes and structs");
      72              : 
      73            1 :                         m.error = true;
      74            1 :                         return;
      75              :                 }
      76       573778 :                 if (m.binding != MemberBinding.STATIC) {
      77       507291 :                         m.this_parameter = new Parameter ("this", SemanticAnalyzer.get_this_type (m, this), m.source_reference);
      78       507291 :                         m.scope.add (m.this_parameter.name, m.this_parameter);
      79              :                 }
      80       573778 :                 if (!(m.return_type is VoidType) && m.get_postconditions ().size > 0) {
      81            0 :                         m.result_var = new LocalVariable (m.return_type.copy (), "result", null, m.source_reference);
      82            0 :                         m.result_var.is_result = true;
      83              :                 }
      84              : 
      85       573778 :                 base.add_method (m);
      86              :         }
      87              : 
      88              :         /**
      89              :          * Adds the specified property as a member to this interface.
      90              :          *
      91              :          * @param prop a property
      92              :          */
      93        49301 :         public override void add_property (Property prop) {
      94        49301 :                 if (prop.field != null) {
      95            0 :                         Report.error (prop.source_reference, "interface properties should be `abstract' or have `get' accessor and/or `set' mutator");
      96              : 
      97            0 :                         prop.error = true;
      98            0 :                         return;
      99              :                 }
     100              : 
     101        49301 :                 base.add_property (prop);
     102              : 
     103        49301 :                 if (prop.binding != MemberBinding.STATIC) {
     104        49301 :                         prop.this_parameter = new Parameter ("this", SemanticAnalyzer.get_this_type (prop, this), prop.source_reference);
     105        49301 :                         prop.scope.add (prop.this_parameter.name, prop.this_parameter);
     106              :                 }
     107              :         }
     108              : 
     109          242 :         public virtual List<Symbol> get_virtuals () {
     110          242 :                 return virtuals;
     111              :         }
     112              : 
     113       130835 :         public override void accept (CodeVisitor visitor) {
     114       130835 :                 visitor.visit_interface (this);
     115              :         }
     116              : 
     117       127846 :         public override void accept_children (CodeVisitor visitor) {
     118       448558 :                 foreach (DataType type in prerequisites) {
     119       160356 :                         type.accept (visitor);
     120              :                 }
     121              : 
     122              :                 // Invoke common implementation in ObjectTypeSymbol
     123       127846 :                 base.accept_children (visitor);
     124              :         }
     125              : 
     126         2152 :         public override bool is_reference_type () {
     127         2152 :                 return true;
     128              :         }
     129              : 
     130       284240 :         public override bool is_subtype_of (TypeSymbol t) {
     131       284240 :                 if (this == t) {
     132       189962 :                         return true;
     133              :                 }
     134              : 
     135       468738 :                 foreach (DataType prerequisite in prerequisites) {
     136       281800 :                         if (prerequisite.type_symbol != null && prerequisite.type_symbol.is_subtype_of (t)) {
     137       189140 :                                 return true;
     138              :                         }
     139              :                 }
     140              : 
     141       284240 :                 return false;
     142              :         }
     143              : 
     144        68404 :         public override void replace_type (DataType old_type, DataType new_type) {
     145        86622 :                 for (int i = 0; i < prerequisites.size; i++) {
     146        86622 :                         if (prerequisites[i] == old_type) {
     147        68404 :                                 prerequisites[i] = new_type;
     148        68404 :                                 new_type.parent_node = this;
     149        68404 :                                 return;
     150              :                         }
     151              :                 }
     152              :         }
     153              : 
     154      1800080 :         public override bool check (CodeContext context) {
     155      1800080 :                 if (checked) {
     156      1745843 :                         return !error;
     157              :                 }
     158              : 
     159        54237 :                 if (!base.check (context)) {
     160            5 :                         return false;
     161              :                 }
     162              : 
     163        54237 :                 checked = true;
     164              : 
     165        54237 :                 var old_source_file = context.analyzer.current_source_file;
     166       107334 :                 var old_symbol = context.analyzer.current_symbol;
     167              : 
     168        54237 :                 if (source_reference != null) {
     169        54237 :                         context.analyzer.current_source_file = source_reference.file;
     170              :                 }
     171        54237 :                 context.analyzer.current_symbol = this;
     172              : 
     173       190461 :                 foreach (DataType prerequisite_reference in get_prerequisites ()) {
     174              :                         // check whether prerequisite is at least as accessible as the interface
     175        68115 :                         if (!prerequisite_reference.is_accessible (this)) {
     176            1 :                                 error = true;
     177            1 :                                 Report.error (source_reference, "prerequisite `%s' is less accessible than interface `%s'", prerequisite_reference.to_string (), get_full_name ());
     178            1 :                                 return false;
     179              :                         }
     180              : 
     181              :                         // check whether there is the expected amount of type-arguments
     182        68114 :                         if (!prerequisite_reference.check_type_arguments (context)) {
     183            2 :                                 error = true;
     184            2 :                                 return false;
     185              :                         }
     186              :                 }
     187              : 
     188              :                 /* check prerequisites */
     189        54234 :                 Class prereq_class = null;
     190       122344 :                 foreach (DataType prereq in get_prerequisites ()) {
     191        68112 :                         if (!(prereq is ObjectType)) {
     192            1 :                                 error = true;
     193            1 :                                 Report.error (source_reference, "Prerequisite `%s' of interface `%s' is not a class or interface", prereq.to_string (), get_full_name ());
     194            1 :                                 return false;
     195              :                         }
     196              : 
     197              :                         /* interfaces are not allowed to have multiple instantiable prerequisites */
     198        68111 :                         if (prereq.type_symbol is Class) {
     199        52754 :                                 if (prereq_class != null) {
     200            1 :                                         error = true;
     201            1 :                                         Report.error (source_reference, "%s: Interfaces cannot have multiple instantiable prerequisites (`%s' and `%s')", get_full_name (), prereq.type_symbol.get_full_name (), prereq_class.get_full_name ());
     202            1 :                                         return false;
     203              :                                 }
     204              : 
     205       120863 :                                 prereq_class = (Class) prereq.type_symbol;
     206              :                         }
     207              :                 }
     208              : 
     209       190450 :                 foreach (DataType type in prerequisites) {
     210        68109 :                         type.check (context);
     211        68109 :                         context.analyzer.check_type (type);
     212              :                 }
     213              : 
     214        54232 :                 foreach (Enum en in get_enums ()) {
     215            0 :                         en.check (context);
     216              :                 }
     217              : 
     218        54234 :                 foreach (Field f in get_fields ()) {
     219            1 :                         f.check (context);
     220              :                 }
     221              : 
     222        54232 :                 foreach (Constant c in get_constants ()) {
     223            0 :                         c.check (context);
     224              :                 }
     225              : 
     226        54232 :                 if (context.abi_stability) {
     227          820 :                         foreach (Symbol s in get_members ()) {
     228          602 :                                 if (s is Method) {
     229          258 :                                         var m = (Method) s;
     230          258 :                                         m.check (context);
     231          258 :                                         if (m.is_virtual || m.is_abstract) {
     232          214 :                                                 virtuals.add (m);
     233              :                                         }
     234           86 :                                 } else if (s is Signal) {
     235            0 :                                         var sig = (Signal) s;
     236            0 :                                         sig.check (context);
     237            0 :                                         if (sig.is_virtual) {
     238            0 :                                                 virtuals.add (sig);
     239              :                                         }
     240          172 :                                 } else if (s is Property) {
     241           86 :                                         var prop = (Property) s;
     242           86 :                                         prop.check (context);
     243           86 :                                         if (prop.is_virtual || prop.is_abstract) {
     244           86 :                                                 virtuals.add (prop);
     245              :                                         }
     246              :                                 }
     247              :                         }
     248              :                 } else {
     249      1115866 :                         foreach (Method m in get_methods ()) {
     250       530883 :                                 m.check (context);
     251       530883 :                                 if (m.is_virtual || m.is_abstract) {
     252       348896 :                                         virtuals.add (m);
     253              :                                 }
     254              :                         }
     255              : 
     256       121022 :                         foreach (Signal sig in get_signals ()) {
     257        33461 :                                 sig.check (context);
     258        33461 :                                 if (sig.is_virtual) {
     259        31289 :                                         virtuals.add (sig);
     260              :                                 }
     261              :                         }
     262              : 
     263       145232 :                         foreach (Property prop in get_properties ()) {
     264        45566 :                                 prop.check (context);
     265        45566 :                                 if (prop.is_virtual || prop.is_abstract) {
     266        44636 :                                         virtuals.add (prop);
     267              :                                 }
     268              :                         }
     269              :                 }
     270              : 
     271        54236 :                 foreach (Class cl in get_classes ()) {
     272            2 :                         cl.check (context);
     273              :                 }
     274              : 
     275        54236 :                 foreach (Interface iface in get_interfaces ()) {
     276            2 :                         iface.check (context);
     277              :                 }
     278              : 
     279        54232 :                 foreach (Struct st in get_structs ()) {
     280            0 :                         st.check (context);
     281              :                 }
     282              : 
     283        54232 :                 foreach (Delegate d in get_delegates ()) {
     284            0 :                         d.check (context);
     285              :                 }
     286              : 
     287        54232 :                 Map<int, Symbol>? positions = new HashMap<int, Symbol> ();
     288        54232 :                 bool ordered_seen = false;
     289        54232 :                 bool unordered_seen = false;
     290       904474 :                 foreach (Symbol sym in virtuals) {
     291       425121 :                         int ordering = sym.get_attribute_integer ("CCode", "ordering", -1);
     292       425121 :                         if (ordering < -1) {
     293            0 :                                 Report.error (sym.source_reference, "%s: Invalid ordering", sym.get_full_name ());
     294              :                                 // Mark state as invalid
     295            0 :                                 error = true;
     296            0 :                                 ordered_seen = true;
     297            0 :                                 unordered_seen = true;
     298            0 :                                 continue;
     299              :                         }
     300       425121 :                         bool ordered = ordering != -1;
     301       425121 :                         if (ordered && unordered_seen && !ordered_seen) {
     302            0 :                                 Report.error (sym.source_reference, "%s: Cannot mix ordered and unordered virtuals", sym.get_full_name ());
     303            0 :                                 error = true;
     304              :                         }
     305       425121 :                         ordered_seen = ordered_seen || ordered;
     306       425121 :                         if (!ordered && !unordered_seen && ordered_seen) {
     307            0 :                                 Report.error (sym.source_reference, "%s: Cannot mix ordered and unordered virtuals", sym.get_full_name ());
     308            0 :                                 error = true;
     309              :                         }
     310       425121 :                         unordered_seen = unordered_seen || !ordered;
     311       425121 :                         if (!ordered_seen || !unordered_seen) {
     312       425121 :                                 if (ordered) {
     313            0 :                                         Symbol? prev = positions[ordering];
     314            0 :                                         if (prev != null) {
     315            0 :                                                 Report.error (sym.source_reference, "%s: Duplicate ordering (previous virtual with the same position is %s)", sym.get_full_name (), prev.name);
     316            0 :                                                 error = true;
     317              :                                         }
     318            0 :                                         positions[ordering] = sym;
     319              :                                 }
     320              :                         }
     321              :                 }
     322        54232 :                 if (ordered_seen) {
     323            0 :                         for (int i = 0; i < virtuals.size; i++) {
     324            0 :                                 Symbol? sym = positions[i];
     325            0 :                                 if (sym == null) {
     326            0 :                                         Report.error (source_reference, "%s: Gap in ordering in position %d", get_full_name (), i);
     327            0 :                                         error = true;
     328              :                                 }
     329            0 :                                 if (!error) {
     330            0 :                                         virtuals[i] = sym;
     331              :                                 }
     332              :                         }
     333              :                 }
     334              : 
     335        54232 :                 context.analyzer.current_source_file = old_source_file;
     336        54232 :                 context.analyzer.current_symbol = old_symbol;
     337              : 
     338        54232 :                 return !error;
     339              :         }
     340              : }
        

Generated by: LCOV version 2.0-1