2019-10-03 03:55:31 +03:00
|
|
|
use super::*;
|
|
|
|
|
|
|
|
use crate::json::JsonEmitter;
|
2019-12-31 20:15:40 +03:00
|
|
|
use rustc_span::source_map::{FilePathMapping, SourceMap};
|
2019-10-03 03:55:31 +03:00
|
|
|
|
2019-11-14 17:24:44 -05:00
|
|
|
use crate::emitter::{ColorConfig, HumanReadableErrorType};
|
|
|
|
use crate::Handler;
|
2022-02-09 17:05:44 -05:00
|
|
|
use rustc_serialize::json;
|
2019-12-31 20:15:40 +03:00
|
|
|
use rustc_span::{BytePos, Span};
|
2019-10-03 03:55:31 +03:00
|
|
|
|
|
|
|
use std::str;
|
|
|
|
|
2022-02-09 17:05:44 -05:00
|
|
|
#[derive(Debug, PartialEq, Eq)]
|
2019-10-03 03:55:31 +03:00
|
|
|
struct SpanTestData {
|
|
|
|
pub byte_start: u32,
|
|
|
|
pub byte_end: u32,
|
|
|
|
pub line_start: u32,
|
|
|
|
pub column_start: u32,
|
|
|
|
pub line_end: u32,
|
|
|
|
pub column_end: u32,
|
|
|
|
}
|
|
|
|
|
2019-10-10 10:26:10 +02:00
|
|
|
struct Shared<T> {
|
|
|
|
data: Arc<Mutex<T>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Write> Write for Shared<T> {
|
|
|
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
|
|
|
self.data.lock().unwrap().write(buf)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn flush(&mut self) -> io::Result<()> {
|
|
|
|
self.data.lock().unwrap().flush()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-03 03:55:31 +03:00
|
|
|
/// Test the span yields correct positions in JSON.
|
|
|
|
fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) {
|
2021-05-05 21:31:25 +02:00
|
|
|
rustc_span::create_default_session_globals_then(|| {
|
2019-10-03 03:55:31 +03:00
|
|
|
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
|
|
|
sm.new_source_file(Path::new("test.rs").to_owned().into(), code.to_owned());
|
|
|
|
|
|
|
|
let output = Arc::new(Mutex::new(Vec::new()));
|
|
|
|
let je = JsonEmitter::new(
|
|
|
|
Box::new(Shared { data: output.clone() }),
|
|
|
|
None,
|
|
|
|
sm,
|
|
|
|
true,
|
|
|
|
HumanReadableErrorType::Short(ColorConfig::Never),
|
2020-07-08 10:44:29 -07:00
|
|
|
None,
|
2019-10-03 03:55:31 +03:00
|
|
|
false,
|
|
|
|
);
|
|
|
|
|
|
|
|
let span = Span::with_root_ctxt(BytePos(span.0), BytePos(span.1));
|
|
|
|
let handler = Handler::with_emitter(true, None, Box::new(je));
|
|
|
|
handler.span_err(span, "foo");
|
|
|
|
|
|
|
|
let bytes = output.lock().unwrap();
|
|
|
|
let actual_output = str::from_utf8(&bytes).unwrap();
|
2022-02-09 17:05:44 -05:00
|
|
|
let actual_output = json::from_str(&actual_output).unwrap();
|
|
|
|
let spans = actual_output["spans"].as_array().unwrap();
|
|
|
|
assert_eq!(spans.len(), 1);
|
|
|
|
let obj = &spans[0];
|
|
|
|
let actual_output = SpanTestData {
|
|
|
|
byte_start: obj["byte_start"].as_u64().unwrap() as u32,
|
|
|
|
byte_end: obj["byte_end"].as_u64().unwrap() as u32,
|
|
|
|
line_start: obj["line_start"].as_u64().unwrap() as u32,
|
|
|
|
line_end: obj["line_end"].as_u64().unwrap() as u32,
|
|
|
|
column_start: obj["column_start"].as_u64().unwrap() as u32,
|
|
|
|
column_end: obj["column_end"].as_u64().unwrap() as u32,
|
|
|
|
};
|
|
|
|
assert_eq!(expected_output, actual_output);
|
2019-10-03 03:55:31 +03:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn empty() {
|
|
|
|
test_positions(
|
|
|
|
" ",
|
|
|
|
(0, 1),
|
|
|
|
SpanTestData {
|
|
|
|
byte_start: 0,
|
|
|
|
byte_end: 1,
|
|
|
|
line_start: 1,
|
|
|
|
column_start: 1,
|
|
|
|
line_end: 1,
|
|
|
|
column_end: 2,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn bom() {
|
|
|
|
test_positions(
|
|
|
|
"\u{feff} ",
|
|
|
|
(0, 1),
|
|
|
|
SpanTestData {
|
|
|
|
byte_start: 3,
|
|
|
|
byte_end: 4,
|
|
|
|
line_start: 1,
|
|
|
|
column_start: 1,
|
|
|
|
line_end: 1,
|
|
|
|
column_end: 2,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn lf_newlines() {
|
|
|
|
test_positions(
|
|
|
|
"\nmod foo;\nmod bar;\n",
|
|
|
|
(5, 12),
|
|
|
|
SpanTestData {
|
|
|
|
byte_start: 5,
|
|
|
|
byte_end: 12,
|
|
|
|
line_start: 2,
|
|
|
|
column_start: 5,
|
|
|
|
line_end: 3,
|
|
|
|
column_end: 3,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn crlf_newlines() {
|
|
|
|
test_positions(
|
|
|
|
"\r\nmod foo;\r\nmod bar;\r\n",
|
|
|
|
(5, 12),
|
|
|
|
SpanTestData {
|
|
|
|
byte_start: 6,
|
|
|
|
byte_end: 14,
|
|
|
|
line_start: 2,
|
|
|
|
column_start: 5,
|
|
|
|
line_end: 3,
|
|
|
|
column_end: 3,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn crlf_newlines_with_bom() {
|
|
|
|
test_positions(
|
|
|
|
"\u{feff}\r\nmod foo;\r\nmod bar;\r\n",
|
|
|
|
(5, 12),
|
|
|
|
SpanTestData {
|
|
|
|
byte_start: 9,
|
|
|
|
byte_end: 17,
|
|
|
|
line_start: 2,
|
|
|
|
column_start: 5,
|
|
|
|
line_end: 3,
|
|
|
|
column_end: 3,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn span_before_crlf() {
|
|
|
|
test_positions(
|
|
|
|
"foo\r\nbar",
|
|
|
|
(2, 3),
|
|
|
|
SpanTestData {
|
|
|
|
byte_start: 2,
|
|
|
|
byte_end: 3,
|
|
|
|
line_start: 1,
|
|
|
|
column_start: 3,
|
|
|
|
line_end: 1,
|
|
|
|
column_end: 4,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn span_on_crlf() {
|
|
|
|
test_positions(
|
|
|
|
"foo\r\nbar",
|
|
|
|
(3, 4),
|
|
|
|
SpanTestData {
|
|
|
|
byte_start: 3,
|
|
|
|
byte_end: 5,
|
|
|
|
line_start: 1,
|
|
|
|
column_start: 4,
|
|
|
|
line_end: 2,
|
|
|
|
column_end: 1,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn span_after_crlf() {
|
|
|
|
test_positions(
|
|
|
|
"foo\r\nbar",
|
|
|
|
(4, 5),
|
|
|
|
SpanTestData {
|
|
|
|
byte_start: 5,
|
|
|
|
byte_end: 6,
|
|
|
|
line_start: 2,
|
|
|
|
column_start: 1,
|
|
|
|
line_end: 2,
|
|
|
|
column_end: 2,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|