Skip to content

Commit

Permalink
test for putting back check on json
Browse files Browse the repository at this point in the history
  • Loading branch information
GuillaumeGomez committed Mar 13, 2018
1 parent c290857 commit 8c75e18
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 79 deletions.
3 changes: 2 additions & 1 deletion src/librustc_errors/diagnostic_builder.rs
Expand Up @@ -92,7 +92,8 @@ impl<'a> DiagnosticBuilder<'a> {
Level::Bug |
Level::Fatal |
Level::PhaseFatal |
Level::Error => {
Level::Error |
Level::FailureNote => {
true
}

Expand Down
89 changes: 35 additions & 54 deletions src/librustc_errors/emitter.rs
Expand Up @@ -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};
Expand All @@ -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 {
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -114,7 +123,6 @@ pub struct EmitterWriter {
cm: Option<Lrc<CodeMapper>>,
short_message: bool,
teach: bool,
error_codes: HashSet<String>,
ui_testing: bool,
}

Expand All @@ -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>>,
Expand All @@ -164,7 +144,6 @@ impl EmitterWriter {
cm: code_map,
short_message,
teach,
error_codes: HashSet::new(),
ui_testing: false,
}
}
Expand All @@ -179,7 +158,6 @@ impl EmitterWriter {
cm: code_map,
short_message,
teach,
error_codes: HashSet::new(),
ui_testing: false,
}
}
Expand Down Expand Up @@ -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);
}
Expand All @@ -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) =
Expand Down Expand Up @@ -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(())

Expand All @@ -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,
Expand Down Expand Up @@ -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(())
}
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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;

Expand All @@ -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")?;
}
}
Expand Down
51 changes: 47 additions & 4 deletions src/librustc_errors/lib.rs
Expand Up @@ -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) {
Expand Down Expand Up @@ -567,8 +569,39 @@ impl Handler {
s = format!("aborting due to {} previous errors", self.err_count());
}
}
let err = self.fatal(&s);

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]));
}
}
}

self.fatal(&s).raise();
err.raise();
}
pub fn emit(&self, msp: &MultiSpan, msg: &str, lvl: Level) {
if lvl == Warning && !self.flags.can_emit_warnings {
Expand Down Expand Up @@ -654,6 +687,7 @@ pub enum Level {
Note,
Help,
Cancelled,
FailureNote,
}

impl fmt::Display for Level {
Expand Down Expand Up @@ -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 {
Expand All @@ -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,
}
}
}
20 changes: 20 additions & 0 deletions src/tools/compiletest/src/json.rs
Expand Up @@ -24,6 +24,7 @@ struct Diagnostic {
level: String,
spans: Vec<DiagnosticSpan>,
children: Vec<Diagnostic>,
rendered: Option<String>,
}

#[derive(Deserialize, Clone)]
Expand Down Expand Up @@ -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))
Expand Down

0 comments on commit 8c75e18

Please sign in to comment.