mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-28 17:53:56 +00:00
test for putting back check on json
This commit is contained in:
parent
c29085761b
commit
8c75e18e5d
@ -92,7 +92,8 @@ impl<'a> DiagnosticBuilder<'a> {
|
||||
Level::Bug |
|
||||
Level::Fatal |
|
||||
Level::PhaseFatal |
|
||||
Level::Error => {
|
||||
Level::Error |
|
||||
Level::FailureNote => {
|
||||
true
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ use atty;
|
||||
use std::borrow::Cow;
|
||||
use std::io::prelude::*;
|
||||
use std::io;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::collections::HashMap;
|
||||
use std::cmp::min;
|
||||
use termcolor::{StandardStream, ColorChoice, ColorSpec, BufferWriter};
|
||||
use termcolor::{WriteColor, Color, Buffer};
|
||||
@ -33,6 +33,11 @@ const ANONYMIZED_LINE_NUM: &str = "LL";
|
||||
pub trait Emitter {
|
||||
/// Emit a structured diagnostic.
|
||||
fn emit(&mut self, db: &DiagnosticBuilder);
|
||||
|
||||
/// Check if should show explanations about "rustc --explain"
|
||||
fn should_show_explain(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl Emitter for EmitterWriter {
|
||||
@ -80,6 +85,10 @@ impl Emitter for EmitterWriter {
|
||||
&children,
|
||||
&suggestions);
|
||||
}
|
||||
|
||||
fn should_show_explain(&self) -> bool {
|
||||
!self.short_message
|
||||
}
|
||||
}
|
||||
|
||||
/// maximum number of lines we will print for each error; arbitrary.
|
||||
@ -114,7 +123,6 @@ pub struct EmitterWriter {
|
||||
cm: Option<Lrc<CodeMapper>>,
|
||||
short_message: bool,
|
||||
teach: bool,
|
||||
error_codes: HashSet<String>,
|
||||
ui_testing: bool,
|
||||
}
|
||||
|
||||
@ -124,34 +132,6 @@ struct FileWithAnnotatedLines {
|
||||
multiline_depth: usize,
|
||||
}
|
||||
|
||||
impl Drop for EmitterWriter {
|
||||
fn drop(&mut self) {
|
||||
if !self.short_message && !self.error_codes.is_empty() {
|
||||
let mut error_codes = self.error_codes.clone().into_iter().collect::<Vec<_>>();
|
||||
let mut dst = self.dst.writable();
|
||||
error_codes.sort();
|
||||
if error_codes.len() > 1 {
|
||||
let limit = if error_codes.len() > 9 { 9 } else { error_codes.len() };
|
||||
writeln!(dst,
|
||||
"You've got a few errors: {}{}",
|
||||
error_codes[..limit].join(", "),
|
||||
if error_codes.len() > 9 { "..." } else { "" }
|
||||
).expect("failed to give tips...");
|
||||
writeln!(dst,
|
||||
"If you want more information on an error, try using \
|
||||
\"rustc --explain {}\"",
|
||||
&error_codes[0]).expect("failed to give tips...");
|
||||
} else {
|
||||
writeln!(dst,
|
||||
"If you want more information on this error, try using \
|
||||
\"rustc --explain {}\"",
|
||||
&error_codes[0]).expect("failed to give tips...");
|
||||
}
|
||||
dst.flush().expect("failed to emit errors");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EmitterWriter {
|
||||
pub fn stderr(color_config: ColorConfig,
|
||||
code_map: Option<Lrc<CodeMapper>>,
|
||||
@ -164,7 +144,6 @@ impl EmitterWriter {
|
||||
cm: code_map,
|
||||
short_message,
|
||||
teach,
|
||||
error_codes: HashSet::new(),
|
||||
ui_testing: false,
|
||||
}
|
||||
}
|
||||
@ -179,7 +158,6 @@ impl EmitterWriter {
|
||||
cm: code_map,
|
||||
short_message,
|
||||
teach,
|
||||
error_codes: HashSet::new(),
|
||||
ui_testing: false,
|
||||
}
|
||||
}
|
||||
@ -993,18 +971,26 @@ impl EmitterWriter {
|
||||
buffer.prepend(0, " ", Style::NoStyle);
|
||||
}
|
||||
draw_note_separator(&mut buffer, 0, max_line_num_len + 1);
|
||||
buffer.append(0, &level.to_string(), Style::HeaderMsg);
|
||||
buffer.append(0, ": ", Style::NoStyle);
|
||||
let level_str = level.to_string();
|
||||
if !level_str.is_empty() {
|
||||
buffer.append(0, &level_str, Style::HeaderMsg);
|
||||
buffer.append(0, ": ", Style::NoStyle);
|
||||
}
|
||||
self.msg_to_buffer(&mut buffer, msg, max_line_num_len, "note", None);
|
||||
} else {
|
||||
buffer.append(0, &level.to_string(), Style::Level(level.clone()));
|
||||
let level_str = level.to_string();
|
||||
if !level_str.is_empty() {
|
||||
buffer.append(0, &level_str, Style::Level(level.clone()));
|
||||
}
|
||||
// only render error codes, not lint codes
|
||||
if let Some(DiagnosticId::Error(ref code)) = *code {
|
||||
buffer.append(0, "[", Style::Level(level.clone()));
|
||||
buffer.append(0, &code, Style::Level(level.clone()));
|
||||
buffer.append(0, "]", Style::Level(level.clone()));
|
||||
}
|
||||
buffer.append(0, ": ", Style::HeaderMsg);
|
||||
if !level_str.is_empty() {
|
||||
buffer.append(0, ": ", Style::HeaderMsg);
|
||||
}
|
||||
for &(ref text, _) in msg.iter() {
|
||||
buffer.append(0, text, Style::HeaderMsg);
|
||||
}
|
||||
@ -1020,14 +1006,12 @@ impl EmitterWriter {
|
||||
if primary_span != &&DUMMY_SP {
|
||||
(cm.lookup_char_pos(primary_span.lo()), cm)
|
||||
} else {
|
||||
emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message,
|
||||
&mut self.error_codes)?;
|
||||
emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?;
|
||||
return Ok(());
|
||||
}
|
||||
} else {
|
||||
// If we don't have span information, emit and exit
|
||||
emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message,
|
||||
&mut self.error_codes)?;
|
||||
emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?;
|
||||
return Ok(());
|
||||
};
|
||||
if let Ok(pos) =
|
||||
@ -1200,8 +1184,7 @@ impl EmitterWriter {
|
||||
}
|
||||
|
||||
// final step: take our styled buffer, render it, then output it
|
||||
emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message,
|
||||
&mut self.error_codes)?;
|
||||
emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?;
|
||||
|
||||
Ok(())
|
||||
|
||||
@ -1218,8 +1201,11 @@ impl EmitterWriter {
|
||||
let mut buffer = StyledBuffer::new();
|
||||
|
||||
// Render the suggestion message
|
||||
buffer.append(0, &level.to_string(), Style::Level(level.clone()));
|
||||
buffer.append(0, ": ", Style::HeaderMsg);
|
||||
let level_str = level.to_string();
|
||||
if !level_str.is_empty() {
|
||||
buffer.append(0, &level_str, Style::Level(level.clone()));
|
||||
buffer.append(0, ": ", Style::HeaderMsg);
|
||||
}
|
||||
self.msg_to_buffer(&mut buffer,
|
||||
&[(suggestion.msg.to_owned(), Style::NoStyle)],
|
||||
max_line_num_len,
|
||||
@ -1289,8 +1275,7 @@ impl EmitterWriter {
|
||||
let msg = format!("and {} other candidates", suggestions.len() - MAX_SUGGESTIONS);
|
||||
buffer.puts(row_num, 0, &msg, Style::NoStyle);
|
||||
}
|
||||
emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message,
|
||||
&mut self.error_codes)?;
|
||||
emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -1321,7 +1306,7 @@ impl EmitterWriter {
|
||||
draw_col_separator_no_space(&mut buffer, 0, max_line_num_len + 1);
|
||||
}
|
||||
match emit_to_destination(&buffer.render(), level, &mut self.dst,
|
||||
self.short_message, &mut self.error_codes) {
|
||||
self.short_message) {
|
||||
Ok(()) => (),
|
||||
Err(e) => panic!("failed to emit error: {}", e)
|
||||
}
|
||||
@ -1416,8 +1401,7 @@ fn overlaps(a1: &Annotation, a2: &Annotation, padding: usize) -> bool {
|
||||
fn emit_to_destination(rendered_buffer: &Vec<Vec<StyledString>>,
|
||||
lvl: &Level,
|
||||
dst: &mut Destination,
|
||||
short_message: bool,
|
||||
error_codes: &mut HashSet<String>)
|
||||
short_message: bool)
|
||||
-> io::Result<()> {
|
||||
use lock;
|
||||
|
||||
@ -1436,16 +1420,13 @@ fn emit_to_destination(rendered_buffer: &Vec<Vec<StyledString>>,
|
||||
// same buffering approach. Instead, we use a global Windows mutex, which we acquire long
|
||||
// enough to output the full error message, then we release.
|
||||
let _buffer_lock = lock::acquire_global_lock("rustc_errors");
|
||||
for line in rendered_buffer {
|
||||
for (pos, line) in rendered_buffer.iter().enumerate() {
|
||||
for part in line {
|
||||
dst.apply_style(lvl.clone(), part.style)?;
|
||||
write!(dst, "{}", part.text)?;
|
||||
if !short_message && part.text.len() == 12 && part.text.starts_with("error[E") {
|
||||
error_codes.insert(part.text[6..11].to_owned());
|
||||
}
|
||||
dst.reset()?;
|
||||
}
|
||||
if !short_message {
|
||||
if !short_message && (!lvl.is_failure_note() || pos != rendered_buffer.len() - 1) {
|
||||
write!(dst, "\n")?;
|
||||
}
|
||||
}
|
||||
|
@ -509,12 +509,14 @@ impl Handler {
|
||||
pub fn span_unimpl<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
|
||||
self.span_bug(sp, &format!("unimplemented {}", msg));
|
||||
}
|
||||
pub fn failure(&self, msg: &str) {
|
||||
DiagnosticBuilder::new(self, FailureNote, msg).emit()
|
||||
}
|
||||
pub fn fatal(&self, msg: &str) -> FatalError {
|
||||
if self.flags.treat_err_as_bug {
|
||||
self.bug(msg);
|
||||
}
|
||||
let mut db = DiagnosticBuilder::new(self, Fatal, msg);
|
||||
db.emit();
|
||||
DiagnosticBuilder::new(self, Fatal, msg).emit();
|
||||
FatalError
|
||||
}
|
||||
pub fn err(&self, msg: &str) {
|
||||
@ -567,8 +569,39 @@ impl Handler {
|
||||
s = format!("aborting due to {} previous errors", self.err_count());
|
||||
}
|
||||
}
|
||||
let err = self.fatal(&s);
|
||||
|
||||
self.fatal(&s).raise();
|
||||
let can_show_explain = self.emitter.borrow().should_show_explain();
|
||||
let are_there_diagnostics = !self.tracked_diagnostic_codes.borrow().is_empty();
|
||||
if can_show_explain && are_there_diagnostics {
|
||||
let mut error_codes =
|
||||
self.tracked_diagnostic_codes.borrow()
|
||||
.clone()
|
||||
.into_iter()
|
||||
.filter_map(|x| match x {
|
||||
DiagnosticId::Error(ref s) => Some(s.clone()),
|
||||
_ => None,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
if !error_codes.is_empty() {
|
||||
error_codes.sort();
|
||||
if error_codes.len() > 1 {
|
||||
let limit = if error_codes.len() > 9 { 9 } else { error_codes.len() };
|
||||
self.failure(&format!("Some errors occurred: {}{}",
|
||||
error_codes[..limit].join(", "),
|
||||
if error_codes.len() > 9 { "..." } else { "." }));
|
||||
self.failure(&format!("For more information about an error, try \
|
||||
`rustc --explain {}`.",
|
||||
&error_codes[0]));
|
||||
} else {
|
||||
self.failure(&format!("For more information about this error, try \
|
||||
`rustc --explain {}`.",
|
||||
&error_codes[0]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err.raise();
|
||||
}
|
||||
pub fn emit(&self, msp: &MultiSpan, msg: &str, lvl: Level) {
|
||||
if lvl == Warning && !self.flags.can_emit_warnings {
|
||||
@ -654,6 +687,7 @@ pub enum Level {
|
||||
Note,
|
||||
Help,
|
||||
Cancelled,
|
||||
FailureNote,
|
||||
}
|
||||
|
||||
impl fmt::Display for Level {
|
||||
@ -682,9 +716,10 @@ impl Level {
|
||||
spec.set_fg(Some(Color::Cyan))
|
||||
.set_intense(true);
|
||||
}
|
||||
FailureNote => {}
|
||||
Cancelled => unreachable!(),
|
||||
}
|
||||
return spec
|
||||
spec
|
||||
}
|
||||
|
||||
pub fn to_str(self) -> &'static str {
|
||||
@ -694,7 +729,15 @@ impl Level {
|
||||
Warning => "warning",
|
||||
Note => "note",
|
||||
Help => "help",
|
||||
FailureNote => "",
|
||||
Cancelled => panic!("Shouldn't call on cancelled error"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_failure_note(&self) -> bool {
|
||||
match *self {
|
||||
FailureNote => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ struct Diagnostic {
|
||||
level: String,
|
||||
spans: Vec<DiagnosticSpan>,
|
||||
children: Vec<Diagnostic>,
|
||||
rendered: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Clone)]
|
||||
@ -56,6 +57,25 @@ struct DiagnosticCode {
|
||||
explanation: Option<String>,
|
||||
}
|
||||
|
||||
pub fn extract_rendered(output: &str, proc_res: &ProcRes) -> String {
|
||||
output.lines()
|
||||
.filter_map(|line| if line.starts_with('{') {
|
||||
match serde_json::from_str::<Diagnostic>(line) {
|
||||
Ok(diagnostic) => diagnostic.rendered,
|
||||
Err(error) => {
|
||||
proc_res.fatal(Some(&format!("failed to decode compiler output as json: \
|
||||
`{}`\noutput: {}\nline: {}",
|
||||
error,
|
||||
line,
|
||||
output)));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn parse_output(file_name: &str, output: &str, proc_res: &ProcRes) -> Vec<Error> {
|
||||
output.lines()
|
||||
.flat_map(|line| parse_line(file_name, line, output, proc_res))
|
||||
|
@ -248,7 +248,7 @@ impl<'test> TestCx<'test> {
|
||||
}
|
||||
|
||||
fn run_cfail_test(&self) {
|
||||
let proc_res = self.compile_test(&[]);
|
||||
let proc_res = self.compile_test();
|
||||
self.check_if_test_should_compile(&proc_res);
|
||||
self.check_no_compiler_crash(&proc_res);
|
||||
|
||||
@ -267,7 +267,7 @@ impl<'test> TestCx<'test> {
|
||||
}
|
||||
|
||||
fn run_rfail_test(&self) {
|
||||
let proc_res = self.compile_test(&[]);
|
||||
let proc_res = self.compile_test();
|
||||
|
||||
if !proc_res.status.success() {
|
||||
self.fatal_proc_rec("compilation failed!", &proc_res);
|
||||
@ -309,7 +309,7 @@ impl<'test> TestCx<'test> {
|
||||
}
|
||||
|
||||
fn run_rpass_test(&self) {
|
||||
let proc_res = self.compile_test(&[]);
|
||||
let proc_res = self.compile_test();
|
||||
|
||||
if !proc_res.status.success() {
|
||||
self.fatal_proc_rec("compilation failed!", &proc_res);
|
||||
@ -336,7 +336,7 @@ impl<'test> TestCx<'test> {
|
||||
return self.run_rpass_test();
|
||||
}
|
||||
|
||||
let mut proc_res = self.compile_test(&[]);
|
||||
let mut proc_res = self.compile_test();
|
||||
|
||||
if !proc_res.status.success() {
|
||||
self.fatal_proc_rec("compilation failed!", &proc_res);
|
||||
@ -578,7 +578,7 @@ impl<'test> TestCx<'test> {
|
||||
let mut cmds = commands.join("\n");
|
||||
|
||||
// compile test file (it should have 'compile-flags:-g' in the header)
|
||||
let compiler_run_result = self.compile_test(&[]);
|
||||
let compiler_run_result = self.compile_test();
|
||||
if !compiler_run_result.status.success() {
|
||||
self.fatal_proc_rec("compilation failed!", &compiler_run_result);
|
||||
}
|
||||
@ -835,7 +835,7 @@ impl<'test> TestCx<'test> {
|
||||
|
||||
fn run_debuginfo_lldb_test_no_opt(&self) {
|
||||
// compile test file (it should have 'compile-flags:-g' in the header)
|
||||
let compile_result = self.compile_test(&[]);
|
||||
let compile_result = self.compile_test();
|
||||
if !compile_result.status.success() {
|
||||
self.fatal_proc_rec("compilation failed!", &compile_result);
|
||||
}
|
||||
@ -1272,15 +1272,12 @@ impl<'test> TestCx<'test> {
|
||||
}
|
||||
}
|
||||
|
||||
fn compile_test(&self, extra_args: &[&'static str]) -> ProcRes {
|
||||
fn compile_test(&self) -> ProcRes {
|
||||
let mut rustc = self.make_compile_args(
|
||||
&self.testpaths.file,
|
||||
TargetLocation::ThisFile(self.make_exe_name()),
|
||||
);
|
||||
|
||||
if !extra_args.is_empty() {
|
||||
rustc.args(extra_args);
|
||||
}
|
||||
rustc.arg("-L").arg(&self.aux_output_dir_name());
|
||||
|
||||
match self.config.mode {
|
||||
@ -1626,12 +1623,14 @@ impl<'test> TestCx<'test> {
|
||||
if self.props.error_patterns.is_empty() {
|
||||
rustc.args(&["--error-format", "json"]);
|
||||
}
|
||||
if !self.props.disable_ui_testing_normalization {
|
||||
rustc.arg("-Zui-testing");
|
||||
}
|
||||
}
|
||||
Ui => {
|
||||
// In case no "--error-format" has been given in the test, we'll compile
|
||||
// a first time to get the compiler's output then compile with
|
||||
// "--error-format json" to check if all expected errors are actually there
|
||||
// and that no new one appeared.
|
||||
if !self.props.compile_flags.iter().any(|s| s.starts_with("--error-format")) {
|
||||
rustc.args(&["--error-format", "json"]);
|
||||
}
|
||||
if !self.props.disable_ui_testing_normalization {
|
||||
rustc.arg("-Zui-testing");
|
||||
}
|
||||
@ -2114,7 +2113,7 @@ impl<'test> TestCx<'test> {
|
||||
fn run_codegen_units_test(&self) {
|
||||
assert!(self.revision.is_none(), "revisions not relevant here");
|
||||
|
||||
let proc_res = self.compile_test(&[]);
|
||||
let proc_res = self.compile_test();
|
||||
|
||||
if !proc_res.status.success() {
|
||||
self.fatal_proc_rec("compilation failed!", &proc_res);
|
||||
@ -2505,7 +2504,7 @@ impl<'test> TestCx<'test> {
|
||||
.iter()
|
||||
.any(|s| s.contains("--error-format"));
|
||||
|
||||
let proc_res = self.compile_test(&[]);
|
||||
let proc_res = self.compile_test();
|
||||
self.check_if_test_should_compile(&proc_res);
|
||||
|
||||
let expected_stderr_path = self.expected_output_path(UI_STDERR);
|
||||
@ -2517,8 +2516,13 @@ impl<'test> TestCx<'test> {
|
||||
let normalized_stdout =
|
||||
self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout);
|
||||
|
||||
let normalized_stderr = self.normalize_output(&proc_res.stderr,
|
||||
&self.props.normalize_stderr);
|
||||
let stderr = if explicit {
|
||||
proc_res.stderr.clone()
|
||||
} else {
|
||||
json::extract_rendered(&proc_res.stderr, &proc_res)
|
||||
};
|
||||
|
||||
let normalized_stderr = self.normalize_output(&stderr, &self.props.normalize_stderr);
|
||||
|
||||
let mut errors = 0;
|
||||
errors += self.compare_output("stdout", &normalized_stdout, &expected_stdout);
|
||||
@ -2551,7 +2555,6 @@ impl<'test> TestCx<'test> {
|
||||
}
|
||||
}
|
||||
if !explicit {
|
||||
let proc_res = self.compile_test(&["--error-format", "json"]);
|
||||
if !expected_errors.is_empty() || !proc_res.status.success() {
|
||||
// "// error-pattern" comments
|
||||
self.check_expected_errors(expected_errors, &proc_res);
|
||||
@ -2563,7 +2566,7 @@ impl<'test> TestCx<'test> {
|
||||
}
|
||||
|
||||
fn run_mir_opt_test(&self) {
|
||||
let proc_res = self.compile_test(&[]);
|
||||
let proc_res = self.compile_test();
|
||||
|
||||
if !proc_res.status.success() {
|
||||
self.fatal_proc_rec("compilation failed!", &proc_res);
|
||||
|
Loading…
Reference in New Issue
Block a user