about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJosh Matthews <josh@joshmatthews.net>2011-07-11 14:31:57 -0400
committerBrian Anderson <banderson@mozilla.com>2011-07-11 18:44:27 -0700
commitfd24fd5e318c5bfbe0cba49f0b49edd3c112f451 (patch)
treeae6b8844abd7ebc2815b9db9c193413ae44aa102
parentb62fcdcc36a451a23a0b4639f78e4434949190ba (diff)
downloadrust-fd24fd5e318c5bfbe0cba49f0b49edd3c112f451.tar.gz
rust-fd24fd5e318c5bfbe0cba49f0b49edd3c112f451.zip
Only print up to six lines on error. Print ^~~~~ to highlight error span.
-rw-r--r--src/comp/driver/session.rs1
-rw-r--r--src/comp/syntax/codemap.rs50
2 files changed, 50 insertions, 1 deletions
diff --git a/src/comp/driver/session.rs b/src/comp/driver/session.rs
index 9d6aab7f56e..8a1f5d791ce 100644
--- a/src/comp/driver/session.rs
+++ b/src/comp/driver/session.rs
@@ -10,6 +10,7 @@ import std::option;
 import std::option::some;
 import std::option::none;
 import std::str;
+import std::vec;
 
 tag os { os_win32; os_macos; os_linux; }
 
diff --git a/src/comp/syntax/codemap.rs b/src/comp/syntax/codemap.rs
index a5382a67e05..34b5a02112f 100644
--- a/src/comp/syntax/codemap.rs
+++ b/src/comp/syntax/codemap.rs
@@ -78,10 +78,22 @@ fn emit_diagnostic(&option::t[span] sp, &str msg, &str kind, u8 color,
     io::stdout().write_str(#fmt(" %s\n", msg));
     alt (maybe_lines) {
         case (some(?lines)) {
+            // FIXME: reading in the entire file is the worst possible way to
+            //        get access to the necessary lines.
             auto rdr = io::file_reader(lines.name);
             auto file = str::unsafe_from_bytes(rdr.read_whole_stream());
             auto fm = codemap::get_filemap(cm, lines.name);
-            for (uint line in lines.lines) {
+
+            // arbitrarily only print up to six lines of the error
+            auto max_lines = 6u;
+            auto elided = false;
+            auto display_lines = lines.lines;
+            if (vec::len(display_lines) > max_lines) {
+                display_lines = vec::slice(display_lines, 0u, max_lines);
+                elided = true;
+            }
+            // Print the offending lines
+            for (uint line in display_lines) {
                 io::stdout().write_str(#fmt("%s:%u ", fm.name, line + 1u));
                 auto s = codemap::get_line(fm, line as int, file);
                 if (!str::ends_with(s, "\n")) {
@@ -89,6 +101,42 @@ fn emit_diagnostic(&option::t[span] sp, &str msg, &str kind, u8 color,
                 }
                 io::stdout().write_str(s);
             }
+            if (elided) {
+                auto last_line = display_lines.(vec::len(display_lines) - 1u);
+                auto s = #fmt("%s:%u ", fm.name, last_line + 1u);
+                auto indent = str::char_len(s);
+                auto out = "";
+                while (indent > 0u) { out += " "; indent -= 1u; }
+                out += "...\n";
+                io::stdout().write_str(out);
+            }
+
+            // If there's one line at fault we can easily point to the problem
+            if (vec::len(lines.lines) == 1u) {
+                auto lo = codemap::lookup_pos(cm, option::get(sp).lo);
+                auto digits = 0u;
+                auto num = lines.lines.(0) / 10u;
+
+                // how many digits must be indent past?
+                while (num > 0u) { num /= 10u; digits += 1u; }
+
+                // indent past |name:## | and the 0-offset column location
+                auto left = str::char_len(fm.name) + digits + lo.col + 3u;
+                auto s = "";
+                while (left > 0u) { str::push_char(s, ' '); left -= 1u; }
+
+                s += "^";
+                auto hi = codemap::lookup_pos(cm, option::get(sp).hi);
+                if (hi.col != lo.col) {
+                    // the ^ already takes up one space
+                    auto width = hi.col - lo.col - 1u;
+                    while (width > 0u) {
+                        str::push_char(s, '~');
+                        width -= 1u;
+                    }
+                }
+                io::stdout().write_str(s + "\n");
+            }
         }
         case (_) {}
     }