diff options
Diffstat (limited to 'libvaladoc/errorreporter.vala')
-rw-r--r-- | libvaladoc/errorreporter.vala | 392 |
1 files changed, 392 insertions, 0 deletions
diff --git a/libvaladoc/errorreporter.vala b/libvaladoc/errorreporter.vala new file mode 100644 index 000000000..5b9543e62 --- /dev/null +++ b/libvaladoc/errorreporter.vala @@ -0,0 +1,392 @@ +/* errorreporter.vala + * + * Copyright (C) 2008-2011 Florian Brosch + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: + * Brosch Florian <flo.brosch@gmail.com> + */ + +using Gee; + + +public class Valadoc.ErrorReporter : Object { + private int _warnings = 0; + private int _errors = 0; + + /** + * SGR end tag + */ + private const string ANSI_COLOR_END = "\x1b[0m"; + + /** + * SGR start tag for source location + */ + private string locus_color_start = ""; + + /** + * SGR end tag for source location + */ + private unowned string locus_color_end = ""; + + /** + * SGR start tag for warning titles + */ + private string warning_color_start = ""; + + /** + * SGR end tag for warning titles + */ + private unowned string warning_color_end = ""; + + /** + * SGR start tag for error titles + */ + private string error_color_start = ""; + + /** + * SGR end tag for error titles + */ + private unowned string error_color_end = ""; + + /** + * SGR start tag for note titles + */ + private string note_color_start = ""; + + /** + * SGR end tag for note titles + */ + private unowned string note_color_end = ""; + + /** + * SGR start tag for caret line (^^^) + */ + private string caret_color_start = ""; + + /** + * SGR end tag for caret line (^^^) + */ + private unowned string caret_color_end = ""; + + /** + * SGR start tag for quotes line ('', ``, `') + */ + private string quote_color_start = ""; + + /** + * SGR end tag for quotes line ('', ``, `') + */ + private unowned string quote_color_end = ""; + + + public int warnings_offset { + get; + set; + } + + public int errors_offset { + get; + set; + } + + public unowned GLib.FileStream stream { + get; + set; + } + + public Settings? settings { + get; + set; + } + + public int errors { + get { + return this._errors + errors_offset; + } + } + + public int warnings { + get { + return this._warnings + warnings_offset; + } + } + + + public ErrorReporter (Settings? settings = null) { + this.stream = GLib.stderr; + this.settings = settings; + } + + /** + * Set all colors by string + * + * {{{ + * "error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01" + * }}} + */ + public bool set_colors (string str) { + Regex val_regex; + try { + val_regex = new Regex ("^\\s*[0-9]+(;[0-9]*)*\\s*$"); + } catch (RegexError e) { + assert_not_reached (); + } + + string error_color = null; + string warning_color = null; + string note_color = null; + string caret_color = null; + string locus_color = null; + string quote_color = null; + + string[] fragments = str.split (":"); + foreach (unowned string fragment in fragments) { + string[] eq = fragment.split ("=", 2); + if (eq.length != 2) { + return false; + } + + if (!val_regex.match (eq[1])) { + return false; + } + + + unowned string checked_value = eq[1]._strip (); + switch (eq[0]._strip ()) { + case "error": + error_color = checked_value; + break; + + case "warning": + warning_color = checked_value; + break; + + case "note": + note_color = checked_value; + break; + + case "caret": + caret_color = checked_value; + break; + + case "locus": + locus_color = checked_value; + break; + + case "quote": + quote_color = checked_value; + break; + + default: + return false; + } + } + + if (is_atty (this.stream.fileno ())) { + if (error_color != null) { + this.error_color_start = "\x1b[0" + error_color + "m"; + this.error_color_end = ANSI_COLOR_END; + } + + if (warning_color != null) { + this.warning_color_start = "\x1b[0" + warning_color + "m"; + this.warning_color_end = ANSI_COLOR_END; + } + + if (note_color != null) { + this.note_color_start = "\x1b[0" + note_color + "m"; + this.note_color_end = ANSI_COLOR_END; + } + + if (caret_color != null) { + this.caret_color_start = "\x1b[0" + caret_color + "m"; + this.caret_color_end = ANSI_COLOR_END; + } + + if (locus_color != null) { + this.locus_color_start = "\x1b[0" + locus_color + "m"; + this.locus_color_end = ANSI_COLOR_END; + } + + if (quote_color != null) { + this.quote_color_start = "\x1b[0" + quote_color + "m"; + this.quote_color_end = ANSI_COLOR_END; + } + } + return true; + } + + [CCode (has_target = false)] + private delegate int AttyFunc (int fd); + + private bool is_atty (int fd) { + Module module = Module.open (null, ModuleFlags.BIND_LAZY); + if (module == null) { + return false; + } + + void* _func; + module.symbol ("isatty", out _func); + if (_func == null) { + return false; + } + + AttyFunc? func = (AttyFunc) _func; + return func (fd) == 1; + } + + [PrintfFormat] + private inline void msg (string type, string type_color_start, string type_color_end, string file, long line, long startpos, long endpos, + string errline, string msg_format, va_list args) + { + this.stream.printf ("%s%s:%lu.%lu-%lu.%lu:%s %s%s:%s ", + locus_color_start, file, line, startpos, line, endpos, locus_color_end, + type_color_start, type, type_color_end); + print_highlighted_message (msg_format.vprintf (args)); + this.stream.putc ('\n'); + + if (startpos <= endpos) { + this.stream.printf ("%s\n", errline); + + this.stream.puts (caret_color_start); + for (int i = 0; i < errline.char_count ()+1; i++) { + if (errline[i] == '\t') { + this.stream.printf ("\t"); + } else if (i >= startpos - 1 && i < endpos - 1) { + this.stream.printf ("^"); + } else { + this.stream.printf (" "); + } + } + this.stream.puts (caret_color_end); + this.stream.printf ("\n"); + } + } + + private void print_highlighted_message (string message) { + int start = 0; + int cur = 0; + + while (message[cur] != '\0') { + if (message[cur] == '\'' || message[cur] == '`') { + unowned string end_chars = (message[cur] == '`')? "`'" : "'"; + this.stream.puts (message.substring (start, cur - start)); + start = cur; + cur++; + + while (message[cur] != '\0' && end_chars.index_of_char (message[cur]) < 0) { + cur++; + } + if (message[cur] == '\0') { + this.stream.puts (message.substring (start, cur - start)); + start = cur; + } else { + cur++; + this.stream.printf ("%s%s%s", quote_color_start, message.substring (start, cur - start), quote_color_end); + start = cur; + } + } else { + cur++; + } + } + + this.stream.puts (message.offset (start)); + } + + [PrintfFormat] + public void simple_warning (string? location, string msg_format, ...) { + var args = va_list(); + + if (location != null) { + this.stream.puts (locus_color_start); + this.stream.puts (location); + this.stream.puts (": "); + this.stream.puts (locus_color_end); + } + + this.stream.puts (warning_color_start); + this.stream.puts ("warning: "); + this.stream.puts (warning_color_end); + + print_highlighted_message (msg_format.vprintf (args)); + this.stream.putc ('\n'); + this._warnings++; + } + + [PrintfFormat] + public void simple_error (string? location, string msg_format, ...) { + var args = va_list(); + + if (location != null) { + this.stream.puts (locus_color_start); + this.stream.puts (location); + this.stream.puts (": "); + this.stream.puts (locus_color_end); + this.stream.putc (' '); + } + + this.stream.puts (error_color_start); + this.stream.puts ("error: "); + this.stream.puts (error_color_end); + + print_highlighted_message (msg_format.vprintf (args)); + this.stream.putc ('\n'); + this._errors++; + } + + [PrintfFormat] + public void simple_note (string? location, string msg_format, ...) { + if (_settings == null || _settings.verbose) { + var args = va_list(); + + if (location != null) { + this.stream.puts (locus_color_start); + this.stream.puts (location); + this.stream.puts (": "); + this.stream.puts (locus_color_end); + this.stream.putc (' '); + } + + this.stream.puts (note_color_start); + this.stream.puts ("note: "); + this.stream.puts (note_color_end); + + print_highlighted_message (msg_format.vprintf (args)); + this.stream.putc ('\n'); + this._warnings++; + } + } + + [PrintfFormat] + public void error (string file, long line, long startpos, long endpos, string errline, + string msg_format, ...) + { + var args = va_list(); + this.msg ("error", error_color_start, error_color_end, file, line, startpos, endpos, errline, msg_format, args); + this._errors++; + } + + [PrintfFormat] + public void warning (string file, long line, long startpos, long endpos, string errline, + string msg_format, ...) + { + var args = va_list(); + this.msg ("warning", warning_color_start, warning_color_end, file, line, startpos, endpos, errline, msg_format, args); + this._warnings++; + } +} + |