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

            Line data    Source code
       1              : /* valacodewriter.vala
       2              :  *
       3              :  * Copyright (C) 2006-2014  Jürg Billeter
       4              :  * Copyright (C) 2006-2008  Raffaele Sandrini
       5              :  * Copyright (C) 2014       Richard Wiedenhöft
       6              :  *
       7              :  * This library is free software; you can redistribute it and/or
       8              :  * modify it under the terms of the GNU Lesser General Public
       9              :  * License as published by the Free Software Foundation; either
      10              :  * version 2.1 of the License, or (at your option) any later version.
      11              : 
      12              :  * This library is distributed in the hope that it will be useful,
      13              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15              :  * Lesser General Public License for more details.
      16              : 
      17              :  * You should have received a copy of the GNU Lesser General Public
      18              :  * License along with this library; if not, write to the Free Software
      19              :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
      20              :  *
      21              :  * Author:
      22              :  *      Jürg Billeter <j@bitron.ch>
      23              :  *      Raffaele Sandrini <raffaele@sandrini.ch>
      24              :  */
      25              : 
      26              : 
      27              : /**
      28              :  * Code visitor generating Vala API file for the public interface.
      29              :  */
      30           78 : public class Vala.CodeWriter : CodeVisitor {
      31              :         static GLib.Regex fix_indent_regex;
      32              : 
      33           78 :         private CodeContext context;
      34              : 
      35           78 :         FileStream stream;
      36              : 
      37              :         int indent;
      38              :         /* at begin of line */
      39           78 :         bool bol = true;
      40              : 
      41           78 :         Scope current_scope;
      42              : 
      43              :         CodeWriterType type;
      44              : 
      45           78 :         string? override_header = null;
      46           78 :         string? header_to_override = null;
      47              : 
      48          156 :         public CodeWriter (CodeWriterType type = CodeWriterType.EXTERNAL) {
      49           78 :                 this.type = type;
      50              :         }
      51              : 
      52              :         /**
      53              :          * Allows overriding of a specific cheader in the output
      54              :          * @param original original cheader to override
      55              :          * @param replacement cheader to replace original with
      56              :          */
      57            0 :         public void set_cheader_override (string original, string replacement)
      58              :         {
      59            0 :                 header_to_override = original;
      60            0 :                 override_header = replacement;
      61              :         }
      62              : 
      63              :         /**
      64              :          * Writes the public interface of the specified code context into the
      65              :          * specified file.
      66              :          *
      67              :          * @param context  a code context
      68              :          * @param filename a relative or absolute filename
      69              :          */
      70          156 :         public void write_file (CodeContext context, string filename) {
      71           78 :                 var file_exists = FileUtils.test (filename, FileTest.EXISTS);
      72           78 :                 var temp_filename = "%s.valatmp".printf (filename);
      73           78 :                 this.context = context;
      74              : 
      75           78 :                 if (file_exists) {
      76           28 :                         stream = FileStream.open (temp_filename, "w");
      77              :                 } else {
      78           50 :                         stream = FileStream.open (filename, "w");
      79              :                 }
      80              : 
      81           78 :                 if (stream == null) {
      82            0 :                         Report.error (null, "unable to open `%s' for writing", filename);
      83            0 :                         return;
      84              :                 }
      85              : 
      86          156 :                 var header = context.version_header ?
      87            0 :                         "/* %s generated by %s %s, do not modify. */".printf (Path.get_basename (filename), Environment.get_prgname (), Vala.BUILD_VERSION) :
      88           78 :                         "/* %s generated by %s, do not modify. */".printf (Path.get_basename (filename), Environment.get_prgname ());
      89           78 :                 write_string (header);
      90           78 :                 write_newline ();
      91           78 :                 write_newline ();
      92              : 
      93         3142 :                 current_scope = context.root.scope;
      94              : 
      95           78 :                 context.accept (this);
      96              : 
      97           78 :                 current_scope = null;
      98              : 
      99           78 :                 stream = null;
     100              : 
     101           78 :                 if (file_exists) {
     102           28 :                         var changed = true;
     103              : 
     104           28 :                         try {
     105           28 :                                 var old_file = new MappedFile (filename, false);
     106           28 :                                 var new_file = new MappedFile (temp_filename, false);
     107           28 :                                 var len = old_file.get_length ();
     108           28 :                                 if (len == new_file.get_length ()) {
     109           28 :                                         if (Memory.cmp (old_file.get_contents (), new_file.get_contents (), len) == 0) {
     110           28 :                                                 changed = false;
     111              :                                         }
     112              :                                 }
     113           28 :                                 old_file = null;
     114           28 :                                 new_file = null;
     115              :                         } catch (FileError e) {
     116              :                                 // assume changed if mmap comparison doesn't work
     117              :                         }
     118              : 
     119           28 :                         if (changed) {
     120            0 :                                 FileUtils.rename (temp_filename, filename);
     121              :                         } else {
     122           28 :                                 FileUtils.unlink (temp_filename);
     123              :                         }
     124              :                 }
     125              : 
     126              :         }
     127              : 
     128          356 :         public override void visit_using_directive (UsingDirective ns) {
     129         8779 :                 if (type == CodeWriterType.FAST) {
     130            1 :                         write_string ("using ");
     131              : 
     132            1 :                         var symbols = new GLib.List<UnresolvedSymbol> ();
     133         8818 :                         var sym = (UnresolvedSymbol) ns.namespace_symbol;
     134            2 :                         symbols.prepend (sym);
     135              : 
     136            1 :                         while ((sym = sym.inner) != null) {
     137            0 :                                 symbols.prepend (sym);
     138              :                         }
     139              : 
     140            1 :                         write_string (symbols.nth_data (0).name);
     141              : 
     142            1 :                         for (int i = 1; i < symbols.length (); i++) {
     143            0 :                                 write_string (".");
     144            0 :                                 write_string (symbols.nth_data (i).name);
     145              :                         }
     146              : 
     147            1 :                         write_string (";\n");
     148              :                 }
     149              :         }
     150              : 
     151          517 :         public override void visit_namespace (Namespace ns) {
     152          420 :                 if (ns.external_package) {
     153              :                         return;
     154              :                 }
     155              : 
     156          175 :                 if (ns.name == null)  {
     157           78 :                         ns.accept_children (this);
     158           78 :                         return;
     159              :                 }
     160              : 
     161         1014 :                 var comments = ns.get_comments ();
     162           97 :                 if (context.vapi_comments && comments.size > 0) {
     163            0 :                         bool first = true;
     164            0 :                         SourceReference? first_reference = null;
     165            0 :                         foreach (Comment comment in comments) {
     166            0 :                                 if (comment.source_reference.file.file_type == SourceFileType.SOURCE) {
     167            0 :                                         if (first) {
     168            0 :                                                 write_comment (comment);
     169            0 :                                                 first = false;
     170           30 :                                                 first_reference = comment.source_reference;
     171              :                                         } else {
     172            0 :                                                 Report.warning (comment.source_reference, "Comment describes namespace, that was already described by another comment.");
     173            0 :                                                 Report.notice (first_reference, "Previous comment was here.");
     174              :                                         }
     175              :                                 }
     176              :                         }
     177              :                 }
     178              : 
     179           97 :                 write_attributes (ns);
     180              : 
     181           97 :                 write_indent ();
     182           97 :                 write_string ("namespace ");
     183           97 :                 write_identifier (ns.name);
     184           97 :                 write_begin_block ();
     185              : 
     186          194 :                 current_scope = ns.scope;
     187              : 
     188           97 :                 visit_sorted (ns.get_namespaces ());
     189           97 :                 visit_sorted (ns.get_classes ());
     190           97 :                 visit_sorted (ns.get_interfaces ());
     191           97 :                 visit_sorted (ns.get_structs ());
     192           97 :                 visit_sorted (ns.get_enums ());
     193           97 :                 visit_sorted (ns.get_error_domains ());
     194           97 :                 visit_sorted (ns.get_delegates ());
     195           97 :                 visit_sorted (ns.get_fields ());
     196           97 :                 visit_sorted (ns.get_constants ());
     197           97 :                 visit_sorted (ns.get_methods ());
     198              : 
     199          194 :                 current_scope = current_scope.parent_scope;
     200              : 
     201           97 :                 write_end_block ();
     202           97 :                 write_newline ();
     203              :         }
     204              : 
     205         7294 :         private string get_cheaders (Symbol sym) {
     206         7294 :                 string cheaders = "";
     207        14588 :                 if (type != CodeWriterType.FAST && !sym.external_package) {
     208         7294 :                         cheaders = sym.get_attribute_string ("CCode", "cheader_filename") ?? "";
     209         7294 :                         if (cheaders == "" && sym.parent_symbol != null && sym.parent_symbol != context.root) {
     210         1478 :                                 cheaders = get_cheaders (sym.parent_symbol);
     211              :                         }
     212         7294 :                         if (cheaders == "" && sym.source_reference != null && !sym.external_package) {
     213         1296 :                                 cheaders = sym.source_reference.file.get_cinclude_filename ();
     214              :                         }
     215              : 
     216         7294 :                         if (header_to_override != null) {
     217            0 :                                 var cheaders_array = cheaders.split (",");
     218            0 :                                 for (int i = 0; i < cheaders_array.length; i++) {
     219            0 :                                         if (cheaders_array[i] == header_to_override) {
     220            0 :                                                 cheaders_array[i] = override_header;
     221              :                                         }
     222              :                                 }
     223            0 :                                 cheaders = string.joinv (",", cheaders_array);
     224              :                         }
     225              :                 }
     226              :                 return cheaders;
     227              :         }
     228              : 
     229         3363 :         public override void visit_class (Class cl) {
     230         2494 :                 if (cl.external_package) {
     231              :                         return;
     232              :                 }
     233              : 
     234          877 :                 if (!check_accessibility (cl)) {
     235              :                         return;
     236              :                 }
     237              : 
     238          869 :                 if (context.vapi_comments && cl.comment != null) {
     239            0 :                         write_comment (cl.comment);
     240              :                 }
     241              : 
     242          869 :                 write_attributes (cl);
     243              : 
     244          869 :                 write_indent ();
     245          869 :                 write_accessibility (cl);
     246          869 :                 if (cl.is_abstract) {
     247           34 :                         write_string ("abstract ");
     248              :                 }
     249          869 :                 if (cl.is_sealed) {
     250            4 :                         write_string ("sealed ");
     251              :                 }
     252          869 :                 write_string ("class ");
     253          869 :                 write_identifier (cl.name);
     254              : 
     255          869 :                 write_type_parameters (cl.get_type_parameters ());
     256              : 
     257          869 :                 var base_types = cl.get_base_types ();
     258          869 :                 if (base_types.size > 0) {
     259          539 :                         write_string (" : ");
     260              : 
     261          539 :                         bool first = true;
     262         2571 :                         foreach (DataType base_type in base_types) {
     263         1016 :                                 if (!first) {
     264          477 :                                         write_string (", ");
     265              :                                 } else {
     266              :                                         first = false;
     267              :                                 }
     268         1016 :                                 write_type (base_type);
     269              :                         }
     270              :                 }
     271          869 :                 write_begin_block ();
     272              : 
     273         1738 :                 current_scope = cl.scope;
     274              : 
     275          869 :                 visit_sorted (cl.get_classes ());
     276          869 :                 visit_sorted (cl.get_interfaces ());
     277          869 :                 visit_sorted (cl.get_structs ());
     278          869 :                 visit_sorted (cl.get_enums ());
     279          869 :                 visit_sorted (cl.get_delegates ());
     280          869 :                 visit_sorted (cl.get_fields ());
     281          869 :                 visit_sorted (cl.get_constants ());
     282          869 :                 visit_sorted (cl.get_methods ());
     283          869 :                 visit_sorted (cl.get_properties ());
     284          869 :                 visit_sorted (cl.get_signals ());
     285              : 
     286          869 :                 if (cl.constructor != null) {
     287            3 :                         cl.constructor.accept (this);
     288              :                 }
     289              : 
     290          869 :                 if (cl.class_constructor != null) {
     291            0 :                         cl.class_constructor.accept (this);
     292              :                 }
     293              : 
     294          869 :                 if (cl.static_constructor != null) {
     295            1 :                         cl.static_constructor.accept (this);
     296              :                 }
     297              : 
     298          869 :                 if (cl.destructor != null) {
     299            1 :                         cl.destructor.accept (this);
     300              :                 }
     301              : 
     302          869 :                 if (cl.static_destructor != null) {
     303            0 :                         cl.static_destructor.accept (this);
     304              :                 }
     305              : 
     306          869 :                 if (cl.class_destructor != null) {
     307            0 :                         cl.class_destructor.accept (this);
     308              :                 }
     309              : 
     310         1738 :                 current_scope = current_scope.parent_scope;
     311              : 
     312          869 :                 write_end_block ();
     313          869 :                 write_newline ();
     314              :         }
     315              : 
     316        20746 :         void visit_sorted (List<Symbol> symbols) {
     317        10401 :                 if (type != CodeWriterType.EXTERNAL && type != CodeWriterType.VAPIGEN) {
     318              :                         // order of virtual methods matters for fast vapis
     319          108 :                         foreach (Symbol sym in symbols) {
     320           26 :                                 sym.accept (this);
     321              :                         }
     322              :                         return;
     323              :                 }
     324              : 
     325        10345 :                 var sorted_symbols = new ArrayList<Symbol> ();
     326        10345 :                 sorted_symbols.add_all (symbols);
     327        57585 :                 sorted_symbols.sort ((a, b) => strcmp (a.name, b.name));
     328        57775 :                 foreach (Symbol sym in sorted_symbols) {
     329        23715 :                         sym.accept (this);
     330              :                 }
     331              :         }
     332              : 
     333         2793 :         public override void visit_struct (Struct st) {
     334         2793 :                 if (st.external_package) {
     335              :                         return;
     336              :                 }
     337              : 
     338           90 :                 if (!check_accessibility (st)) {
     339              :                         return;
     340              :                 }
     341              : 
     342           87 :                 if (context.vapi_comments && st.comment != null) {
     343            0 :                         write_comment (st.comment);
     344              :                 }
     345              : 
     346           87 :                 write_attributes (st);
     347              : 
     348           87 :                 write_indent ();
     349           87 :                 write_accessibility (st);
     350           87 :                 write_string ("struct ");
     351           87 :                 write_identifier (st.name);
     352              : 
     353           87 :                 write_type_parameters (st.get_type_parameters ());
     354              : 
     355           87 :                 if (st.base_type != null) {
     356            6 :                         write_string (" : ");
     357            6 :                         write_type (st.base_type);
     358              :                 }
     359              : 
     360           87 :                 write_begin_block ();
     361              : 
     362          174 :                 current_scope = st.scope;
     363              : 
     364          879 :                 foreach (Field field in st.get_fields ()) {
     365          396 :                         field.accept (this);
     366              :                 }
     367           87 :                 visit_sorted (st.get_constants ());
     368           87 :                 visit_sorted (st.get_methods ());
     369           87 :                 visit_sorted (st.get_properties ());
     370              : 
     371          174 :                 current_scope = current_scope.parent_scope;
     372              : 
     373           87 :                 write_end_block ();
     374           87 :                 write_newline ();
     375              :         }
     376              : 
     377          195 :         public override void visit_interface (Interface iface) {
     378          147 :                 if (iface.external_package) {
     379              :                         return;
     380              :                 }
     381              : 
     382           48 :                 if (!check_accessibility (iface)) {
     383              :                         return;
     384              :                 }
     385              : 
     386           48 :                 if (context.vapi_comments && iface.comment != null) {
     387            0 :                         write_comment (iface.comment);
     388              :                 }
     389              : 
     390           48 :                 write_attributes (iface);
     391              : 
     392           48 :                 write_indent ();
     393           48 :                 write_accessibility (iface);
     394           48 :                 write_string ("interface ");
     395           48 :                 write_identifier (iface.name);
     396              : 
     397           48 :                 write_type_parameters (iface.get_type_parameters ());
     398              : 
     399           48 :                 var prerequisites = iface.get_prerequisites ();
     400           48 :                 if (prerequisites.size > 0) {
     401           43 :                         write_string (" : ");
     402              : 
     403           43 :                         bool first = true;
     404          135 :                         foreach (DataType prerequisite in prerequisites) {
     405           46 :                                 if (!first) {
     406            3 :                                         write_string (", ");
     407              :                                 } else {
     408              :                                         first = false;
     409              :                                 }
     410           46 :                                 write_type (prerequisite);
     411              :                         }
     412              :                 }
     413           48 :                 write_begin_block ();
     414              : 
     415           96 :                 current_scope = iface.scope;
     416              : 
     417           48 :                 visit_sorted (iface.get_classes ());
     418           48 :                 visit_sorted (iface.get_interfaces ());
     419           48 :                 visit_sorted (iface.get_structs ());
     420           48 :                 visit_sorted (iface.get_enums ());
     421           48 :                 visit_sorted (iface.get_delegates ());
     422           48 :                 visit_sorted (iface.get_fields ());
     423           48 :                 visit_sorted (iface.get_constants ());
     424           48 :                 visit_sorted (iface.get_methods ());
     425           48 :                 visit_sorted (iface.get_properties ());
     426           48 :                 visit_sorted (iface.get_signals ());
     427              : 
     428           96 :                 current_scope = current_scope.parent_scope;
     429              : 
     430           48 :                 write_end_block ();
     431           48 :                 write_newline ();
     432              :         }
     433              : 
     434         1003 :         public override void visit_enum (Enum en) {
     435         1003 :                 if (en.external_package) {
     436              :                         return;
     437              :                 }
     438              : 
     439          418 :                 if (!check_accessibility (en)) {
     440              :                         return;
     441              :                 }
     442              : 
     443          413 :                 if (context.vapi_comments && en.comment != null) {
     444            0 :                         write_comment (en.comment);
     445              :                 }
     446              : 
     447          413 :                 write_attributes (en);
     448              : 
     449          413 :                 write_indent ();
     450          413 :                 write_accessibility (en);
     451          413 :                 write_string ("enum ");
     452          413 :                 write_identifier (en.name);
     453          413 :                 write_begin_block ();
     454              : 
     455          413 :                 bool first = true;
     456         5307 :                 foreach (EnumValue ev in en.get_values ()) {
     457         2447 :                         if (first) {
     458              :                                 first = false;
     459              :                         } else {
     460         2034 :                                 write_string (",");
     461         2034 :                                 write_newline ();
     462              :                         }
     463              : 
     464         2447 :                         if (context.vapi_comments && ev.comment != null) {
     465            0 :                                 write_comment (ev.comment);
     466              :                         }
     467              : 
     468         2447 :                         write_attributes (ev);
     469              : 
     470         2447 :                         write_indent ();
     471         2447 :                         write_identifier (ev.name);
     472              : 
     473         2447 :                         if (type == CodeWriterType.FAST && ev.value != null && ev.value.is_constant ()) {
     474            1 :                                 write_string(" = ");
     475            1 :                                 ev.value.accept (this);
     476              :                         }
     477              :                 }
     478              : 
     479          413 :                 if (!first) {
     480          413 :                         if (en.get_methods ().size > 0 || en.get_constants ().size > 0) {
     481            7 :                                 write_string (";");
     482              :                         }
     483          413 :                         write_newline ();
     484              :                 }
     485              : 
     486          826 :                 current_scope = en.scope;
     487          439 :                 foreach (Method m in en.get_methods ()) {
     488           13 :                         m.accept (this);
     489              :                 }
     490          413 :                 foreach (Constant c in en.get_constants ()) {
     491            0 :                         c.accept (this);
     492              :                 }
     493          826 :                 current_scope = current_scope.parent_scope;
     494              : 
     495          413 :                 write_end_block ();
     496          413 :                 write_newline ();
     497              :         }
     498              : 
     499           62 :         public override void visit_error_domain (ErrorDomain edomain) {
     500           62 :                 if (edomain.external_package) {
     501              :                         return;
     502              :                 }
     503              : 
     504           19 :                 if (!check_accessibility (edomain)) {
     505              :                         return;
     506              :                 }
     507              : 
     508           18 :                 if (context.vapi_comments && edomain.comment != null) {
     509            0 :                         write_comment (edomain.comment);
     510              :                 }
     511              : 
     512           18 :                 write_attributes (edomain);
     513              : 
     514           18 :                 write_indent ();
     515           18 :                 write_accessibility (edomain);
     516           18 :                 write_string ("errordomain ");
     517           18 :                 write_identifier (edomain.name);
     518           18 :                 write_begin_block ();
     519              : 
     520           18 :                 bool first = true;
     521          126 :                 foreach (ErrorCode ecode in edomain.get_codes ()) {
     522           54 :                         if (first) {
     523              :                                 first = false;
     524              :                         } else {
     525           36 :                                 write_string (",");
     526           36 :                                 write_newline ();
     527              :                         }
     528              : 
     529           54 :                         if (context.vapi_comments && ecode.comment != null) {
     530            0 :                                 write_comment (ecode.comment);
     531              :                         }
     532              : 
     533           54 :                         write_attributes (ecode);
     534              : 
     535           54 :                         write_indent ();
     536           54 :                         write_identifier (ecode.name);
     537              :                 }
     538              : 
     539           18 :                 if (!first) {
     540           18 :                         if (edomain.get_methods ().size > 0) {
     541            0 :                                 write_string (";");
     542              :                         }
     543           18 :                         write_newline ();
     544              :                 }
     545              : 
     546           36 :                 current_scope = edomain.scope;
     547           18 :                 foreach (Method m in edomain.get_methods ()) {
     548            0 :                         m.accept (this);
     549              :                 }
     550           36 :                 current_scope = current_scope.parent_scope;
     551              : 
     552           18 :                 write_end_block ();
     553           18 :                 write_newline ();
     554              :         }
     555              : 
     556         3281 :         public override void visit_constant (Constant c) {
     557         3281 :                 if (c.external_package) {
     558              :                         return;
     559              :                 }
     560              : 
     561         2717 :                 if (!check_accessibility (c)) {
     562              :                         return;
     563              :                 }
     564              : 
     565         2656 :                 if (context.vapi_comments && c.comment != null) {
     566            0 :                         write_comment (c.comment);
     567              :                 }
     568              : 
     569         2656 :                 write_attributes (c);
     570              : 
     571         2656 :                 write_indent ();
     572         2656 :                 write_accessibility (c);
     573              : 
     574         2656 :                 if (c.hides) {
     575            0 :                         write_string ("new ");
     576              :                 }
     577              : 
     578         2656 :                 write_string ("const ");
     579              : 
     580         2656 :                 write_type (c.type_reference);
     581              : 
     582         2656 :                 write_string (" ");
     583         2656 :                 write_identifier (c.name);
     584         2656 :                 write_type_suffix (c.type_reference);
     585         2656 :                 if (type == CodeWriterType.FAST && c.value != null && c.value.is_constant ()) {
     586            1 :                         write_string(" = ");
     587            1 :                         c.value.accept (this);
     588              :                 }
     589         2656 :                 write_string (";");
     590         2656 :                 write_newline ();
     591              :         }
     592              : 
     593         3322 :         public override void visit_field (Field f) {
     594         3322 :                 if (f.external_package) {
     595              :                         return;
     596              :                 }
     597              : 
     598         3215 :                 if (!check_accessibility (f)) {
     599              :                         return;
     600              :                 }
     601              : 
     602         2555 :                 if (context.vapi_comments && f.comment != null) {
     603            0 :                         write_comment (f.comment);
     604              :                 }
     605              : 
     606         2555 :                 write_attributes (f);
     607              : 
     608         2555 :                 write_indent ();
     609         2555 :                 write_accessibility (f);
     610              : 
     611         2555 :                 if (f.hides) {
     612            0 :                         write_string ("new ");
     613              :                 }
     614              : 
     615         2555 :                 if (f.binding == MemberBinding.STATIC) {
     616           85 :                         write_string ("static ");
     617         2470 :                 } else if (f.binding == MemberBinding.CLASS) {
     618            1 :                         write_string ("class ");
     619              :                 }
     620              : 
     621         2555 :                 if (f.variable_type.is_weak ()) {
     622         1088 :                         write_string ("weak ");
     623              :                 }
     624              : 
     625         2555 :                 write_type (f.variable_type);
     626              : 
     627         2555 :                 write_string (" ");
     628         2555 :                 write_identifier (f.name);
     629         2555 :                 write_type_suffix (f.variable_type);
     630         2555 :                 write_string (";");
     631         2555 :                 write_newline ();
     632              :         }
     633              : 
     634         9806 :         private void write_error_domains (List<DataType> error_domains) {
     635         9806 :                 if (error_domains.size > 0) {
     636          227 :                         write_string (" throws ");
     637              : 
     638          227 :                         bool first = true;
     639          683 :                         foreach (DataType type in error_domains) {
     640          228 :                                 if (!first) {
     641            1 :                                         write_string (", ");
     642              :                                 } else {
     643              :                                         first = false;
     644              :                                 }
     645              : 
     646          228 :                                 write_type (type);
     647              :                         }
     648              :                 }
     649              :         }
     650              : 
     651        10293 :         private void write_params (List<Parameter> params) {
     652        10293 :                 write_string ("(");
     653              : 
     654        10293 :                 int i = 1;
     655        35825 :                 foreach (Parameter param in params) {
     656        12806 :                         if (i > 1) {
     657         6194 :                                 write_string (", ");
     658              :                         }
     659              : 
     660        12806 :                         if (param.ellipsis) {
     661           80 :                                 write_string ("...");
     662           80 :                                 continue;
     663              :                         }
     664              : 
     665        12726 :                         write_attributes (param);
     666              : 
     667        12726 :                         if (param.params_array) {
     668            0 :                                 write_string ("params ");
     669              :                         }
     670              : 
     671        12726 :                         if (param.direction == ParameterDirection.IN) {
     672        12126 :                                 if (param.variable_type.value_owned) {
     673           58 :                                         write_string ("owned ");
     674              :                                 }
     675              :                         } else {
     676          600 :                                 if (param.direction == ParameterDirection.REF) {
     677           77 :                                         write_string ("ref ");
     678          523 :                                 } else if (param.direction == ParameterDirection.OUT) {
     679          523 :                                         write_string ("out ");
     680              :                                 }
     681          600 :                                 if (param.variable_type.is_weak ()) {
     682          117 :                                         write_string ("unowned ");
     683              :                                 }
     684              :                         }
     685              : 
     686        12726 :                         write_type (param.variable_type);
     687              : 
     688        12726 :                         write_string (" ");
     689        12726 :                         write_identifier (param.name);
     690        12726 :                         write_type_suffix (param.variable_type);
     691              : 
     692        12726 :                         if (param.initializer != null) {
     693          198 :                                 write_string (" = ");
     694          198 :                                 param.initializer.accept (this);
     695              :                         }
     696              : 
     697        12726 :                         i++;
     698              :                 }
     699              : 
     700        10293 :                 write_string (")");
     701              :         }
     702              : 
     703          745 :         public override void visit_delegate (Delegate cb) {
     704          551 :                 if (cb.external_package) {
     705              :                         return;
     706              :                 }
     707              : 
     708          196 :                 if (!check_accessibility (cb)) {
     709              :                         return;
     710              :                 }
     711              : 
     712          194 :                 if (context.vapi_comments && cb.comment != null) {
     713            0 :                         write_comment (cb.comment);
     714              :                 }
     715              : 
     716          194 :                 write_attributes (cb);
     717              : 
     718          194 :                 write_indent ();
     719              : 
     720          194 :                 write_accessibility (cb);
     721          194 :                 write_string ("delegate ");
     722              : 
     723          194 :                 write_return_type (cb.return_type);
     724              : 
     725          194 :                 write_string (" ");
     726          194 :                 write_identifier (cb.name);
     727              : 
     728          194 :                 write_type_parameters (cb.get_type_parameters ());
     729              : 
     730          194 :                 write_string (" ");
     731              : 
     732          194 :                 write_params (cb.get_parameters ());
     733              : 
     734          194 :                 var error_types = new ArrayList<DataType> ();
     735          194 :                 cb.get_error_types (error_types);
     736          194 :                 write_error_domains (error_types);
     737              : 
     738          194 :                 write_string (";");
     739              : 
     740          194 :                 write_newline ();
     741              :         }
     742              : 
     743            4 :         public override void visit_constructor (Constructor c) {
     744            4 :                 if (type != CodeWriterType.DUMP) {
     745              :                         return;
     746              :                 }
     747              : 
     748            0 :                 if (context.vapi_comments && c.comment != null) {
     749            0 :                         write_comment (c.comment);
     750              :                 }
     751              : 
     752            0 :                 write_indent ();
     753            0 :                 if (c.binding == MemberBinding.STATIC) {
     754            0 :                         write_string ("static ");
     755            0 :                 } else if (c.binding == MemberBinding.CLASS) {
     756            0 :                         write_string ("class ");
     757              :                 }
     758            0 :                 write_string ("construct");
     759            0 :                 write_code_block (c.body);
     760            0 :                 write_newline ();
     761              :         }
     762              : 
     763            1 :         public override void visit_destructor (Destructor d) {
     764            1 :                 if (type != CodeWriterType.DUMP) {
     765              :                         return;
     766              :                 }
     767              : 
     768            0 :                 if (context.vapi_comments && d.comment != null) {
     769            0 :                         write_comment (d.comment);
     770              :                 }
     771              : 
     772            0 :                 write_indent ();
     773            0 :                 if (d.binding == MemberBinding.STATIC) {
     774            0 :                         write_string ("static ");
     775            0 :                 } else if (d.binding == MemberBinding.CLASS) {
     776            0 :                         write_string ("class ");
     777              :                 }
     778            0 :                 write_string ("~");
     779            0 :                 var datatype = (TypeSymbol) d.parent_symbol;
     780            0 :                 write_identifier (datatype.name);
     781            0 :                 write_string (" () ");
     782            0 :                 write_code_block (d.body);
     783            0 :                 write_newline ();
     784              :         }
     785              : 
     786        20759 :         public override void visit_method (Method m) {
     787        11147 :                 if (m.external_package) {
     788              :                         return;
     789              :                 }
     790              : 
     791              :                 // don't write interface implementation unless it's an abstract or virtual method
     792        10230 :                 if (!check_accessibility (m) || (m.base_interface_method != null && !m.is_abstract && !m.is_virtual)) {
     793          618 :                         if (type != CodeWriterType.DUMP) {
     794              :                                 return;
     795              :                         }
     796              :                 }
     797              : 
     798         9612 :                 if (context.vapi_comments && m.comment != null) {
     799            0 :                         write_comment (m.comment);
     800              :                 }
     801              : 
     802         9612 :                 write_attributes (m);
     803              : 
     804         9612 :                 write_indent ();
     805         9612 :                 write_accessibility (m);
     806              : 
     807        10430 :                 if (m is CreationMethod) {
     808          818 :                         if (m.coroutine) {
     809            1 :                                 write_string ("async ");
     810              :                         }
     811              : 
     812          818 :                         var datatype = (TypeSymbol) m.parent_symbol;
     813          818 :                         write_identifier (datatype.name);
     814          818 :                         if (m.name != ".new") {
     815          193 :                                 write_string (".");
     816          193 :                                 write_identifier (m.name);
     817              :                         }
     818          818 :                         write_string (" ");
     819              :                 } else {
     820         8794 :                         if (m.hides) {
     821            1 :                                 write_string ("new ");
     822              :                         }
     823              : 
     824         8794 :                         if (m.binding == MemberBinding.STATIC) {
     825         2096 :                                 write_string ("static ");
     826         6698 :                         } else if (m.binding == MemberBinding.CLASS) {
     827            7 :                                 write_string ("class ");
     828         6691 :                         } else if (m.is_abstract) {
     829          210 :                                 write_string ("abstract ");
     830         6481 :                         } else if (m.is_virtual) {
     831          389 :                                 write_string ("virtual ");
     832         6092 :                         } else if (m.overrides) {
     833          547 :                                 write_string ("override ");
     834              :                         }
     835              : 
     836         8794 :                         if (m.coroutine) {
     837           21 :                                 write_string ("async ");
     838              :                         }
     839              : 
     840         8794 :                         write_return_type (m.return_type);
     841         8794 :                         write_string (" ");
     842              : 
     843         8794 :                         write_identifier (m.name);
     844              : 
     845         8794 :                         write_type_parameters (m.get_type_parameters ());
     846              : 
     847         8794 :                         write_string (" ");
     848              :                 }
     849              : 
     850         9612 :                 write_params (m.get_parameters ());
     851              : 
     852         9612 :                 var error_types = new ArrayList<DataType> ();
     853         9612 :                 m.get_error_types (error_types);
     854         9612 :                 write_error_domains (error_types);
     855              : 
     856         9612 :                 write_code_block (m.body);
     857              : 
     858         9612 :                 write_newline ();
     859              :         }
     860              : 
     861          842 :         public override void visit_creation_method (CreationMethod m) {
     862          842 :                 visit_method (m);
     863              :         }
     864              : 
     865         1809 :         public override void visit_property (Property prop) {
     866         1809 :                 if (!check_accessibility (prop) || (prop.base_interface_property != null && !prop.is_abstract && !prop.is_virtual)) {
     867           26 :                         return;
     868              :                 }
     869              : 
     870         1783 :                 if (context.vapi_comments && prop.comment != null) {
     871            0 :                         write_comment (prop.comment);
     872              :                 }
     873              : 
     874         1783 :                 write_attributes (prop);
     875              : 
     876         1783 :                 write_indent ();
     877         1783 :                 write_accessibility (prop);
     878              : 
     879         1783 :                 if (prop.hides) {
     880            0 :                         write_string ("new ");
     881              :                 }
     882              : 
     883         1783 :                 if (prop.binding == MemberBinding.STATIC) {
     884            0 :                         write_string ("static ");
     885         1783 :                 } else  if (prop.is_abstract) {
     886           11 :                         write_string ("abstract ");
     887         1772 :                 } else if (prop.is_virtual) {
     888            0 :                         write_string ("virtual ");
     889         1772 :                 } else if (prop.overrides) {
     890           20 :                         write_string ("override ");
     891              :                 }
     892              : 
     893         1783 :                 if (prop.property_type.is_weak ()) {
     894           13 :                         write_string ("weak ");
     895              :                 }
     896              : 
     897         1783 :                 write_type (prop.property_type);
     898              : 
     899         1783 :                 write_string (" ");
     900         1783 :                 write_identifier (prop.name);
     901         1783 :                 write_string (" {");
     902         1783 :                 if (prop.get_accessor != null) {
     903         1723 :                         write_attributes (prop.get_accessor);
     904              : 
     905         1723 :                         write_property_accessor_accessibility (prop.get_accessor);
     906              : 
     907         1723 :                         if (prop.get_accessor.value_type.value_owned) {
     908          207 :                                 write_string (" owned");
     909              :                         }
     910              : 
     911         1723 :                         write_string (" get");
     912         1723 :                         write_code_block (prop.get_accessor.body);
     913              :                 }
     914         1783 :                 if (prop.set_accessor != null) {
     915         1578 :                         write_attributes (prop.set_accessor);
     916              : 
     917         1578 :                         write_property_accessor_accessibility (prop.set_accessor);
     918              : 
     919         1578 :                         if (prop.set_accessor.value_type.value_owned) {
     920            0 :                                 write_string (" owned");
     921              :                         }
     922              : 
     923         1578 :                         if (prop.set_accessor.writable) {
     924         1469 :                                 write_string (" set");
     925              :                         }
     926         1578 :                         if (prop.set_accessor.construction) {
     927          194 :                                 write_string (" construct");
     928              :                         }
     929         1578 :                         write_code_block (prop.set_accessor.body);
     930              :                 }
     931         1783 :                 write_string (" }");
     932         1783 :                 write_newline ();
     933              :         }
     934              : 
     935          487 :         public override void visit_signal (Signal sig) {
     936          487 :                 if (!check_accessibility (sig)) {
     937              :                         return;
     938              :                 }
     939              : 
     940          487 :                 if (context.vapi_comments && sig.comment != null) {
     941            0 :                         write_comment (sig.comment);
     942              :                 }
     943              : 
     944          487 :                 write_attributes (sig);
     945              : 
     946          487 :                 write_indent ();
     947          487 :                 write_accessibility (sig);
     948              : 
     949          487 :                 if (sig.hides) {
     950            0 :                         write_string ("new ");
     951              :                 }
     952              : 
     953          487 :                 if (sig.is_virtual) {
     954          437 :                         write_string ("virtual ");
     955              :                 }
     956              : 
     957          487 :                 write_string ("signal ");
     958              : 
     959          487 :                 write_return_type (sig.return_type);
     960              : 
     961          487 :                 write_string (" ");
     962          487 :                 write_identifier (sig.name);
     963              : 
     964          487 :                 write_string (" ");
     965              : 
     966          487 :                 write_params (sig.get_parameters ());
     967              : 
     968          487 :                 write_string (";");
     969              : 
     970          487 :                 write_newline ();
     971              :         }
     972              : 
     973            0 :         public override void visit_block (Block b) {
     974            0 :                 write_begin_block ();
     975              : 
     976            0 :                 foreach (Statement stmt in b.get_statements ()) {
     977            0 :                         stmt.accept (this);
     978              :                 }
     979              : 
     980            0 :                 write_end_block ();
     981            0 :                 if (b.parent_node is Block) {
     982            0 :                         write_newline ();
     983              :                 }
     984              :         }
     985              : 
     986            0 :         public override void visit_empty_statement (EmptyStatement stmt) {
     987              :         }
     988              : 
     989            0 :         public override void visit_declaration_statement (DeclarationStatement stmt) {
     990            0 :                 write_indent ();
     991            0 :                 stmt.declaration.accept (this);
     992            0 :                 write_string (";");
     993            0 :                 write_newline ();
     994              :         }
     995              : 
     996            0 :         public override void visit_local_variable (LocalVariable local) {
     997            0 :                 if (local.variable_type.is_weak ()) {
     998            0 :                         write_string ("unowned ");
     999              :                 }
    1000            0 :                 write_type (local.variable_type);
    1001            0 :                 write_string (" ");
    1002            0 :                 write_identifier (local.name);
    1003            0 :                 write_type_suffix (local.variable_type);
    1004            0 :                 if (local.initializer != null) {
    1005            0 :                         write_string (" = ");
    1006            0 :                         local.initializer.accept (this);
    1007              :                 }
    1008              :         }
    1009              : 
    1010            0 :         public override void visit_initializer_list (InitializerList list) {
    1011            0 :                 write_string ("{");
    1012              : 
    1013            0 :                 bool first = true;
    1014            0 :                 foreach (Expression initializer in list.get_initializers ()) {
    1015            0 :                         if (!first) {
    1016            0 :                                 write_string (", ");
    1017              :                         } else {
    1018            0 :                                 write_string (" ");
    1019              :                         }
    1020            0 :                         first = false;
    1021            0 :                         initializer.accept (this);
    1022              :                 }
    1023            0 :                 write_string (" }");
    1024              :         }
    1025              : 
    1026            0 :         public override void visit_expression_statement (ExpressionStatement stmt) {
    1027            0 :                 write_indent ();
    1028            0 :                 stmt.expression.accept (this);
    1029            0 :                 write_string (";");
    1030            0 :                 write_newline ();
    1031              :         }
    1032              : 
    1033            0 :         public override void visit_if_statement (IfStatement stmt) {
    1034            0 :                 write_indent ();
    1035            0 :                 write_string ("if (");
    1036            0 :                 stmt.condition.accept (this);
    1037            0 :                 write_string (")");
    1038            0 :                 stmt.true_statement.accept (this);
    1039            0 :                 if (stmt.false_statement != null) {
    1040            0 :                         write_string (" else");
    1041            0 :                         stmt.false_statement.accept (this);
    1042              :                 }
    1043            0 :                 write_newline ();
    1044              :         }
    1045              : 
    1046            0 :         public override void visit_switch_statement (SwitchStatement stmt) {
    1047            0 :                 write_indent ();
    1048            0 :                 write_string ("switch (");
    1049            0 :                 stmt.expression.accept (this);
    1050            0 :                 write_string (") {");
    1051            0 :                 write_newline ();
    1052              : 
    1053            0 :                 foreach (SwitchSection section in stmt.get_sections ()) {
    1054            0 :                         section.accept (this);
    1055              :                 }
    1056              : 
    1057            0 :                 write_indent ();
    1058            0 :                 write_string ("}");
    1059            0 :                 write_newline ();
    1060              :         }
    1061              : 
    1062            0 :         public override void visit_switch_section (SwitchSection section) {
    1063            0 :                 foreach (SwitchLabel label in section.get_labels ()) {
    1064            0 :                         label.accept (this);
    1065              :                 }
    1066              : 
    1067            0 :                 visit_block (section);
    1068              :         }
    1069              : 
    1070            0 :         public override void visit_switch_label (SwitchLabel label) {
    1071            0 :                 if (label.expression != null) {
    1072            0 :                         write_indent ();
    1073            0 :                         write_string ("case ");
    1074            0 :                         label.expression.accept (this);
    1075            0 :                         write_string (":");
    1076            0 :                         write_newline ();
    1077              :                 } else {
    1078            0 :                         write_indent ();
    1079            0 :                         write_string ("default:");
    1080            0 :                         write_newline ();
    1081              :                 }
    1082              :         }
    1083              : 
    1084            0 :         public override void visit_loop_statement (LoopStatement stmt) {
    1085            0 :                 write_indent ();
    1086            0 :                 write_string ("while (");
    1087            0 :                 stmt.condition.accept (this);
    1088            0 :                 write_string (")");
    1089            0 :                 stmt.body.accept (this);
    1090            0 :                 write_newline ();
    1091              :         }
    1092              : 
    1093            0 :         public override void visit_while_statement (WhileStatement stmt) {
    1094            0 :                 write_indent ();
    1095            0 :                 write_string ("while (");
    1096            0 :                 stmt.condition.accept (this);
    1097            0 :                 write_string (")");
    1098            0 :                 stmt.body.accept (this);
    1099            0 :                 write_newline ();
    1100              :         }
    1101              : 
    1102            0 :         public override void visit_do_statement (DoStatement stmt) {
    1103            0 :                 write_indent ();
    1104            0 :                 write_string ("do");
    1105            0 :                 stmt.body.accept (this);
    1106            0 :                 write_string ("while (");
    1107            0 :                 stmt.condition.accept (this);
    1108            0 :                 write_string (");");
    1109            0 :                 write_newline ();
    1110              :         }
    1111              : 
    1112            0 :         public override void visit_for_statement (ForStatement stmt) {
    1113            0 :                 write_indent ();
    1114            0 :                 write_string ("for (");
    1115              : 
    1116            0 :                 bool first = true;
    1117            0 :                 foreach (Expression initializer in stmt.get_initializer ()) {
    1118            0 :                         if (!first) {
    1119            0 :                                 write_string (", ");
    1120              :                         }
    1121            0 :                         first = false;
    1122            0 :                         initializer.accept (this);
    1123              :                 }
    1124            0 :                 write_string ("; ");
    1125              : 
    1126            0 :                 stmt.condition.accept (this);
    1127            0 :                 write_string ("; ");
    1128              : 
    1129            0 :                 first = true;
    1130            0 :                 foreach (Expression iterator in stmt.get_iterator ()) {
    1131            0 :                         if (!first) {
    1132            0 :                                 write_string (", ");
    1133              :                         }
    1134            0 :                         first = false;
    1135            0 :                         iterator.accept (this);
    1136              :                 }
    1137              : 
    1138            0 :                 write_string (")");
    1139            0 :                 stmt.body.accept (this);
    1140            0 :                 write_newline ();
    1141              :         }
    1142              : 
    1143            0 :         public override void visit_foreach_statement (ForeachStatement stmt) {
    1144            0 :                 write_indent ();
    1145            0 :                 write_string ("foreach (");
    1146            0 :                 write_type (stmt.type_reference);
    1147            0 :                 write_string (" ");
    1148            0 :                 write_string (stmt.variable_name);
    1149            0 :                 write_string (" in ");
    1150            0 :                 stmt.collection.accept (this);
    1151            0 :                 write_string (")");
    1152            0 :                 stmt.body.accept (this);
    1153              :         }
    1154              : 
    1155            0 :         public override void visit_break_statement (BreakStatement stmt) {
    1156            0 :                 write_indent ();
    1157            0 :                 write_string ("break;");
    1158            0 :                 write_newline ();
    1159              :         }
    1160              : 
    1161            0 :         public override void visit_continue_statement (ContinueStatement stmt) {
    1162            0 :                 write_indent ();
    1163            0 :                 write_string ("continue;");
    1164            0 :                 write_newline ();
    1165              :         }
    1166              : 
    1167            0 :         public override void visit_return_statement (ReturnStatement stmt) {
    1168            0 :                 write_indent ();
    1169            0 :                 write_string ("return");
    1170            0 :                 if (stmt.return_expression != null) {
    1171            0 :                         write_string (" ");
    1172            0 :                         stmt.return_expression.accept (this);
    1173              :                 }
    1174            0 :                 write_string (";");
    1175            0 :                 write_newline ();
    1176              :         }
    1177              : 
    1178            0 :         public override void visit_with_statement (WithStatement stmt) {
    1179            0 :                 write_indent ();
    1180            0 :                 write_string ("with (");
    1181            0 :                 stmt.expression.accept (this);
    1182            0 :                 write_string (")");
    1183            0 :                 stmt.body.accept (this);
    1184            0 :                 write_newline ();
    1185              :         }
    1186              : 
    1187            0 :         public override void visit_yield_statement (YieldStatement y) {
    1188            0 :                 write_indent ();
    1189            0 :                 write_string ("yield");
    1190            0 :                 write_string (";");
    1191            0 :                 write_newline ();
    1192              :         }
    1193              : 
    1194            0 :         public override void visit_throw_statement (ThrowStatement stmt) {
    1195            0 :                 write_indent ();
    1196            0 :                 write_string ("throw");
    1197            0 :                 if (stmt.error_expression != null) {
    1198            0 :                         write_string (" ");
    1199            0 :                         stmt.error_expression.accept (this);
    1200              :                 }
    1201            0 :                 write_string (";");
    1202            0 :                 write_newline ();
    1203              :         }
    1204              : 
    1205            0 :         public override void visit_try_statement (TryStatement stmt) {
    1206            0 :                 write_indent ();
    1207            0 :                 write_string ("try");
    1208            0 :                 stmt.body.accept (this);
    1209            0 :                 foreach (var clause in stmt.get_catch_clauses ()) {
    1210            0 :                         clause.accept (this);
    1211              :                 }
    1212            0 :                 if (stmt.finally_body != null) {
    1213            0 :                         write_string (" finally");
    1214            0 :                         stmt.finally_body.accept (this);
    1215              :                 }
    1216            0 :                 write_newline ();
    1217              :         }
    1218              : 
    1219            0 :         public override void visit_catch_clause (CatchClause clause) {
    1220            0 :                 if (clause.variable_name != null) {
    1221            0 :                         var type_name = clause.error_type == null ? "GLib.Error" : clause.error_type.to_string ();
    1222            0 :                         write_string (" catch (%s %s)".printf (type_name, clause.variable_name));
    1223              :                 } else {
    1224            0 :                         write_string (" catch");
    1225              :                 }
    1226            0 :                 clause.body.accept (this);
    1227              :         }
    1228              : 
    1229            0 :         public override void visit_lock_statement (LockStatement stmt) {
    1230            0 :                 write_indent ();
    1231            0 :                 write_string ("lock (");
    1232            0 :                 stmt.resource.accept (this);
    1233            0 :                 write_string (")");
    1234            0 :                 if (stmt.body == null) {
    1235            0 :                         write_string (";");
    1236              :                 } else {
    1237            0 :                         stmt.body.accept (this);
    1238              :                 }
    1239            0 :                 write_newline ();
    1240              :         }
    1241              : 
    1242            0 :         public override void visit_unlock_statement (UnlockStatement stmt) {
    1243            0 :                 write_indent ();
    1244            0 :                 write_string ("unlock (");
    1245            0 :                 stmt.resource.accept (this);
    1246            0 :                 write_string (");");
    1247            0 :                 write_newline ();
    1248              :         }
    1249              : 
    1250            0 :         public override void visit_delete_statement (DeleteStatement stmt) {
    1251            0 :                 write_indent ();
    1252            0 :                 write_string ("delete ");
    1253            0 :                 stmt.expression.accept (this);
    1254            0 :                 write_string (";");
    1255            0 :                 write_newline ();
    1256              :         }
    1257              : 
    1258            0 :         public override void visit_array_creation_expression (ArrayCreationExpression expr) {
    1259            0 :                 write_string ("new ");
    1260            0 :                 write_type (expr.element_type);
    1261            0 :                 write_string ("[");
    1262              : 
    1263            0 :                 bool first = true;
    1264            0 :                 foreach (Expression size in expr.get_sizes ()) {
    1265            0 :                         if (!first) {
    1266            0 :                                 write_string (", ");
    1267              :                         }
    1268            0 :                         first = false;
    1269              : 
    1270            0 :                         size.accept (this);
    1271              :                 }
    1272              : 
    1273            0 :                 write_string ("]");
    1274              : 
    1275            0 :                 if (expr.initializer_list != null) {
    1276            0 :                         write_string (" ");
    1277            0 :                         expr.initializer_list.accept (this);
    1278              :                 }
    1279              :         }
    1280              : 
    1281           46 :         public override void visit_boolean_literal (BooleanLiteral lit) {
    1282           46 :                 write_string (lit.value.to_string ());
    1283              :         }
    1284              : 
    1285            0 :         public override void visit_character_literal (CharacterLiteral lit) {
    1286            0 :                 write_string (lit.value);
    1287              :         }
    1288              : 
    1289           26 :         public override void visit_integer_literal (IntegerLiteral lit) {
    1290           26 :                 write_string (lit.value);
    1291              :         }
    1292              : 
    1293            3 :         public override void visit_real_literal (RealLiteral lit) {
    1294            3 :                 write_string (lit.value);
    1295              :         }
    1296              : 
    1297            3 :         public override void visit_string_literal (StringLiteral lit) {
    1298            3 :                 write_string (lit.value);
    1299              :         }
    1300              : 
    1301          124 :         public override void visit_null_literal (NullLiteral lit) {
    1302          124 :                 write_string ("null");
    1303              :         }
    1304              : 
    1305           10 :         public override void visit_member_access (MemberAccess expr) {
    1306           10 :                 if (expr.inner != null) {
    1307            6 :                         expr.inner.accept (this);
    1308            6 :                         write_string (".");
    1309              :                 }
    1310           10 :                 write_identifier (expr.member_name);
    1311              :         }
    1312              : 
    1313            0 :         public override void visit_method_call (MethodCall expr) {
    1314            0 :                 if (expr.is_yield_expression) {
    1315            0 :                         write_string ("yield ");
    1316              :                 }
    1317              : 
    1318            0 :                 expr.call.accept (this);
    1319            0 :                 write_string (" (");
    1320              : 
    1321            0 :                 bool first = true;
    1322            0 :                 foreach (Expression arg in expr.get_argument_list ()) {
    1323            0 :                         if (!first) {
    1324            0 :                                 write_string (", ");
    1325              :                         }
    1326            0 :                         first = false;
    1327              : 
    1328            0 :                         arg.accept (this);
    1329              :                 }
    1330              : 
    1331            0 :                 write_string (")");
    1332              :         }
    1333              : 
    1334            0 :         public override void visit_element_access (ElementAccess expr) {
    1335            0 :                 expr.container.accept (this);
    1336            0 :                 write_string ("[");
    1337              : 
    1338            0 :                 bool first = true;
    1339            0 :                 foreach (Expression index in expr.get_indices ()) {
    1340            0 :                         if (!first) {
    1341            0 :                                 write_string (", ");
    1342              :                         }
    1343            0 :                         first = false;
    1344              : 
    1345            0 :                         index.accept (this);
    1346              :                 }
    1347              : 
    1348            0 :                 write_string ("]");
    1349              :         }
    1350              : 
    1351            0 :         public override void visit_slice_expression (SliceExpression expr) {
    1352            0 :                 expr.container.accept (this);
    1353            0 :                 write_string ("[");
    1354            0 :                 expr.start.accept (this);
    1355            0 :                 write_string (":");
    1356            0 :                 expr.stop.accept (this);
    1357            0 :                 write_string ("]");
    1358              :         }
    1359              : 
    1360            0 :         public override void visit_base_access (BaseAccess expr) {
    1361            0 :                 write_string ("base");
    1362              :         }
    1363              : 
    1364            0 :         public override void visit_postfix_expression (PostfixExpression expr) {
    1365            0 :                 expr.inner.accept (this);
    1366            0 :                 if (expr.increment) {
    1367            0 :                         write_string ("++");
    1368              :                 } else {
    1369            0 :                         write_string ("--");
    1370              :                 }
    1371              :         }
    1372              : 
    1373            0 :         public override void visit_object_creation_expression (ObjectCreationExpression expr) {
    1374            0 :                 if (expr.is_yield_expression) {
    1375            0 :                         write_string ("yield ");
    1376              :                 }
    1377              : 
    1378            0 :                 if (!expr.struct_creation) {
    1379            0 :                         write_string ("new ");
    1380              :                 }
    1381              : 
    1382            0 :                 write_type (expr.type_reference);
    1383              : 
    1384            0 :                 if (expr.symbol_reference.name != ".new") {
    1385            0 :                         write_string (".");
    1386            0 :                         write_string (expr.symbol_reference.name);
    1387              :                 }
    1388              : 
    1389            0 :                 write_string (" (");
    1390              : 
    1391            0 :                 bool first = true;
    1392            0 :                 foreach (Expression arg in expr.get_argument_list ()) {
    1393            0 :                         if (!first) {
    1394            0 :                                 write_string (", ");
    1395              :                         }
    1396            0 :                         first = false;
    1397              : 
    1398            0 :                         arg.accept (this);
    1399              :                 }
    1400              : 
    1401            0 :                 write_string (")");
    1402              :         }
    1403              : 
    1404            0 :         public override void visit_sizeof_expression (SizeofExpression expr) {
    1405            0 :                 write_string ("sizeof (");
    1406            0 :                 write_type (expr.type_reference);
    1407            0 :                 write_string (")");
    1408              :         }
    1409              : 
    1410            0 :         public override void visit_typeof_expression (TypeofExpression expr) {
    1411            0 :                 write_string ("typeof (");
    1412            0 :                 write_type (expr.type_reference);
    1413            0 :                 write_string (")");
    1414              :         }
    1415              : 
    1416            0 :         public override void visit_unary_expression (UnaryExpression expr) {
    1417            0 :                 write_string (expr.operator.to_string ());
    1418            0 :                 expr.inner.accept (this);
    1419              :         }
    1420              : 
    1421            0 :         public override void visit_cast_expression (CastExpression expr) {
    1422            0 :                 if (expr.is_non_null_cast) {
    1423            0 :                         write_string ("(!) ");
    1424            0 :                         expr.inner.accept (this);
    1425            0 :                         return;
    1426              :                 }
    1427              : 
    1428            0 :                 if (!expr.is_silent_cast) {
    1429            0 :                         write_string ("(");
    1430            0 :                         write_type (expr.type_reference);
    1431            0 :                         write_string (") ");
    1432              :                 }
    1433              : 
    1434            0 :                 expr.inner.accept (this);
    1435              : 
    1436            0 :                 if (expr.is_silent_cast) {
    1437            0 :                         write_string (" as ");
    1438            0 :                         write_type (expr.type_reference);
    1439              :                 }
    1440              :         }
    1441              : 
    1442            0 :         public override void visit_pointer_indirection (PointerIndirection expr) {
    1443            0 :                 write_string ("(*");
    1444            0 :                 expr.inner.accept (this);
    1445            0 :                 write_string (")");
    1446              :         }
    1447              : 
    1448            0 :         public override void visit_addressof_expression (AddressofExpression expr) {
    1449            0 :                 write_string ("(&");
    1450            0 :                 expr.inner.accept (this);
    1451            0 :                 write_string (")");
    1452              :         }
    1453              : 
    1454            0 :         public override void visit_reference_transfer_expression (ReferenceTransferExpression expr) {
    1455            0 :                 write_string ("(owned) ");
    1456            0 :                 expr.inner.accept (this);
    1457              :         }
    1458              : 
    1459            0 :         public override void visit_binary_expression (BinaryExpression expr) {
    1460            0 :                 expr.left.accept (this);
    1461            0 :                 write_string (" ");
    1462            0 :                 write_string (expr.operator.to_string ());
    1463            0 :                 write_string (" ");
    1464            0 :                 expr.right.accept (this);
    1465              :         }
    1466              : 
    1467            0 :         public override void visit_type_check (TypeCheck expr) {
    1468            0 :                 expr.expression.accept (this);
    1469            0 :                 write_string (" is ");
    1470            0 :                 write_type (expr.type_reference);
    1471              :         }
    1472              : 
    1473            0 :         public override void visit_conditional_expression (ConditionalExpression expr) {
    1474            0 :                 expr.condition.accept (this);
    1475            0 :                 write_string ("?");
    1476            0 :                 expr.true_expression.accept (this);
    1477            0 :                 write_string (":");
    1478            0 :                 expr.false_expression.accept (this);
    1479              :         }
    1480              : 
    1481            0 :         public override void visit_lambda_expression (LambdaExpression expr) {
    1482            0 :                 write_string ("(");
    1483            0 :                 var params = expr.get_parameters ();
    1484            0 :                 int i = 1;
    1485            0 :                 foreach (var param in params) {
    1486            0 :                         if (i > 1) {
    1487            0 :                                 write_string (", ");
    1488              :                         }
    1489              : 
    1490            0 :                         if (param.direction == ParameterDirection.REF) {
    1491            0 :                                 write_string ("ref ");
    1492            0 :                         } else if (param.direction == ParameterDirection.OUT) {
    1493            0 :                                 write_string ("out ");
    1494              :                         }
    1495              : 
    1496            0 :                         write_identifier (param.name);
    1497              : 
    1498            0 :                         i++;
    1499              :                 }
    1500            0 :                 write_string (") =>");
    1501            0 :                 if (expr.statement_body != null) {
    1502            0 :                         expr.statement_body.accept (this);
    1503            0 :                 } else if (expr.expression_body != null) {
    1504            0 :                         expr.expression_body.accept (this);
    1505              :                 }
    1506              :         }
    1507              : 
    1508            0 :         public override void visit_assignment (Assignment a) {
    1509            0 :                 a.left.accept (this);
    1510            0 :                 write_string (" = ");
    1511            0 :                 a.right.accept (this);
    1512              :         }
    1513              : 
    1514        31164 :         private void write_indent () {
    1515        31164 :                 if (!bol) {
    1516            1 :                         stream.putc ('\n');
    1517              :                 }
    1518              : 
    1519        31164 :                 stream.puts (string.nfill (indent, '\t'));
    1520        31164 :                 bol = false;
    1521              :         }
    1522              : 
    1523            0 :         private void write_comment (Comment comment) {
    1524            0 :                 try {
    1525            0 :                         if (fix_indent_regex == null)
    1526            0 :                                 fix_indent_regex = new Regex ("\\n[\\t ]*");
    1527              :                 } catch (Error e) {
    1528            0 :                         assert_not_reached ();
    1529              :                 }
    1530              : 
    1531            0 :                 string replacement = "\n%s ".printf (string.nfill (indent, '\t'));
    1532              :                 string fixed_content;
    1533            0 :                 try {
    1534            0 :                         fixed_content = fix_indent_regex.replace (comment.content, comment.content.length, 0, replacement);
    1535              :                 } catch (Error e) {
    1536            0 :                         assert_not_reached();
    1537              :                 }
    1538              : 
    1539            0 :                 write_indent ();
    1540            0 :                 write_string ("/*");
    1541            0 :                 write_string (fixed_content);
    1542            0 :                 write_string ("*/");
    1543              :         }
    1544              : 
    1545        34256 :         private void write_identifier (string s) {
    1546        34256 :                 char* id = (char*)s;
    1547        34256 :                 int id_length = (int)s.length;
    1548        34256 :                 if (Vala.Scanner.get_identifier_or_keyword (id, id_length) != Vala.TokenType.IDENTIFIER ||
    1549        34136 :                     s.get_char ().isdigit ()) {
    1550          163 :                         stream.putc ('@');
    1551              :                 }
    1552        34256 :                 write_string (s);
    1553              :         }
    1554              : 
    1555         9475 :         private void write_return_type (DataType type) {
    1556         9475 :                 if (type.is_weak ()) {
    1557         1715 :                         write_string ("unowned ");
    1558              :                 }
    1559              : 
    1560         9475 :                 write_type (type);
    1561              :         }
    1562              : 
    1563        30491 :         private void write_type (DataType type) {
    1564        30491 :                 write_string (type.to_qualified_string (current_scope));
    1565              :         }
    1566              : 
    1567        17937 :         private void write_type_suffix (DataType type) {
    1568        17937 :                 unowned ArrayType? array_type = type as ArrayType;
    1569          335 :                 if (array_type != null && array_type.fixed_length) {
    1570            6 :                         write_string ("[");
    1571            6 :                         array_type.length.accept (this);
    1572            6 :                         var length_type = array_type.length_type.to_qualified_string (current_scope);
    1573            6 :                         if (length_type != "int") {
    1574            0 :                                 write_string (":");
    1575            0 :                                 write_string (length_type);
    1576              :                         }
    1577            6 :                         write_string ("]");
    1578              :                 }
    1579              :         }
    1580              : 
    1581       211182 :         private void write_string (string s) {
    1582       211182 :                 stream.puts (s);
    1583       211182 :                 bol = false;
    1584              :         }
    1585              : 
    1586        31320 :         private void write_newline () {
    1587        31320 :                 stream.putc ('\n');
    1588        31320 :                 bol = true;
    1589              :         }
    1590              : 
    1591        12913 :         void write_code_block (Block? block) {
    1592        12913 :                 if (block == null || (type != CodeWriterType.DUMP && type != CodeWriterType.VAPIGEN)) {
    1593        12913 :                         write_string (";");
    1594        12913 :                         return;
    1595              :                 }
    1596              : 
    1597            0 :                 block.accept (this);
    1598              :         }
    1599              : 
    1600         1532 :         private void write_begin_block () {
    1601         1532 :                 if (!bol) {
    1602         1532 :                         stream.putc (' ');
    1603              :                 } else {
    1604            0 :                         write_indent ();
    1605              :                 }
    1606         1532 :                 stream.putc ('{');
    1607         1532 :                 write_newline ();
    1608         1532 :                 indent++;
    1609              :         }
    1610              : 
    1611         1532 :         private void write_end_block () {
    1612         1532 :                 indent--;
    1613         1532 :                 write_indent ();
    1614         1532 :                 stream.putc ('}');
    1615              :         }
    1616              : 
    1617        20106 :         private bool check_accessibility (Symbol sym) {
    1618        20106 :                 switch (type) {
    1619              :                 case CodeWriterType.EXTERNAL:
    1620              :                 case CodeWriterType.VAPIGEN:
    1621        20078 :                         return sym.access == SymbolAccessibility.PUBLIC ||
    1622         1576 :                                sym.access == SymbolAccessibility.PROTECTED;
    1623              : 
    1624              :                 case CodeWriterType.INTERNAL:
    1625              :                 case CodeWriterType.FAST:
    1626           28 :                         return sym.access == SymbolAccessibility.INTERNAL ||
    1627           28 :                                sym.access == SymbolAccessibility.PUBLIC ||
    1628            4 :                                sym.access == SymbolAccessibility.PROTECTED;
    1629              : 
    1630              :                 case CodeWriterType.DUMP:
    1631              :                         return true;
    1632              : 
    1633              :                 default:
    1634            0 :                         assert_not_reached ();
    1635              :                 }
    1636              :         }
    1637              : 
    1638            7 :         private bool skip_since_tag_check (Symbol sym, string since_val) {
    1639            7 :                 Symbol parent_symbol = sym;
    1640              : 
    1641           28 :                 while (parent_symbol.parent_symbol != null) {
    1642           42 :                         parent_symbol = parent_symbol.parent_symbol;
    1643           21 :                         if (parent_symbol.version.since == since_val) {
    1644            0 :                                 return true;
    1645              :                         }
    1646              :                 }
    1647              : 
    1648            7 :                 return false;
    1649              :         }
    1650              : 
    1651        74694 :         private void write_attributes (CodeNode node) {
    1652        37347 :                 unowned Symbol? sym = node as Symbol;
    1653              : 
    1654        37347 :                 var need_cheaders = type != CodeWriterType.FAST && sym != null && !(sym is Namespace) && sym.parent_symbol is Namespace;
    1655              : 
    1656        37347 :                 var attributes = new GLib.Sequence<Attribute> ();
    1657        53285 :                 foreach (var attr in node.attributes) {
    1658        16383 :                         attributes.insert_sorted (attr, (a, b) => strcmp (a.name, b.name));
    1659              :                 }
    1660        37347 :                 if (need_cheaders && !node.has_attribute ("CCode")) {
    1661          480 :                         attributes.insert_sorted (new Attribute ("CCode"), (a, b) => strcmp (a.name, b.name));
    1662              :                 }
    1663              : 
    1664        37347 :                 var iter = attributes.get_begin_iter ();
    1665        54171 :                 while (!iter.is_end ()) {
    1666         8421 :                         unowned Attribute attr = iter.get ();
    1667         8421 :                         iter = iter.next ();
    1668              : 
    1669        16923 :                         var keys = new GLib.Sequence<string> ();
    1670        32957 :                         foreach (var key in attr.args.get_keys ()) {
    1671         8093 :                                 if (key == "cheader_filename" && sym is Namespace) {
    1672           71 :                                         continue;
    1673              :                                 }
    1674        16044 :                                 keys.insert_sorted (key, (CompareDataFunc<string>) strcmp);
    1675              :                         }
    1676         8421 :                         if (need_cheaders && attr.name == "CCode" && !attr.has_argument ("cheader_filename")) {
    1677          480 :                                 keys.insert_sorted ("cheader_filename", (CompareDataFunc<string>) strcmp);
    1678              :                         }
    1679              : 
    1680         8421 :                         if (attr.name == "CCode" && keys.get_length () == 0) {
    1681              :                                 // only cheader_filename on namespace
    1682           18 :                                 continue;
    1683              :                         }
    1684              : 
    1685         8403 :                         if (attr.name == "Source") {
    1686            0 :                                 continue;
    1687              :                         }
    1688              : 
    1689         8421 :                         if (sym != null && attr.args.size == 1 && attr.name == "Version") {
    1690           18 :                                 string since_val = attr.get_string ("since");
    1691           18 :                                 if (since_val != null && skip_since_tag_check (sym, since_val)) {
    1692            0 :                                         continue;
    1693              :                                 }
    1694              :                         }
    1695              : 
    1696         8403 :                         if (node is PropertyAccessor) {
    1697            0 :                                 write_string (" ");
    1698         8403 :                         } else if (node is Parameter) {
    1699              :                                 // nothing
    1700              :                         } else {
    1701         8282 :                                 write_indent ();
    1702              :                         }
    1703              : 
    1704         8403 :                         stream.printf ("[%s", attr.name);
    1705         8403 :                         if (keys.get_length () > 0) {
    1706         6952 :                                 stream.puts (" (");
    1707              : 
    1708         6952 :                                 unowned string separator = "";
    1709         6952 :                                 var arg_iter = keys.get_begin_iter ();
    1710        15454 :                                 while (!arg_iter.is_end ()) {
    1711         8502 :                                         unowned string arg_name = arg_iter.get ();
    1712         8502 :                                         arg_iter = arg_iter.next ();
    1713         8502 :                                         if (arg_name == "cheader_filename") {
    1714         5816 :                                                 stream.printf ("%scheader_filename = \"%s\"", separator, get_cheaders (sym));
    1715              :                                         } else {
    1716         2686 :                                                 stream.printf ("%s%s = %s", separator, arg_name, attr.args.get (arg_name));
    1717              :                                         }
    1718              :                                         separator = ", ";
    1719              :                                 }
    1720              : 
    1721         6952 :                                 stream.puts (")");
    1722              :                         }
    1723         8403 :                         stream.puts ("]");
    1724         8403 :                         if (node is PropertyAccessor) {
    1725              :                                 // nothing
    1726         8403 :                         } else if (node is Parameter) {
    1727          121 :                                 write_string (" ");
    1728              :                         } else {
    1729         8282 :                                 write_newline ();
    1730              :                         }
    1731              :                 }
    1732              : 
    1733        37347 :                 if (type == CodeWriterType.FAST && !(node is Parameter || node is PropertyAccessor)) {
    1734           30 :                         var source_reference = node.source_reference;
    1735        37377 :                         if (source_reference != null) {
    1736           30 :                                 write_indent ();
    1737           30 :                                 string filename = source_reference.file.filename;
    1738           30 :                                 if (filename.has_prefix (context.basedir)) {
    1739           30 :                                         filename = filename.substring (context.basedir.length + 1);
    1740              :                                 }
    1741           30 :                                 stream.puts ("[Source (filename = \"%s\", line = %i, column = %i)]".printf (filename, source_reference.begin.line, source_reference.begin.column));
    1742           30 :                                 write_newline ();
    1743              :                         }
    1744              :                 }
    1745              :         }
    1746              : 
    1747        18722 :         private void write_accessibility (Symbol sym) {
    1748        18722 :                 write_string (sym.access.to_string ());
    1749        18722 :                 write_string (" ");
    1750              : 
    1751        18722 :                 if (type != CodeWriterType.EXTERNAL && type != CodeWriterType.VAPIGEN && sym.external && !sym.external_package) {
    1752            0 :                         write_string ("extern ");
    1753              :                 }
    1754              :         }
    1755              : 
    1756         3301 :         void write_property_accessor_accessibility (Symbol sym) {
    1757         3301 :                 if (sym.access == SymbolAccessibility.PUBLIC) {
    1758              :                         return;
    1759              :                 }
    1760              : 
    1761           78 :                 write_string (" ");
    1762           78 :                 write_string (sym.access.to_string ());
    1763              :         }
    1764              : 
    1765         9992 :         void write_type_parameters (List<TypeParameter> type_params) {
    1766         9992 :                 if (type_params.size > 0) {
    1767            4 :                         write_string ("<");
    1768            4 :                         bool first = true;
    1769           18 :                         foreach (TypeParameter type_param in type_params) {
    1770            7 :                                 if (first) {
    1771              :                                         first = false;
    1772              :                                 } else {
    1773            3 :                                         write_string (",");
    1774              :                                 }
    1775            7 :                                 write_identifier (type_param.name);
    1776              :                         }
    1777            4 :                         write_string (">");
    1778              :                 }
    1779              :         }
    1780              : }
    1781              : 
    1782              : public enum Vala.CodeWriterType {
    1783              :         EXTERNAL,
    1784              :         INTERNAL,
    1785              :         FAST,
    1786              :         DUMP,
    1787              :         VAPIGEN
    1788              : }
        

Generated by: LCOV version 2.0-1