]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #21499 - P1start:issue-8706, r=huonw
authorbors <bors@rust-lang.org>
Wed, 4 Feb 2015 12:42:40 +0000 (12:42 +0000)
committerbors <bors@rust-lang.org>
Wed, 4 Feb 2015 12:42:40 +0000 (12:42 +0000)
Closes #8706.

src/libsyntax/diagnostic.rs
src/test/run-make/unicode-input/span_length.rs

index d22054d8ed0c44a45a5668887a852653ed7e22cc..454209bdba2830943791dc2da4d790bbb973fa9c 100644 (file)
@@ -483,42 +483,61 @@ fn highlight_lines(err: &mut EmitterWriter,
         // how many digits must be indent past?
         while num > 0 { num /= 10; digits += 1; }
 
-        // indent past |name:## | and the 0-offset column location
-        let left = fm.name.len() + digits + lo.col.to_usize() + 3;
         let mut s = String::new();
         // Skip is the number of characters we need to skip because they are
         // part of the 'filename:line ' part of the previous line.
-        let skip = fm.name.len() + digits + 3;
+        let skip = fm.name.width(false) + digits + 3;
         for _ in 0..skip {
             s.push(' ');
         }
         if let Some(orig) = fm.get_line(lines.lines[0]) {
-            for pos in 0..left - skip {
-                let cur_char = orig.as_bytes()[pos] as char;
+            let mut col = skip;
+            let mut lastc = ' ';
+            let mut iter = orig.chars().enumerate();
+            for (pos, ch) in iter.by_ref() {
+                lastc = ch;
+                if pos >= lo.col.to_usize() { break; }
                 // Whenever a tab occurs on the previous line, we insert one on
                 // the error-point-squiggly-line as well (instead of a space).
                 // That way the squiggly line will usually appear in the correct
                 // position.
-                match cur_char {
-                    '\t' => s.push('\t'),
-                    _ => s.push(' '),
-                };
+                match ch {
+                    '\t' => {
+                        col += 8 - col%8;
+                        s.push('\t');
+                    },
+                    c => for _ in 0..c.width(false).unwrap_or(0) {
+                        col += 1;
+                        s.push(' ');
+                    },
+                }
             }
-        }
 
-        try!(write!(&mut err.dst, "{}", s));
-        let mut s = String::from_str("^");
-        let hi = cm.lookup_char_pos(sp.hi);
-        if hi.col != lo.col {
-            // the ^ already takes up one space
-            let num_squigglies = hi.col.to_usize() - lo.col.to_usize() - 1;
-            for _ in 0..num_squigglies {
-                s.push('~');
+            try!(write!(&mut err.dst, "{}", s));
+            let mut s = String::from_str("^");
+            let count = match lastc {
+                // Most terminals have a tab stop every eight columns by default
+                '\t' => 8 - col%8,
+                _ => lastc.width(false).unwrap_or(1),
+            };
+            col += count;
+            s.extend(::std::iter::repeat('~').take(count - 1));
+            let hi = cm.lookup_char_pos(sp.hi);
+            if hi.col != lo.col {
+                for (pos, ch) in iter {
+                    if pos >= hi.col.to_usize() { break; }
+                    let count = match ch {
+                        '\t' => 8 - col%8,
+                        _ => ch.width(false).unwrap_or(0),
+                    };
+                    col += count;
+                    s.extend(::std::iter::repeat('~').take(count));
+                }
             }
+            try!(print_maybe_styled(err,
+                                    &format!("{}\n", s)[],
+                                    term::attr::ForegroundColor(lvl.color())));
         }
-        try!(print_maybe_styled(err,
-                                &format!("{}\n", s)[],
-                                term::attr::ForegroundColor(lvl.color())));
     }
     Ok(())
 }
@@ -559,12 +578,28 @@ fn custom_highlight_lines(w: &mut EmitterWriter,
     }
     let last_line_start = format!("{}:{} ", fm.name, lines[lines.len()-1]+1);
     let hi = cm.lookup_char_pos(sp.hi);
-    // Span seems to use half-opened interval, so subtract 1
-    let skip = last_line_start.len() + hi.col.to_usize() - 1;
+    let skip = last_line_start.width(false);
     let mut s = String::new();
     for _ in 0..skip {
         s.push(' ');
     }
+    if let Some(orig) = fm.get_line(lines[0]) {
+        let iter = orig.chars().enumerate();
+        for (pos, ch) in iter {
+            // Span seems to use half-opened interval, so subtract 1
+            if pos >= hi.col.to_usize() - 1 { break; }
+            // Whenever a tab occurs on the previous line, we insert one on
+            // the error-point-squiggly-line as well (instead of a space).
+            // That way the squiggly line will usually appear in the correct
+            // position.
+            match ch {
+                '\t' => s.push('\t'),
+                c => for _ in 0..c.width(false).unwrap_or(0) {
+                    s.push(' ');
+                },
+            }
+        }
+    }
     s.push('^');
     s.push('\n');
     print_maybe_styled(w,
index 01e2c1f29730beab99535782beb7167401c4a394..9ee7516c7baeb91eadcf31be2f3e4ba5d4ee3186 100644 (file)
@@ -65,4 +65,36 @@ fn main() {
                                                         .collect::<String>());
         assert!(err.contains(expected_span.as_slice()));
     }
+
+    // Test multi-column characters and tabs
+    {
+        let _ = write!(&mut File::create(&main_file).unwrap(),
+                       r#"extern "路濫狼á́́" fn foo() {{}} extern "路濫狼á́" fn bar() {{}}"#);
+    }
+
+    // Extra characters. Every line is preceded by `filename:lineno <actual code>`
+    let offset = main_file.as_str().unwrap().len() + 3;
+
+    let result = Command::new("sh")
+                         .arg("-c")
+                         .arg(format!("{} {}",
+                                      rustc,
+                                      main_file.as_str()
+                                               .unwrap()).as_slice())
+                         .output().unwrap();
+
+    let err = String::from_utf8_lossy(result.error.as_slice());
+
+    // Test both the length of the snake and the leading spaces up to it
+
+    // First snake is 8 ~s long, with 7 preceding spaces (excluding file name/line offset)
+    let expected_span = format!("\n{}^{}\n",
+                                repeat(" ").take(offset + 7).collect::<String>(),
+                                repeat("~").take(8).collect::<String>());
+    assert!(err.contains(expected_span.as_slice()));
+    // Second snake is 8 ~s long, with 36 preceding spaces
+    let expected_span = format!("\n{}^{}\n",
+                                repeat(" ").take(offset + 36).collect::<String>(),
+                                repeat("~").take(8).collect::<String>());
+    assert!(err.contains(expected_span.as_slice()));
 }