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

            Line data    Source code
       1              : /* valareport.vala
       2              :  *
       3              :  * Copyright (C) 2006-2010  Jürg Billeter
       4              :  *
       5              :  * This library is free software; you can redistribute it and/or
       6              :  * modify it under the terms of the GNU Lesser General Public
       7              :  * License as published by the Free Software Foundation; either
       8              :  * version 2.1 of the License, or (at your option) any later version.
       9              : 
      10              :  * This library is distributed in the hope that it will be useful,
      11              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13              :  * Lesser General Public License for more details.
      14              : 
      15              :  * You should have received a copy of the GNU Lesser General Public
      16              :  * License along with this library; if not, write to the Free Software
      17              :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
      18              :  *
      19              :  * Author:
      20              :  *      Jürg Billeter <j@bitron.ch>
      21              :  */
      22              : 
      23              : using GLib;
      24              : 
      25              : 
      26              : /**
      27              :  * Namespace to centralize reporting warnings and errors.
      28              :  */
      29         9228 : public class Vala.Report {
      30              :         public enum Colored {
      31              :                 AUTO,
      32              :                 NEVER,
      33              :                 ALWAYS
      34              :         }
      35              : 
      36              :         /**
      37              :          * SGR (Select Graphic Rendition) end tag
      38              :          */
      39              :         private const string ANSI_COLOR_END = "\x1b[0m";
      40              : 
      41              :         /**
      42              :          * SGR (Select Graphic Rendition) start tag for source location
      43              :          */
      44         3076 :         private string locus_color_start = "";
      45              : 
      46              :         /**
      47              :          * SGR (Select Graphic Rendition) end tag for source location
      48              :          */
      49         1538 :         private unowned string locus_color_end = "";
      50              : 
      51              :         /**
      52              :          * SGR (Select Graphic Rendition) start tag for warning titles
      53              :          */
      54         3076 :         private string warning_color_start = "";
      55              : 
      56              :         /**
      57              :          * SGR (Select Graphic Rendition) end tag for warning titles
      58              :          */
      59         1538 :         private unowned string warning_color_end = "";
      60              : 
      61              :         /**
      62              :          * SGR (Select Graphic Rendition) start tag for error titles
      63              :          */
      64         3076 :         private string error_color_start = "";
      65              : 
      66              :         /**
      67              :          * SGR (Select Graphic Rendition) end tag for error titles
      68              :          */
      69         1538 :         private unowned string error_color_end = "";
      70              : 
      71              :         /**
      72              :          * SGR (Select Graphic Rendition) start tag for note titles
      73              :          */
      74         3076 :         private string note_color_start = "";
      75              : 
      76              :         /**
      77              :          * SGR (Select Graphic Rendition) end tag for note titles
      78              :          */
      79         1538 :         private unowned string note_color_end = "";
      80              : 
      81              :         /**
      82              :          * SGR (Select Graphic Rendition) start tag for caret line (^^^)
      83              :          */
      84         3076 :         private string caret_color_start = "";
      85              : 
      86              :         /**
      87              :          * SGR (Select Graphic Rendition) end tag for caret line (^^^)
      88              :          */
      89         1538 :         private unowned string caret_color_end = "";
      90              : 
      91              :         /**
      92              :          * SGR (Select Graphic Rendition) start tag for quotes line ('...', `...`, `...')
      93              :          */
      94         3076 :         private string quote_color_start = "";
      95              : 
      96              :         /**
      97              :          * SGR (Select Graphic Rendition) end tag for quotes line ('...', `...`, `...')
      98              :          */
      99         1538 :         private unowned string quote_color_end = "";
     100              : 
     101              : 
     102              :         protected int warnings;
     103              :         protected int errors;
     104              : 
     105              :         private bool verbose_errors;
     106              : 
     107         1538 :         public bool enable_warnings { get; set; default = true; }
     108              : 
     109              :         static GLib.Regex val_regex;
     110              : 
     111              :         /**
     112              :          * Set all colors by string
     113              :          *
     114              :          * {{{
     115              :          *   "error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01"
     116              :          * }}}
     117              :          */
     118         1467 :         public bool set_colors (string str, Report.Colored colored_output = Report.Colored.AUTO) {
     119            0 :                 try {
     120         1467 :                         if (val_regex == null)
     121         1467 :                                 val_regex = new Regex ("^\\s*[0-9]+(;[0-9]*)*\\s*$");
     122              :                 } catch (RegexError e) {
     123         1467 :                         assert_not_reached ();
     124              :                 }
     125              : 
     126         1467 :                 string error_color = null;
     127         1467 :                 string warning_color = null;
     128         1467 :                 string note_color = null;
     129         1467 :                 string caret_color = null;
     130         1467 :                 string locus_color = null;
     131         1467 :                 string quote_color = null;
     132              : 
     133         1467 :                 string[] fragments = str.split (":");
     134        19071 :                 foreach (unowned string fragment in fragments) {
     135         8802 :                         string[] eq = fragment.split ("=", 2);
     136         8802 :                         if (eq.length != 2) {
     137            0 :                                 return false;
     138              :                         }
     139              : 
     140         8802 :                         if (!val_regex.match (eq[1])) {
     141            0 :                                 return false;
     142              :                         }
     143              : 
     144              : 
     145         8802 :                         unowned string checked_value = eq[1]._strip ();
     146        24939 :                         switch (eq[0]._strip ()) {
     147              :                         case "error":
     148         1467 :                                 error_color = checked_value;
     149         1467 :                                 break;
     150              : 
     151              :                         case "warning":
     152         1467 :                                 warning_color = checked_value;
     153         1467 :                                 break;
     154              : 
     155              :                         case "note":
     156         1467 :                                 note_color = checked_value;
     157         1467 :                                 break;
     158              : 
     159              :                         case "caret":
     160         1467 :                                 caret_color = checked_value;
     161         1467 :                                 break;
     162              : 
     163              :                         case "locus":
     164         1467 :                                 locus_color = checked_value;
     165         1467 :                                 break;
     166              : 
     167              :                         case "quote":
     168         1467 :                                 quote_color = checked_value;
     169         1467 :                                 break;
     170              : 
     171              :                         default:
     172            0 :                                 return false;
     173              :                         }
     174              :                 }
     175              : 
     176         1467 :                 if (colored_output == Report.Colored.ALWAYS || (colored_output == Report.Colored.AUTO && Log.writer_supports_color (stderr.fileno ()))) {
     177            0 :                         if (error_color != null) {
     178            0 :                                 this.error_color_start = "\x1b[0" + error_color + "m";
     179            0 :                                 this.error_color_end = ANSI_COLOR_END;
     180              :                         }
     181              : 
     182            0 :                         if (warning_color != null) {
     183            0 :                                 this.warning_color_start = "\x1b[0" + warning_color + "m";
     184            0 :                                 this.warning_color_end = ANSI_COLOR_END;
     185              :                         }
     186              : 
     187            0 :                         if (note_color != null) {
     188            0 :                                 this.note_color_start = "\x1b[0" + note_color + "m";
     189            0 :                                 this.note_color_end = ANSI_COLOR_END;
     190              :                         }
     191              : 
     192            0 :                         if (caret_color != null) {
     193            0 :                                 this.caret_color_start = "\x1b[0" + caret_color + "m";
     194            0 :                                 this.caret_color_end = ANSI_COLOR_END;
     195              :                         }
     196              : 
     197            0 :                         if (locus_color != null) {
     198            0 :                                 this.locus_color_start = "\x1b[0" + locus_color + "m";
     199            0 :                                 this.locus_color_end = ANSI_COLOR_END;
     200              :                         }
     201              : 
     202            0 :                         if (quote_color != null) {
     203            0 :                                 this.quote_color_start = "\x1b[0" + quote_color + "m";
     204            0 :                                 this.quote_color_end = ANSI_COLOR_END;
     205              :                         }
     206              :                 }
     207         2934 :                 return true;
     208              :         }
     209              : 
     210              :         /**
     211              :          * Set the error verbosity.
     212              :          */
     213         1538 :         public void set_verbose_errors (bool verbose) {
     214         1538 :                 verbose_errors = verbose;
     215              :         }
     216              : 
     217              :         /**
     218              :          * Returns the total number of warnings reported.
     219              :          */
     220         1542 :         public int get_warnings () {
     221         1542 :                 return warnings;
     222              :         }
     223              : 
     224              :         /**
     225              :          * Returns the total number of errors reported.
     226              :          */
     227        16748 :         public int get_errors () {
     228        16748 :                 return errors;
     229              :         }
     230              : 
     231              :         /**
     232              :          * Pretty-print the actual line of offending code if possible.
     233              :          */
     234          748 :         private void report_source (SourceReference source) {
     235         1514 :                 for (int idx = source.begin.line; idx <= source.end.line; idx++) {
     236          767 :                         string? offending_line = source.file.get_source_line (idx);
     237          767 :                         if (offending_line == null) {
     238            1 :                                 break;
     239              :                         }
     240          766 :                         printerr ("%5d | %s\n", idx, offending_line);
     241          766 :                         printerr ("      | ");
     242          766 :                         stderr.puts (caret_color_start);
     243        19776 :                         for (int jdx = 0; jdx < offending_line.length; jdx++) {
     244        19010 :                                 if (offending_line[jdx] == '\t') {
     245          656 :                                         stderr.putc ('\t');
     246          656 :                                         continue;
     247              :                                 }
     248        18354 :                                 bool caret = false;
     249        18354 :                                 unowned SourceLocation begin = source.begin;
     250        18354 :                                 unowned SourceLocation end = source.end;
     251        18354 :                                 if (begin.line == idx && end.line == idx) {
     252        17865 :                                         if (begin.column <= jdx + 1 <= end.column) {
     253              :                                                 caret = true;
     254              :                                         }
     255          489 :                                 } else if (begin.line == idx && begin.column <= jdx + 1) {
     256              :                                         caret = true;
     257          341 :                                 } else if (begin.line < idx < end.line) {
     258              :                                         caret = true;
     259          145 :                                 } else if (end.line == idx && end.column >= jdx + 1) {
     260              :                                         caret = true;
     261              :                                 }
     262           81 :                                 if (caret) {
     263         8518 :                                         if (begin.line == idx && begin.column == jdx + 1) {
     264          739 :                                                 stderr.putc ('^');
     265              :                                         } else {
     266         7779 :                                                 stderr.putc ('~');
     267              :                                         }
     268              :                                 } else {
     269         9836 :                                         stderr.putc (' ');
     270              :                                 }
     271              :                         }
     272          766 :                         stderr.puts (caret_color_end);
     273          766 :                         stderr.putc ('\n');
     274              :                 }
     275              :         }
     276              : 
     277          749 :         private void print_highlighted_message (string message) {
     278              :                 int start = 0;
     279              :                 int cur = 0;
     280              : 
     281        34809 :                 while (message[cur] != '\0') {
     282        34060 :                         if (message[cur] == '\'' || message[cur] == '`') {
     283          679 :                                 unowned string end_chars = (message[cur] == '`')? "`'" : "'";
     284          679 :                                 stderr.puts (message.substring (start, cur - start));
     285          679 :                                 start = cur;
     286          679 :                                 cur++;
     287              : 
     288         5726 :                                 while (message[cur] != '\0' && end_chars.index_of_char (message[cur]) < 0) {
     289         5047 :                                         cur++;
     290              :                                 }
     291          679 :                                 if (message[cur] == '\0') {
     292            3 :                                         stderr.puts (message.substring (start, cur - start));
     293            3 :                                         start = cur;
     294              :                                 } else {
     295          676 :                                         cur++;
     296          676 :                                         printerr ("%s%s%s", quote_color_start, message.substring (start, cur - start), quote_color_end);
     297          676 :                                         start = cur;
     298              :                                 }
     299              :                         } else {
     300        33381 :                                 cur++;
     301              :                         }
     302              :                 }
     303              : 
     304          749 :                 stderr.puts (message.offset (start));
     305              :         }
     306              : 
     307          749 :         private void print_message (SourceReference? source, string type, string type_color_start, string type_color_end, string message, bool do_report_source) {
     308          749 :                 if (source != null) {
     309          748 :                         printerr ("%s%s:%s ", locus_color_start, source.to_string (), locus_color_end);
     310              :                 }
     311              : 
     312          749 :                 printerr ("%s%s:%s ", type_color_start, type, type_color_end);
     313              : 
     314              :                 // highlight '', `', ``
     315          749 :                 print_highlighted_message (message);
     316          749 :                 stderr.putc ('\n');
     317              : 
     318          749 :                 if (do_report_source && source != null) {
     319          748 :                         report_source (source);
     320              :                 }
     321              :         }
     322              : 
     323              :         /**
     324              :          * Reports the specified message as note.
     325              :          *
     326              :          * @param source  reference to source code
     327              :          * @param message note message
     328              :          */
     329           22 :         public virtual void note (SourceReference? source, string message) {
     330           11 :                 if (!enable_warnings) {
     331              :                         return;
     332              :                 }
     333              : 
     334            1 :                 print_message (source, "note", note_color_start, note_color_end, message, verbose_errors);
     335              :         }
     336              : 
     337              :         /**
     338              :          * Reports the specified message as deprecation warning.
     339              :          *
     340              :          * @param source  reference to source code
     341              :          * @param message warning message
     342              :          */
     343          112 :         public virtual void depr (SourceReference? source, string message) {
     344           56 :                 if (!enable_warnings) {
     345              :                         return;
     346              :                 }
     347              : 
     348           20 :                 warnings++;
     349              : 
     350           20 :                 print_message (source, "warning", warning_color_start, warning_color_end, message, verbose_errors);
     351              :         }
     352              : 
     353              :         /**
     354              :          * Reports the specified message as warning.
     355              :          *
     356              :          * @param source  reference to source code
     357              :          * @param message warning message
     358              :          */
     359         4282 :         public virtual void warn (SourceReference? source, string message) {
     360         2141 :                 if (!enable_warnings) {
     361              :                         return;
     362              :                 }
     363              : 
     364           22 :                 warnings++;
     365              : 
     366           22 :                 print_message (source, "warning", warning_color_start, warning_color_end, message, verbose_errors);
     367              :         }
     368              : 
     369              :         /**
     370              :          * Reports the specified message as error.
     371              :          *
     372              :          * @param source  reference to source code
     373              :          * @param message error message
     374              :          */
     375         1412 :         public virtual void err (SourceReference? source, string message) {
     376          706 :                 errors++;
     377              : 
     378          706 :                 print_message (source, "error", error_color_start, error_color_end, message, verbose_errors);
     379              :         }
     380              : 
     381              :         /* Convenience methods calling warn and err on correct instance */
     382              :         [PrintfFormat]
     383           11 :         public static void notice (SourceReference? source, string msg_format, ...) {
     384           11 :                 CodeContext.get ().report.note (source, msg_format.vprintf (va_list ()));
     385              :         }
     386              :         [PrintfFormat]
     387           56 :         public static void deprecated (SourceReference? source, string msg_format, ...) {
     388           56 :                 CodeContext.get ().report.depr (source, msg_format.vprintf (va_list ()));
     389              :         }
     390              :         [PrintfFormat]
     391            0 :         public static void experimental (SourceReference? source, string msg_format, ...) {
     392            0 :                 CodeContext.get ().report.depr (source, msg_format.vprintf (va_list ()));
     393              :         }
     394              :         [PrintfFormat]
     395         2141 :         public static void warning (SourceReference? source, string msg_format, ...) {
     396         2141 :                 CodeContext.get ().report.warn (source, msg_format.vprintf (va_list ()));
     397              :         }
     398              :         [PrintfFormat]
     399          706 :         public static void error (SourceReference? source, string msg_format, ...) {
     400          706 :                 CodeContext.get ().report.err (source, msg_format.vprintf (va_list ()));
     401              :         }
     402              : }
        

Generated by: LCOV version 2.0-1