1 // Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
13 use errors::emitter::EmitterWriter;
15 use std::io::prelude::*;
18 use std::sync::{Arc, Mutex};
19 use syntax_pos::{BytePos, NO_EXPANSION, Span, MultiSpan};
21 /// Identify a position in the text by the Nth occurrence of a string.
33 struct Shared<T: Write> {
37 impl<T: Write> Write for Shared<T> {
38 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
39 self.data.lock().unwrap().write(buf)
42 fn flush(&mut self) -> io::Result<()> {
43 self.data.lock().unwrap().flush()
47 fn test_harness(file_text: &str, span_labels: Vec<SpanLabel>, expected_output: &str) {
48 let output = Arc::new(Mutex::new(Vec::new()));
50 let code_map = Rc::new(CodeMap::new());
51 code_map.new_filemap_and_lines("test.rs", None, &file_text);
53 let primary_span = make_span(&file_text, &span_labels[0].start, &span_labels[0].end);
54 let mut msp = MultiSpan::from_span(primary_span);
55 for span_label in span_labels {
56 let span = make_span(&file_text, &span_label.start, &span_label.end);
57 msp.push_span_label(span, span_label.label.to_string());
58 println!("span: {:?} label: {:?}", span, span_label.label);
59 println!("text: {:?}", code_map.span_to_snippet(span));
62 let emitter = EmitterWriter::new(Box::new(Shared { data: output.clone() }),
63 Some(code_map.clone()));
64 let handler = Handler::with_emitter(true, false, Box::new(emitter));
65 handler.span_err(msp, "foo");
67 assert!(expected_output.chars().next() == Some('\n'),
68 "expected output should begin with newline");
69 let expected_output = &expected_output[1..];
71 let bytes = output.lock().unwrap();
72 let actual_output = str::from_utf8(&bytes).unwrap();
73 println!("expected output:\n------\n{}------", expected_output);
74 println!("actual output:\n------\n{}------", actual_output);
76 assert!(expected_output == actual_output)
79 fn make_span(file_text: &str, start: &Position, end: &Position) -> Span {
80 let start = make_pos(file_text, start);
81 let end = make_pos(file_text, end) + end.string.len(); // just after matching thing ends
82 assert!(start <= end);
84 lo: BytePos(start as u32),
85 hi: BytePos(end as u32),
90 fn make_pos(file_text: &str, pos: &Position) -> usize {
91 let mut remainder = file_text;
93 for _ in 0..pos.count {
94 if let Some(n) = remainder.find(&pos.string) {
96 remainder = &remainder[n + 1..];
98 panic!("failed to find {} instances of {:?} in {:?}",
131 | __________^ starting here...
133 | |_^ ...ending here: test
164 | __________^ starting here...
168 | |___^ ...ending here: test
191 label: "`X` is a good letter",
202 label: "`Y` is a good letter too",
210 | ____^__- starting here...
212 | || starting here...
215 | ||____^__- ...ending here: `Y` is a good letter too
217 | ...ending here: `X` is a good letter
240 label: "`X` is a good letter",
251 label: "`Y` is a good letter too",
259 | ____^__- starting here...
261 | || starting here...
263 | ||____-__^ ...ending here: `X` is a good letter
265 | ...ending here: `Y` is a good letter too
271 fn different_overlap() {
290 label: "`X` is a good letter",
301 label: "`Y` is a good letter too",
309 | ______^ starting here...
311 | |_________- starting here...
313 | ||____^ ...ending here: `X` is a good letter
315 | |_____- ...ending here: `Y` is a good letter too
321 fn triple_overlap() {
339 label: "`X` is a good letter",
350 label: "`Y` is a good letter too",
369 | _____^__-__- starting here...
371 | || ___| starting here...
372 | ||| starting here...
375 | |||____^__-__- ...ending here: `Z` label
377 | |____| ...ending here: `Y` is a good letter too
378 | ...ending here: `X` is a good letter
403 label: "`X` is a good letter",
414 label: "`Y` is a good letter too",
433 | ______^ starting here...
435 | |____^_- starting here...
437 | | ...ending here: `X` is a good letter
439 | |____-______- ...ending here: `Y` is a good letter too
443 | |________- ...ending here: `Z`
449 fn non_overlaping() {
468 label: "`X` is a good letter",
479 label: "`Y` is a good letter too",
487 | ______^ starting here...
489 | |____^ ...ending here: `X` is a good letter
491 | ______- starting here...
493 | |__________- ...ending here: `Y` is a good letter too
499 fn overlaping_start_and_end() {
518 label: "`X` is a good letter",
529 label: "`Y` is a good letter too",
537 | ______^ starting here...
539 | |____^____- starting here...
541 | | ...ending here: `X` is a good letter
544 | |___________- ...ending here: `Y` is a good letter too
550 fn multiple_labels_primary_without_message() {
577 label: "`a` is a good letter",
596 | ----^^^^-^^-- `a` is a good letter
602 fn multiple_labels_secondary_without_message() {
618 label: "`a` is a good letter",
637 | ^^^^-------^^ `a` is a good letter
643 fn multiple_labels_primary_without_message_2() {
659 label: "`b` is a good letter",
691 | `b` is a good letter
697 fn multiple_labels_secondary_without_message_2() {
724 label: "`b` is a good letter",
734 | `b` is a good letter
740 fn multiple_labels_without_message() {
781 fn multiple_labels_without_message_2() {
833 fn multiple_labels_with_message() {
849 label: "`a` is a good letter",
860 label: "`b` is a good letter",
870 | | `b` is a good letter
871 | `a` is a good letter
877 fn single_label_with_message() {
893 label: "`a` is a good letter",
901 | ^^^^^^^^^^^^^ `a` is a good letter
907 fn single_label_without_message() {
966 label: "`X` is a good letter",
977 label: "`Y` is a good letter too",
985 | ______^ starting here...
987 | |____^____- starting here...
989 | | ...ending here: `X` is a good letter
996 | |___________- ...ending here: `Y` is a good letter too
1002 fn long_snippet_multiple_spans() {
1031 label: "`Y` is a good letter",
1042 label: "`Z` is a good letter too",
1050 | ______^ starting here...
1055 | |_________- starting here...
1060 | ||__________- ...ending here: `Z` is a good letter too
1064 | |_______^ ...ending here: `Y` is a good letter