diff --git a/src/libsyntax/errors/emitter.rs b/src/libsyntax/errors/emitter.rs index b5be0fa16dd..7f4d1a9dc34 100644 --- a/src/libsyntax/errors/emitter.rs +++ b/src/libsyntax/errors/emitter.rs @@ -135,6 +135,9 @@ pub struct EmitterWriter { /// Is this the first error emitted thus far? If not, we emit a /// `\n` before the top-level errors. first: bool, + + // For now, allow an old-school mode while we transition + old_school: bool, } impl CoreEmitter for EmitterWriter { @@ -170,14 +173,23 @@ impl EmitterWriter { registry: Option, code_map: Rc) -> EmitterWriter { + let old_school = match ::std::env::var("RUST_NEW_ERROR_FORMAT") { + Ok(_) => false, + Err(_) => true, + }; if color_config.use_color() { let dst = Destination::from_stderr(); - EmitterWriter { dst: dst, registry: registry, cm: code_map, first: true } + EmitterWriter { dst: dst, + registry: registry, + cm: code_map, + first: true, + old_school: old_school } } else { EmitterWriter { dst: Raw(Box::new(io::stderr())), registry: registry, cm: code_map, - first: true } + first: true, + old_school: old_school } } } @@ -185,7 +197,15 @@ impl EmitterWriter { registry: Option, code_map: Rc) -> EmitterWriter { - EmitterWriter { dst: Raw(dst), registry: registry, cm: code_map, first: true } + let old_school = match ::std::env::var("RUST_NEW_ERROR_FORMAT") { + Ok(_) => false, + Err(_) => true, + }; + EmitterWriter { dst: Raw(dst), + registry: registry, + cm: code_map, + first: true, + old_school: old_school } } fn emit_message_(&mut self, @@ -199,7 +219,9 @@ impl EmitterWriter { if self.first { self.first = false; } else { - write!(self.dst, "\n")?; + if !self.old_school { + write!(self.dst, "\n")?; + } } } @@ -208,7 +230,17 @@ impl EmitterWriter { .and_then(|registry| registry.find_description(code)) .is_some() => { let code_with_explain = String::from("--explain ") + code; - print_diagnostic(&mut self.dst, "", lvl, msg, Some(&code_with_explain))? + if self.old_school { + let loc = match rsp.span().primary_span() { + Some(COMMAND_LINE_SP) | Some(DUMMY_SP) => "".to_string(), + Some(ps) => self.cm.span_to_string(ps), + None => "".to_string() + }; + print_diagnostic(&mut self.dst, &loc, lvl, msg, Some(code))? + } + else { + print_diagnostic(&mut self.dst, "", lvl, msg, Some(&code_with_explain))? + } } _ => { print_diagnostic(&mut self.dst, "", lvl, msg, code)? @@ -239,7 +271,24 @@ impl EmitterWriter { } } } - + if self.old_school { + match code { + Some(code) if self.registry.as_ref() + .and_then(|registry| registry.find_description(code)) + .is_some() => { + let loc = match rsp.span().primary_span() { + Some(COMMAND_LINE_SP) | Some(DUMMY_SP) => "".to_string(), + Some(ps) => self.cm.span_to_string(ps), + None => "".to_string() + }; + let msg = "run `rustc --explain ".to_string() + &code.to_string() + + "` to see a detailed explanation"; + print_diagnostic(&mut self.dst, &loc, Level::Help, &msg, + None)? + } + _ => () + } + } Ok(()) } @@ -282,19 +331,48 @@ impl EmitterWriter { { let mut snippet_data = SnippetData::new(self.cm.clone(), msp.primary_span()); - for span_label in msp.span_labels() { - snippet_data.push(span_label.span, - span_label.is_primary, - span_label.label); - } - let rendered_lines = snippet_data.render_lines(); - for rendered_line in &rendered_lines { - for styled_string in &rendered_line.text { - self.dst.apply_style(lvl, &rendered_line.kind, styled_string.style)?; - write!(&mut self.dst, "{}", styled_string.text)?; - self.dst.reset_attrs()?; + if self.old_school { + let mut output_vec = vec![]; + for span_label in msp.span_labels() { + let mut snippet_data = snippet_data.clone(); + snippet_data.push(span_label.span, + span_label.is_primary, + span_label.label); + if span_label.is_primary { + output_vec.insert(0, snippet_data); + } + else { + output_vec.push(snippet_data); + } + } + + for snippet_data in output_vec.iter() { + let rendered_lines = snippet_data.render_lines(); + for rendered_line in &rendered_lines { + for styled_string in &rendered_line.text { + self.dst.apply_style(lvl, &rendered_line.kind, styled_string.style)?; + write!(&mut self.dst, "{}", styled_string.text)?; + self.dst.reset_attrs()?; + } + write!(&mut self.dst, "\n")?; + } + } + } + else { + for span_label in msp.span_labels() { + snippet_data.push(span_label.span, + span_label.is_primary, + span_label.label); + } + let rendered_lines = snippet_data.render_lines(); + for rendered_line in &rendered_lines { + for styled_string in &rendered_line.text { + self.dst.apply_style(lvl, &rendered_line.kind, styled_string.style)?; + write!(&mut self.dst, "{}", styled_string.text)?; + self.dst.reset_attrs()?; + } + write!(&mut self.dst, "\n")?; } - write!(&mut self.dst, "\n")?; } Ok(()) } @@ -327,7 +405,6 @@ fn line_num_max_digits(line: &codemap::LineInfo) -> usize { digits } - fn print_diagnostic(dst: &mut Destination, topic: &str, lvl: Level, @@ -335,7 +412,6 @@ fn print_diagnostic(dst: &mut Destination, code: Option<&str>) -> io::Result<()> { if !topic.is_empty() { - dst.start_attr(term::Attr::ForegroundColor(lvl.color()))?; write!(dst, "{}: ", topic)?; dst.reset_attrs()?; } @@ -346,10 +422,12 @@ fn print_diagnostic(dst: &mut Destination, write!(dst, ": ")?; dst.start_attr(term::Attr::Bold)?; write!(dst, "{}", msg)?; + if let Some(code) = code { let style = term::Attr::ForegroundColor(term::color::BRIGHT_MAGENTA); print_maybe_styled!(dst, style, " [{}]", code.clone())?; } + dst.reset_attrs()?; write!(dst, "\n")?; Ok(()) diff --git a/src/libsyntax/errors/snippet/mod.rs b/src/libsyntax/errors/snippet/mod.rs index feaf48352db..18a64cc399c 100644 --- a/src/libsyntax/errors/snippet/mod.rs +++ b/src/libsyntax/errors/snippet/mod.rs @@ -17,11 +17,13 @@ use std::mem; mod test; +#[derive(Clone)] pub struct SnippetData { codemap: Rc, files: Vec, } +#[derive(Clone)] pub struct FileInfo { file: Rc, @@ -35,6 +37,7 @@ pub struct FileInfo { lines: Vec, } +#[derive(Clone)] struct Line { line_index: usize, annotations: Vec, @@ -429,6 +432,10 @@ impl FileInfo { } fn render_file_lines(&self, codemap: &Rc) -> Vec { + let old_school = match ::std::env::var("RUST_NEW_ERROR_FORMAT") { + Ok(_) => false, + Err(_) => true, + }; // As a first step, we elide any instance of more than one // continuous unannotated line. @@ -436,28 +443,30 @@ impl FileInfo { let mut output = vec![]; // First insert the name of the file. - match self.primary_span { - Some(span) => { - let lo = codemap.lookup_char_pos(span.lo); - output.push(RenderedLine { - text: vec![StyledString { - text: lo.file.name.clone(), - style: Style::FileNameStyle, - }, StyledString { - text: format!(":{}:{}", lo.line, lo.col.0 + 1), - style: Style::LineAndColumn, - }], - kind: RenderedLineKind::PrimaryFileName, - }); - } - None => { - output.push(RenderedLine { - text: vec![StyledString { - text: self.file.name.clone(), - style: Style::FileNameStyle, - }], - kind: RenderedLineKind::OtherFileName, - }); + if !old_school { + match self.primary_span { + Some(span) => { + let lo = codemap.lookup_char_pos(span.lo); + output.push(RenderedLine { + text: vec![StyledString { + text: lo.file.name.clone(), + style: Style::FileNameStyle, + }, StyledString { + text: format!(":{}:{}", lo.line, lo.col.0 + 1), + style: Style::LineAndColumn, + }], + kind: RenderedLineKind::PrimaryFileName, + }); + } + None => { + output.push(RenderedLine { + text: vec![StyledString { + text: self.file.name.clone(), + style: Style::FileNameStyle, + }], + kind: RenderedLineKind::OtherFileName, + }); + } } } @@ -466,7 +475,31 @@ impl FileInfo { // Consume lines with annotations. while let Some(line) = next_line { if line.annotations.is_empty() { break; } - output.append(&mut self.render_line(line)); + + let mut rendered_line = self.render_line(line); + if old_school { + match self.primary_span { + Some(span) => { + let lo = codemap.lookup_char_pos(span.lo); + rendered_line[0].text.insert(0, StyledString { + text: format!(":{} ", lo.line), + style: Style::LineAndColumn, + }); + rendered_line[0].text.insert(0, StyledString { + text: lo.file.name.clone(), + style: Style::FileNameStyle, + }); + let gap_amount = rendered_line[0].text[0].text.len() + + rendered_line[0].text[1].text.len(); + rendered_line[1].text.insert(0, StyledString { + text: vec![" "; gap_amount].join(""), + style: Style::NoStyle + }); + } + _ =>() + } + } + output.append(&mut rendered_line); next_line = lines_iter.next(); } @@ -492,6 +525,10 @@ impl FileInfo { } fn render_line(&self, line: &Line) -> Vec { + let old_school = match ::std::env::var("RUST_NEW_ERROR_FORMAT") { + Ok(_) => false, + Err(_) => true, + }; let source_string = self.file.get_line(line.line_index) .unwrap_or(""); let source_kind = RenderedLineKind::SourceText { @@ -535,12 +572,34 @@ impl FileInfo { // Next, create the highlight line. for annotation in &annotations { - for p in annotation.start_col .. annotation.end_col { - if annotation.is_primary { - styled_buffer.putc(1, p, '^', Style::UnderlinePrimary); - styled_buffer.set_style(0, p, Style::UnderlinePrimary); - } else { - styled_buffer.putc(1, p, '-', Style::UnderlineSecondary); + if old_school { + for p in annotation.start_col .. annotation.end_col { + if p == annotation.start_col { + styled_buffer.putc(1, p, '^', + if annotation.is_primary { + Style::UnderlinePrimary + } else { + Style::UnderlineSecondary + }); + } + else { + styled_buffer.putc(1, p, '~', + if annotation.is_primary { + Style::UnderlinePrimary + } else { + Style::UnderlineSecondary + }); + } + } + } + else { + for p in annotation.start_col .. annotation.end_col { + if annotation.is_primary { + styled_buffer.putc(1, p, '^', Style::UnderlinePrimary); + styled_buffer.set_style(0, p, Style::UnderlinePrimary); + } else { + styled_buffer.putc(1, p, '-', Style::UnderlineSecondary); + } } } } @@ -555,6 +614,9 @@ impl FileInfo { if labeled_annotations.is_empty() { return styled_buffer.render(source_kind); } + if old_school { + return styled_buffer.render(source_kind); + } // Now add the text labels. We try, when possible, to stick the rightmost // annotation at the end of the highlight line: @@ -647,6 +709,14 @@ impl FileInfo { } fn prepend_prefixes(rendered_lines: &mut [RenderedLine]) { + let old_school = match ::std::env::var("RUST_NEW_ERROR_FORMAT") { + Ok(_) => false, + Err(_) => true, + }; + if old_school { + return; + } + let prefixes: Vec<_> = rendered_lines.iter() .map(|rl| rl.kind.prefix()) @@ -686,11 +756,14 @@ fn prepend_prefixes(rendered_lines: &mut [RenderedLine]) { style: Style::LineNumber}) } RenderedLineKind::OtherFileName => { - // >>>>> filename + // ::: filename // 22 |> // ^ // padding_len - let dashes = (0..padding_len + 2).map(|_| '>') + let dashes = (0..padding_len - 1).map(|_| ' ') + .chain(Some(':')) + .chain(Some(':')) + .chain(Some(':')) .chain(Some(' ')); line.text.insert(0, StyledString {text: dashes.collect(), style: Style::LineNumber})