diff --git a/benches/bench.rs b/benches/bench.rs index 32b67c3f..6390628f 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -24,8 +24,9 @@ fn simple() -> String { _ => continue, } }"#; - let message = Level::ERROR.header("mismatched types").id("E0308").group( - Group::new().element( + let message = &[Group::new() + .element(Level::ERROR.title("mismatched types").id("E0308")) + .element( Snippet::source(source) .line_start(51) .path("src/format.rs") @@ -39,8 +40,7 @@ fn simple() -> String { .span(26..724) .label("expected enum `std::option::Option`"), ), - ), - ); + )]; let renderer = Renderer::plain(); let rendered = renderer.render(message); @@ -69,8 +69,9 @@ fn fold(bencher: divan::Bencher<'_, '_>, context: usize) { (input, span) }) .bench_values(|(input, span)| { - let message = Level::ERROR.header("mismatched types").id("E0308").group( - Group::new().element( + let message = &[Group::new() + .element(Level::ERROR.title("mismatched types").id("E0308")) + .element( Snippet::source(&input) .fold(true) .path("src/format.rs") @@ -79,8 +80,7 @@ fn fold(bencher: divan::Bencher<'_, '_>, context: usize) { .span(span) .label("expected `Option` because of return type"), ), - ), - ); + )]; let renderer = Renderer::plain(); let rendered = renderer.render(message); diff --git a/examples/custom_error.rs b/examples/custom_error.rs index dfb8fc6c..e80b1466 100644 --- a/examples/custom_error.rs +++ b/examples/custom_error.rs @@ -15,22 +15,23 @@ fn main() { pub static C: u32 = 0 - 1; //~^ ERROR could not evaluate static initializer "#; - let message = Level::ERROR - .text(Some("error: internal compiler error")) - .header("could not evaluate static initializer") - .id("E0080") - .group( - Group::new().element( - Snippet::source(source) - .path("$DIR/err.rs") - .fold(true) - .annotation( - AnnotationKind::Primary - .span(386..391) - .label("attempt to compute `0_u32 - 1_u32`, which would overflow"), - ), - ), - ); + let message = &[Group::new() + .element( + Level::ERROR + .text(Some("error: internal compiler error")) + .title("could not evaluate static initializer") + .id("E0080"), + ) + .element( + Snippet::source(source) + .path("$DIR/err.rs") + .fold(true) + .annotation( + AnnotationKind::Primary + .span(386..391) + .label("attempt to compute `0_u32 - 1_u32`, which would overflow"), + ), + )]; let renderer = Renderer::styled().theme(OutputTheme::Unicode); anstream::println!("{}", renderer.render(message)); diff --git a/examples/custom_level.rs b/examples/custom_level.rs index 57f2fb5a..b500c063 100644 --- a/examples/custom_level.rs +++ b/examples/custom_level.rs @@ -29,11 +29,14 @@ fn main() { } } "#; - let message = Level::ERROR - .header("`break` with value from a `while` loop") - .id("E0571") - .group( - Group::new().element( + let message = &[ + Group::new() + .element( + Level::ERROR + .title("`break` with value from a `while` loop") + .id("E0571"), + ) + .element( Snippet::source(source) .line_start(1) .path("$DIR/issue-114529-illegal-break-with-value.rs") @@ -49,22 +52,20 @@ fn main() { .label("you can't `break` with a value in a `while` loop"), ), ), - ) - .group( - Group::new() - .element( - Level::HELP - .text(Some("suggestion")) - .title("use `break` on its own without a value inside this `while` loop"), - ) - .element( - Snippet::source(source) - .line_start(1) - .path("$DIR/issue-114529-illegal-break-with-value.rs") - .fold(true) - .patch(Patch::new(483..581, "break")), - ), - ); + Group::new() + .element( + Level::HELP + .text(Some("suggestion")) + .title("use `break` on its own without a value inside this `while` loop"), + ) + .element( + Snippet::source(source) + .line_start(1) + .path("$DIR/issue-114529-illegal-break-with-value.rs") + .fold(true) + .patch(Patch::new(483..581, "break")), + ), + ]; let renderer = Renderer::styled().theme(OutputTheme::Unicode); anstream::println!("{}", renderer.render(message)); diff --git a/examples/expected_type.rs b/examples/expected_type.rs index 440c64c3..0fce9938 100644 --- a/examples/expected_type.rs +++ b/examples/expected_type.rs @@ -6,8 +6,9 @@ fn main() { , range: <22, 25>,"#; let message = - Level::ERROR.header("expected type, found `22`").group( - Group::new().element( + &[Group::new() + .element(Level::ERROR.title("expected type, found `22`")) + .element( Snippet::source(source) .line_start(26) .path("examples/footer.rs") @@ -20,8 +21,7 @@ fn main() { .span(34..50) .label("while parsing this struct"), ), - ), - ); + )]; let renderer = Renderer::styled(); anstream::println!("{}", renderer.render(message)); diff --git a/examples/footer.rs b/examples/footer.rs index 36173350..aa9b784f 100644 --- a/examples/footer.rs +++ b/examples/footer.rs @@ -1,11 +1,10 @@ use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; fn main() { - let message = Level::ERROR - .header("mismatched types") - .id("E0308") - .group( - Group::new().element( + let message = &[ + Group::new() + .element(Level::ERROR.title("mismatched types").id("E0308")) + .element( Snippet::source(" slices: vec![\"A\",") .line_start(13) .path("src/multislice.rs") @@ -13,10 +12,10 @@ fn main() { "expected struct `annotate_snippets::snippet::Slice`, found reference", )), ), - ) - .group(Group::new().element(Level::NOTE.title( + Group::new().element(Level::NOTE.title( "expected type: `snippet::Annotation`\n found type: `__&__snippet::Annotation`", - ))); + )), + ]; let renderer = Renderer::styled(); anstream::println!("{}", renderer.render(message)); diff --git a/examples/format.rs b/examples/format.rs index 4268e315..ae603259 100644 --- a/examples/format.rs +++ b/examples/format.rs @@ -23,8 +23,9 @@ fn main() { _ => continue, } }"#; - let message = Level::ERROR.header("mismatched types").id("E0308").group( - Group::new().element( + let message = &[Group::new() + .element(Level::ERROR.title("mismatched types").id("E0308")) + .element( Snippet::source(source) .line_start(51) .path("src/format.rs") @@ -38,8 +39,7 @@ fn main() { .span(26..724) .label("expected enum `std::option::Option`"), ), - ), - ); + )]; let renderer = Renderer::styled(); anstream::println!("{}", renderer.render(message)); diff --git a/examples/highlight_source.rs b/examples/highlight_source.rs index f5871453..f897a3f5 100644 --- a/examples/highlight_source.rs +++ b/examples/highlight_source.rs @@ -9,26 +9,23 @@ const CON: Vec = vec![1, 2, 3]; //~ ERROR E0010 //~| ERROR cannot call non-const method fn main() {} "#; - let message = Level::ERROR - .header("allocations are not allowed in constants") - .id("E0010") - .group( - Group::new() - .element( - Snippet::source(source) - .fold(true) - .path("$DIR/E0010-teach.rs") - .annotation( - AnnotationKind::Primary - .span(72..85) - .label("allocation not allowed in constants") - .highlight_source(true), - ), - ) - .element( - Level::NOTE.title("The runtime heap is not yet available at compile-time, so no runtime heap allocations can be created."), + let message = &[Group::new().element(Level::ERROR.title("allocations are not allowed in constants") + .id("E0010")) + .element( + Snippet::source(source) + .fold(true) + .path("$DIR/E0010-teach.rs") + .annotation( + AnnotationKind::Primary + .span(72..85) + .label("allocation not allowed in constants") + .highlight_source(true), ), - ); + ) + .element( + Level::NOTE.title("The runtime heap is not yet available at compile-time, so no runtime heap allocations can be created."), + + )]; let renderer = Renderer::styled().anonymized_line_numbers(true); anstream::println!("{}", renderer.render(message)); diff --git a/examples/highlight_title.rs b/examples/highlight_title.rs index 2f74a37b..6ed3817f 100644 --- a/examples/highlight_title.rs +++ b/examples/highlight_title.rs @@ -41,39 +41,35 @@ fn main() { magenta.render_reset() ); - let message = Level::ERROR - .header("mismatched types") - .id("E0308") - .group( - Group::new() - .element( - Snippet::source(source) - .fold(true) - .path("$DIR/highlighting.rs") - .annotation( - AnnotationKind::Primary - .span(553..563) - .label("one type is more general than the other"), - ) - .annotation( - AnnotationKind::Context - .span(547..552) - .label("arguments to this function are incorrect"), - ), - ) - .element(Level::NOTE.title(&title)), - ) - .group( - Group::new() - .element(Level::NOTE.title("function defined here")) - .element( - Snippet::source(source) - .fold(true) - .path("$DIR/highlighting.rs") - .annotation(AnnotationKind::Context.span(200..333).label("")) - .annotation(AnnotationKind::Primary.span(194..199)), - ), - ); + let message = &[ + Group::new() + .element(Level::ERROR.title("mismatched types").id("E0308")) + .element( + Snippet::source(source) + .fold(true) + .path("$DIR/highlighting.rs") + .annotation( + AnnotationKind::Primary + .span(553..563) + .label("one type is more general than the other"), + ) + .annotation( + AnnotationKind::Context + .span(547..552) + .label("arguments to this function are incorrect"), + ), + ) + .element(Level::NOTE.pre_styled_title(&title)), + Group::new() + .element(Level::NOTE.title("function defined here")) + .element( + Snippet::source(source) + .fold(true) + .path("$DIR/highlighting.rs") + .annotation(AnnotationKind::Context.span(200..333).label("")) + .annotation(AnnotationKind::Primary.span(194..199)), + ), + ]; let renderer = Renderer::styled().anonymized_line_numbers(true); anstream::println!("{}", renderer.render(message)); diff --git a/examples/id_hyperlink.rs b/examples/id_hyperlink.rs index 209fc15b..2d49b275 100644 --- a/examples/id_hyperlink.rs +++ b/examples/id_hyperlink.rs @@ -7,28 +7,29 @@ fn main() { let () = 4; //~ ERROR } "#; - let message = Level::ERROR - .header("mismatched types") - .id("E0308") - .id_url("https://doc.rust-lang.org/error_codes/E0308.html") - .group( - Group::new().element( - Snippet::source(source) - .line_start(1) - .path("$DIR/terminal_urls.rs") - .fold(true) - .annotation( - AnnotationKind::Primary - .span(59..61) - .label("expected integer, found `()`"), - ) - .annotation( - AnnotationKind::Context - .span(64..65) - .label("this expression has type `{integer}`"), - ), - ), - ); + let message = &[Group::new() + .element( + Level::ERROR + .title("mismatched types") + .id("E0308") + .id_url("https://doc.rust-lang.org/error_codes/E0308.html"), + ) + .element( + Snippet::source(source) + .line_start(1) + .path("$DIR/terminal_urls.rs") + .fold(true) + .annotation( + AnnotationKind::Primary + .span(59..61) + .label("expected integer, found `()`"), + ) + .annotation( + AnnotationKind::Context + .span(64..65) + .label("this expression has type `{integer}`"), + ), + )]; let renderer = Renderer::styled().theme(OutputTheme::Unicode); anstream::println!("{}", renderer.render(message)); diff --git a/examples/multislice.rs b/examples/multislice.rs index b8b4ac74..9393aadb 100644 --- a/examples/multislice.rs +++ b/examples/multislice.rs @@ -1,19 +1,18 @@ use annotate_snippets::{Annotation, Group, Level, Renderer, Snippet}; fn main() { - let message = Level::ERROR.header("mismatched types").group( - Group::new() - .element( - Snippet::>::source("Foo") - .line_start(51) - .path("src/format.rs"), - ) - .element( - Snippet::>::source("Faa") - .line_start(129) - .path("src/display.rs"), - ), - ); + let message = &[Group::new() + .element(Level::ERROR.title("mismatched types")) + .element( + Snippet::>::source("Foo") + .line_start(51) + .path("src/format.rs"), + ) + .element( + Snippet::>::source("Faa") + .line_start(129) + .path("src/display.rs"), + )]; let renderer = Renderer::styled(); anstream::println!("{}", renderer.render(message)); diff --git a/src/level.rs b/src/level.rs index eaa95600..d3db1814 100644 --- a/src/level.rs +++ b/src/level.rs @@ -2,7 +2,7 @@ use crate::renderer::stylesheet::Stylesheet; use crate::snippet::{ERROR_TXT, HELP_TXT, INFO_TXT, NOTE_TXT, WARNING_TXT}; -use crate::{Element, Group, Message, Title}; +use crate::Title; use anstyle::Style; /// Default `error:` [`Level`] @@ -35,7 +35,7 @@ pub const HELP: Level<'_> = Level { level: LevelInner::Help, }; -/// [`Message`] or [`Title`] severity level +/// [`Title`] severity level #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct Level<'a> { pub(crate) name: Option>, @@ -72,13 +72,12 @@ impl<'a> Level<'a> { /// not allowed to be passed to this function. /// /// - pub fn header(self, header: &'a str) -> Message<'a> { - Message { + pub fn title(self, title: &'a str) -> Title<'a> { + Title { + level: self, id: None, - groups: vec![Group::new().element(Element::Title(Title { - level: self, - title: header, - }))], + title, + is_pre_styled: false, } } @@ -90,8 +89,13 @@ impl<'a> Level<'a> { /// used to normalize untrusted text before it is passed to this function. /// /// - pub fn title(self, title: &'a str) -> Title<'a> { - Title { level: self, title } + pub fn pre_styled_title(self, title: &'a str) -> Title<'a> { + Title { + level: self, + id: None, + title, + is_pre_styled: true, + } } pub(crate) fn as_str(&self) -> &'a str { diff --git a/src/lib.rs b/src/lib.rs index bf5a720e..74f116aa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,24 +12,6 @@ //! #![doc = include_str!("../examples/expected_type.svg")] //! -//! The crate uses a three stage process with two conversions between states: -//! -//! ```text -//! Message --> Renderer --> impl Display -//! ``` -//! -//! The input type - [Message] is a structure designed -//! to align with likely output from any parser whose code snippet is to be -//! annotated. -//! -//! The middle structure - [Renderer] is a structure designed -//! to convert a snippet into an internal structure that is designed to store -//! the snippet data in a way that is easy to format. -//! [Renderer] also handles the user-configurable formatting -//! options, such as color, or margins. -//! -//! Finally, `impl Display` into a final `String` output. -//! //! # features //! - `testing-colors` - Makes [Renderer::styled] colors OS independent, which //! allows for easier testing when testing colored output. It should be added as diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index a5459734..12139c38 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -1,6 +1,6 @@ // Most of this file is adapted from https://github.com/rust-lang/rust/blob/160905b6253f42967ed4aef4b98002944c7df24c/compiler/rustc_errors/src/emitter.rs -//! The renderer for [`Message`]s +//! The renderer for [`Group`]s //! //! # Example //! ``` @@ -18,21 +18,24 @@ //! bar(); //! } //! "#; -//! Level::ERROR -//! .header("unresolved import `baz::zed`") -//! .id("E0432") -//! .group( -//! Group::new().element( -//! Snippet::source(source) -//! .path("temp.rs") -//! .line_start(1) -//! .fold(true) -//! .annotation( -//! AnnotationKind::Primary -//! .span(10..13) -//! .label("could not find `zed` in `baz`"), -//! ) -//! ) +//! +//! +//! Group::new() +//! .element( +//! Level::ERROR +//! .title("unresolved import `baz::zed`") +//! .id("E0432") +//! ) +//! .element( +//! Snippet::source(source) +//! .path("temp.rs") +//! .line_start(1) +//! .fold(true) +//! .annotation( +//! AnnotationKind::Primary +//! .span(10..13) +//! .label("could not find `zed` in `baz`"), +//! ) //! ); //! ``` @@ -47,7 +50,7 @@ use crate::renderer::source_map::{ }; use crate::renderer::styled_buffer::StyledBuffer; use crate::snippet::Id; -use crate::{Annotation, AnnotationKind, Element, Group, Message, Origin, Patch, Snippet, Title}; +use crate::{Annotation, AnnotationKind, Element, Group, Origin, Patch, Snippet, Title}; pub use anstyle::*; use margin::Margin; use std::borrow::Cow; @@ -60,7 +63,7 @@ use stylesheet::Stylesheet; const ANONYMIZED_LINE_NUM: &str = "LL"; pub const DEFAULT_TERM_WIDTH: usize = 140; -/// A renderer for [`Message`]s +/// A renderer for [`Group`]s #[derive(Clone, Debug)] pub struct Renderer { anonymized_line_numbers: bool, @@ -206,272 +209,220 @@ impl Renderer { } impl Renderer { - pub fn render(&self, mut message: Message<'_>) -> String { + pub fn render(&self, groups: &[Group<'_>]) -> String { if self.short_message { - self.render_short_message(message).unwrap() + self.render_short_message(groups).unwrap() } else { let max_line_num_len = if self.anonymized_line_numbers { ANONYMIZED_LINE_NUM.len() } else { - let n = message.max_line_number(); - num_decimal_digits(n) + num_decimal_digits(max_line_number(groups)) }; - let title = message.groups.remove(0).elements.remove(0); - if let Some(first) = message.groups.first_mut() { - first.elements.insert(0, title); - } else { - message.groups.push(Group::new().element(title)); - } - self.render_message(message, max_line_num_len).unwrap() - } - } - - fn render_message( - &self, - message: Message<'_>, - max_line_num_len: usize, - ) -> Result { - let mut out_string = String::new(); - - let og_primary_path = message - .groups - .iter() - .find_map(|group| { - group.elements.iter().find_map(|s| match &s { - Element::Cause(cause) => { - if cause.markers.iter().any(|m| m.kind.is_primary()) { - Some(cause.path) - } else { - None + let mut out_string = String::new(); + let group_len = groups.len(); + let mut og_primary_path = None; + for (g, group) in groups.iter().enumerate() { + let mut buffer = StyledBuffer::new(); + let primary_path = group + .elements + .iter() + .find_map(|s| match &s { + Element::Cause(cause) => { + if cause.markers.iter().any(|m| m.kind.is_primary()) { + Some(cause.path) + } else { + None + } } - } - Element::Origin(origin) => { - if origin.primary { - Some(Some(origin.path)) - } else { - None + Element::Origin(origin) => { + if origin.primary { + Some(Some(origin.path)) + } else { + None + } } - } - _ => None, - }) - }) - .unwrap_or( - message - .groups + _ => None, + }) + .unwrap_or( + group + .elements + .iter() + .find_map(|s| match &s { + Element::Cause(cause) => Some(cause.path), + Element::Origin(origin) => Some(Some(origin.path)), + _ => None, + }) + .unwrap_or_default(), + ); + if og_primary_path.is_none() && primary_path.is_some() { + og_primary_path = primary_path; + } + let level = group + .elements .iter() - .find_map(|group| { - group.elements.iter().find_map(|s| match &s { - Element::Cause(cause) => Some(cause.path), - Element::Origin(origin) => Some(Some(origin.path)), - _ => None, - }) + .find_map(|s| match &s { + Element::Title(title) => Some(title.level.clone()), + _ => None, }) - .unwrap_or_default(), - ); - let group_len = message.groups.len(); - for (g, group) in message.groups.into_iter().enumerate() { - let mut buffer = StyledBuffer::new(); - let primary_path = group - .elements - .iter() - .find_map(|s| match &s { - Element::Cause(cause) => { - if cause.markers.iter().any(|m| m.kind.is_primary()) { - Some(cause.path) - } else { - None - } - } - Element::Origin(origin) => { - if origin.primary { - Some(Some(origin.path)) - } else { - None - } + .unwrap_or(Level::ERROR); + let mut source_map_annotated_lines = VecDeque::new(); + let mut max_depth = 0; + for e in &group.elements { + if let Element::Cause(cause) = e { + let source_map = SourceMap::new(cause.source, cause.line_start); + let (depth, annotated_lines) = + source_map.annotated_lines(cause.markers.clone(), cause.fold); + max_depth = max(max_depth, depth); + source_map_annotated_lines.push_back((source_map, annotated_lines)); } - _ => None, - }) - .unwrap_or( - group - .elements - .iter() - .find_map(|s| match &s { - Element::Cause(cause) => Some(cause.path), - Element::Origin(origin) => Some(Some(origin.path)), - _ => None, - }) - .unwrap_or_default(), - ); - let level = group - .elements - .iter() - .find_map(|s| match &s { - Element::Title(title) => Some(title.level.clone()), - _ => None, - }) - .unwrap_or(Level::ERROR); - let mut source_map_annotated_lines = VecDeque::new(); - let mut max_depth = 0; - for e in &group.elements { - if let Element::Cause(cause) = e { - let source_map = SourceMap::new(cause.source, cause.line_start); - let (depth, annotated_lines) = - source_map.annotated_lines(cause.markers.clone(), cause.fold); - max_depth = max(max_depth, depth); - source_map_annotated_lines.push_back((source_map, annotated_lines)); } - } - let mut message_iter = group.elements.iter().enumerate().peekable(); - let mut last_was_suggestion = false; - while let Some((i, section)) = message_iter.next() { - let peek = message_iter.peek().map(|(_, s)| s).copied(); - match §ion { - Element::Title(title) => { - let title_style = match (i == 0, g == 0) { - (true, true) => TitleStyle::MainHeader, - (true, false) => TitleStyle::Header, - (false, _) => TitleStyle::Secondary, - }; - let buffer_msg_line_offset = buffer.num_lines(); - self.render_title( - &mut buffer, - title, - max_line_num_len, - title_style, - message.id.as_ref().and_then(|id| { - if g == 0 && i == 0 { - Some(id) - } else { - None - } - }), - matches!(peek, Some(Element::Title(_))), - buffer_msg_line_offset, - ); - last_was_suggestion = false; - } - Element::Cause(cause) => { - if let Some((source_map, annotated_lines)) = - source_map_annotated_lines.pop_front() - { - self.render_snippet_annotations( + let mut message_iter = group.elements.iter().enumerate().peekable(); + let mut last_was_suggestion = false; + while let Some((i, section)) = message_iter.next() { + let peek = message_iter.peek().map(|(_, s)| s).copied(); + match §ion { + Element::Title(title) => { + let title_style = match (i == 0, g == 0) { + (true, true) => TitleStyle::MainHeader, + (true, false) => TitleStyle::Header, + (false, _) => TitleStyle::Secondary, + }; + let buffer_msg_line_offset = buffer.num_lines(); + self.render_title( &mut buffer, + title, max_line_num_len, - cause, - primary_path, - &source_map, - &annotated_lines, - max_depth, - peek.is_some() || (g == 0 && group_len > 1), + title_style, + matches!(peek, Some(Element::Title(_))), + buffer_msg_line_offset, ); + last_was_suggestion = false; + } + Element::Cause(cause) => { + if let Some((source_map, annotated_lines)) = + source_map_annotated_lines.pop_front() + { + self.render_snippet_annotations( + &mut buffer, + max_line_num_len, + cause, + primary_path, + &source_map, + &annotated_lines, + max_depth, + peek.is_some() || (g == 0 && group_len > 1), + ); - if g == 0 { - let current_line = buffer.num_lines(); - match peek { - Some(Element::Title(level)) - if level.level.name != Some(None) => - { - self.draw_col_separator_no_space( + if g == 0 { + let current_line = buffer.num_lines(); + match peek { + Some(Element::Title(level)) + if level.level.name != Some(None) => + { + self.draw_col_separator_no_space( + &mut buffer, + current_line, + max_line_num_len + 1, + ); + } + + None if group_len > 1 => self.draw_col_separator_end( &mut buffer, current_line, max_line_num_len + 1, - ); + ), + _ => {} } - - None if group_len > 1 => self.draw_col_separator_end( - &mut buffer, - current_line, - max_line_num_len + 1, - ), - _ => {} } } - } - last_was_suggestion = false; - } - Element::Suggestion(suggestion) => { - let source_map = SourceMap::new(suggestion.source, suggestion.line_start); - self.emit_suggestion_default( - &mut buffer, - suggestion, - max_line_num_len, - &source_map, - primary_path.or(og_primary_path), - last_was_suggestion, - ); - last_was_suggestion = true; - } + last_was_suggestion = false; + } + Element::Suggestion(suggestion) => { + let source_map = + SourceMap::new(suggestion.source, suggestion.line_start); + self.emit_suggestion_default( + &mut buffer, + suggestion, + max_line_num_len, + &source_map, + primary_path.or(og_primary_path), + last_was_suggestion, + ); + last_was_suggestion = true; + } - Element::Origin(origin) => { - let buffer_msg_line_offset = buffer.num_lines(); - self.render_origin( - &mut buffer, - max_line_num_len, - origin, - buffer_msg_line_offset, - ); - last_was_suggestion = false; - } - Element::Padding(_) => { - let current_line = buffer.num_lines(); - self.draw_col_separator_no_space( - &mut buffer, - current_line, - max_line_num_len + 1, - ); + Element::Origin(origin) => { + let buffer_msg_line_offset = buffer.num_lines(); + self.render_origin( + &mut buffer, + max_line_num_len, + origin, + buffer_msg_line_offset, + ); + last_was_suggestion = false; + } + Element::Padding(_) => { + let current_line = buffer.num_lines(); + self.draw_col_separator_no_space( + &mut buffer, + current_line, + max_line_num_len + 1, + ); + } } - } - if g == 0 - && (matches!(section, Element::Origin(_)) - || (matches!(section, Element::Title(_)) && i == 0) - || matches!(section, Element::Title(level) if level.level.name == Some(None))) - { - let current_line = buffer.num_lines(); - if peek.is_none() && group_len > 1 { - self.draw_col_separator_end( - &mut buffer, - current_line, - max_line_num_len + 1, - ); - } else if matches!(peek, Some(Element::Title(level)) if level.level.name != Some(None)) + if g == 0 + && (matches!(section, Element::Origin(_)) + || (matches!(section, Element::Title(_)) && i == 0) + || matches!(section, Element::Title(level) if level.level.name == Some(None))) { - self.draw_col_separator_no_space( - &mut buffer, - current_line, - max_line_num_len + 1, - ); + let current_line = buffer.num_lines(); + if peek.is_none() && group_len > 1 { + self.draw_col_separator_end( + &mut buffer, + current_line, + max_line_num_len + 1, + ); + } else if matches!(peek, Some(Element::Title(level)) if level.level.name != Some(None)) + { + self.draw_col_separator_no_space( + &mut buffer, + current_line, + max_line_num_len + 1, + ); + } } } - } - buffer.render(level, &self.stylesheet, &mut out_string)?; - if g != group_len - 1 { - use std::fmt::Write; + buffer + .render(&level, &self.stylesheet, &mut out_string) + .unwrap(); + if g != group_len - 1 { + use std::fmt::Write; - writeln!(out_string)?; + writeln!(out_string).unwrap(); + } } + out_string } - Ok(out_string) } - fn render_short_message(&self, mut message: Message<'_>) -> Result { + fn render_short_message(&self, groups: &[Group<'_>]) -> Result { let mut buffer = StyledBuffer::new(); + let mut labels = None; + let group = groups.first().expect("Expected at least one group"); - let Element::Title(title) = message.groups.remove(0).elements.remove(0) else { + let Some(Element::Title(title)) = group.elements.first() else { panic!( "Expected first element to be a Title, got: {:?}", - message.groups + group.elements.first() ); }; - let mut labels = None; - - if let Some(Element::Cause(cause)) = message.groups.first().and_then(|group| { - group - .elements - .iter() - .find(|e| matches!(e, Element::Cause(_))) - }) { + if let Some(Element::Cause(cause)) = group + .elements + .iter() + .find(|e| matches!(e, Element::Cause(_))) + { let labels_inner = cause .markers .iter() @@ -521,10 +472,9 @@ impl Renderer { self.render_title( &mut buffer, - &title, + title, 0, // No line numbers in short messages TitleStyle::MainHeader, - message.id.as_ref(), false, 0, ); @@ -534,7 +484,7 @@ impl Renderer { } let mut out_string = String::new(); - buffer.render(title.level, &self.stylesheet, &mut out_string)?; + buffer.render(&title.level, &self.stylesheet, &mut out_string)?; Ok(out_string) } @@ -546,34 +496,62 @@ impl Renderer { title: &Title<'_>, max_line_num_len: usize, title_style: TitleStyle, - id: Option<&Id<'_>>, is_cont: bool, buffer_msg_line_offset: usize, ) { - if title_style == TitleStyle::Secondary { - // This is a secondary message with no span info - for _ in 0..max_line_num_len { - buffer.prepend(buffer_msg_line_offset, " ", ElementStyle::NoStyle); - } - - self.draw_note_separator( - buffer, - buffer_msg_line_offset, - max_line_num_len + 1, - is_cont, - ); + let (label_style, title_element_style) = match title_style { + TitleStyle::MainHeader => ( + ElementStyle::Level(title.level.level), + if self.short_message { + ElementStyle::NoStyle + } else { + ElementStyle::MainHeaderMsg + }, + ), + TitleStyle::Header => ( + ElementStyle::Level(title.level.level), + ElementStyle::HeaderMsg, + ), + TitleStyle::Secondary => { + for _ in 0..max_line_num_len { + buffer.prepend(buffer_msg_line_offset, " ", ElementStyle::NoStyle); + } - let label_width = if title.level.name != Some(None) { - buffer.append( + self.draw_note_separator( + buffer, buffer_msg_line_offset, - title.level.as_str(), - ElementStyle::MainHeaderMsg, + max_line_num_len + 1, + is_cont, ); - buffer.append(buffer_msg_line_offset, ": ", ElementStyle::NoStyle); - title.level.as_str().len() + 2 - } else { - 0 - }; + (ElementStyle::MainHeaderMsg, ElementStyle::NoStyle) + } + }; + let mut label_width = 0; + + if title.level.name != Some(None) { + buffer.append(buffer_msg_line_offset, title.level.as_str(), label_style); + label_width += title.level.as_str().len(); + if let Some(Id { id: Some(id), url }) = title.id { + buffer.append(buffer_msg_line_offset, "[", label_style); + if let Some(url) = url.as_ref() { + buffer.append( + buffer_msg_line_offset, + &format!("\x1B]8;;{url}\x1B\\"), + label_style, + ); + } + buffer.append(buffer_msg_line_offset, id, label_style); + if url.is_some() { + buffer.append(buffer_msg_line_offset, "\x1B]8;;\x1B\\", label_style); + } + buffer.append(buffer_msg_line_offset, "]", label_style); + label_width += 2 + id.len(); + } + buffer.append(buffer_msg_line_offset, ": ", title_element_style); + label_width += 2; + } + + let padding = " ".repeat(if title_style == TitleStyle::Secondary { // The extra 3 ` ` is padding that's always needed to align to the // label i.e. `note: `: // @@ -591,153 +569,43 @@ impl Renderer { // | | width of label // | magic `3` // `max_line_num_len` - let padding = max_line_num_len + 3 + label_width; - - let printed_lines = self.msgs_to_buffer(buffer, title.title, padding, None); - if is_cont && matches!(self.theme, OutputTheme::Unicode) { - // There's another note after this one, associated to the subwindow above. - // We write additional vertical lines to join them: - // ╭▸ test.rs:3:3 - // │ - // 3 │ code - // │ ━━━━ - // │ - // ├ note: foo - // │ bar - // ╰ note: foo - // bar - for i in buffer_msg_line_offset + 1..=printed_lines { - self.draw_col_separator_no_space(buffer, i, max_line_num_len + 1); - } - } + max_line_num_len + 3 + label_width } else { - let mut label_width = 0; - - if title.level.name != Some(None) { - buffer.append( - buffer_msg_line_offset, - title.level.as_str(), - ElementStyle::Level(title.level.level), - ); - } - label_width += title.level.as_str().len(); - if let Some(Id { id: Some(id), url }) = id { - buffer.append( - buffer_msg_line_offset, - "[", - ElementStyle::Level(title.level.level), - ); - if let Some(url) = url.as_ref() { - buffer.append( - buffer_msg_line_offset, - &format!("\x1B]8;;{url}\x1B\\"), - ElementStyle::Level(title.level.level), - ); - } - buffer.append( - buffer_msg_line_offset, - id, - ElementStyle::Level(title.level.level), - ); - if url.is_some() { - buffer.append( - buffer_msg_line_offset, - "\x1B]8;;\x1B\\", - ElementStyle::Level(title.level.level), - ); - } - buffer.append( - buffer_msg_line_offset, - "]", - ElementStyle::Level(title.level.level), - ); - label_width += 2 + id.len(); - } - let header_style = match title_style { - TitleStyle::MainHeader => { - if self.short_message { - ElementStyle::NoStyle - } else { - ElementStyle::MainHeaderMsg - } - } - TitleStyle::Header => ElementStyle::HeaderMsg, - TitleStyle::Secondary => unreachable!(), - }; - if title.level.name != Some(None) { - buffer.append(buffer_msg_line_offset, ": ", header_style); - label_width += 2; - } - if !title.title.is_empty() { - for (line, text) in normalize_whitespace(title.title).lines().enumerate() { - buffer.append( - buffer_msg_line_offset + line, - &format!( - "{}{}", - if line == 0 { - String::new() - } else { - " ".repeat(label_width) - }, - text - ), - header_style, - ); - } - } - } - } - - /// Adds a left margin to every line but the first, given a padding length and the label being - /// displayed, keeping the provided highlighting. - fn msgs_to_buffer( - &self, - buffer: &mut StyledBuffer, - title: &str, - padding: usize, - override_style: Option, - ) -> usize { - let padding = " ".repeat(padding); - - let mut line_number = buffer.num_lines().saturating_sub(1); + label_width + }); - // Provided the following diagnostic message: - // - // let msgs = vec![ - // (" - // ("highlighted multiline\nstring to\nsee how it ", Style::NoStyle), - // ("looks", Style::Highlight), - // ("with\nvery ", Style::NoStyle), - // ("weird", Style::Highlight), - // (" formats\n", Style::NoStyle), - // ("see?", Style::Highlight), - // ]; - // - // the expected output on a note is (* surround the highlighted text) - // - // = note: highlighted multiline - // string to - // see how it *looks* with - // very *weird* formats - // see? - let style = if let Some(override_style) = override_style { - override_style + let (title_str, style) = if title.is_pre_styled { + (title.title.to_owned(), ElementStyle::NoStyle) } else { - ElementStyle::NoStyle + (normalize_whitespace(title.title), title_element_style) }; - let lines = title.split('\n').collect::>(); - if lines.len() > 1 { - for (i, line) in lines.iter().enumerate() { - if i != 0 { - line_number += 1; - buffer.append(line_number, &padding, ElementStyle::NoStyle); + for (i, text) in title_str.lines().enumerate() { + if i != 0 { + buffer.append(buffer_msg_line_offset + i, &padding, ElementStyle::NoStyle); + if title_style == TitleStyle::Secondary + && is_cont + && matches!(self.theme, OutputTheme::Unicode) + { + // There's another note after this one, associated to the subwindow above. + // We write additional vertical lines to join them: + // ╭▸ test.rs:3:3 + // │ + // 3 │ code + // │ ━━━━ + // │ + // ├ note: foo + // │ bar + // ╰ note: foo + // bar + self.draw_col_separator_no_space( + buffer, + buffer_msg_line_offset + i, + max_line_num_len + 1, + ); } - buffer.append(line_number, line, style); } - } else { - buffer.append(line_number, title, style); + buffer.append(buffer_msg_line_offset + i, text, style); } - line_number } fn render_origin( @@ -2961,6 +2829,57 @@ enum TitleStyle { Secondary, } +fn max_line_number(groups: &[Group<'_>]) -> usize { + groups + .iter() + .map(|v| { + v.elements + .iter() + .map(|s| match s { + Element::Title(_) | Element::Origin(_) | Element::Padding(_) => 0, + Element::Cause(cause) => { + let end = cause + .markers + .iter() + .map(|a| a.span.end) + .max() + .unwrap_or(cause.source.len()) + .min(cause.source.len()); + + cause.line_start + newline_count(&cause.source[..end]) + } + Element::Suggestion(suggestion) => { + let end = suggestion + .markers + .iter() + .map(|a| a.span.end) + .max() + .unwrap_or(suggestion.source.len()) + .min(suggestion.source.len()); + + suggestion.line_start + newline_count(&suggestion.source[..end]) + } + }) + .max() + .unwrap_or(1) + }) + .max() + .unwrap_or(1) +} + +fn newline_count(body: &str) -> usize { + #[cfg(feature = "simd")] + { + memchr::memchr_iter(b'\n', body.as_bytes()) + .count() + .saturating_sub(1) + } + #[cfg(not(feature = "simd"))] + { + body.lines().count().saturating_sub(1) + } +} + #[cfg(test)] mod test { use super::OUTPUT_REPLACEMENTS; diff --git a/src/renderer/styled_buffer.rs b/src/renderer/styled_buffer.rs index f72c58c6..de3d0815 100644 --- a/src/renderer/styled_buffer.rs +++ b/src/renderer/styled_buffer.rs @@ -41,14 +41,14 @@ impl StyledBuffer { pub(crate) fn render( &self, - level: Level<'_>, + level: &Level<'_>, stylesheet: &Stylesheet, str: &mut String, ) -> Result<(), fmt::Error> { for (i, line) in self.lines.iter().enumerate() { let mut current_style = stylesheet.none; for StyledChar { ch, style } in line { - let ch_style = style.color_spec(&level, stylesheet); + let ch_style = style.color_spec(level, stylesheet); if ch_style != current_style { if !line.is_empty() { write!(str, "{}", current_style.render_reset())?; diff --git a/src/snippet.rs b/src/snippet.rs index 2d686a5e..6e9a78c7 100644 --- a/src/snippet.rs +++ b/src/snippet.rs @@ -10,81 +10,6 @@ pub(crate) const INFO_TXT: &str = "info"; pub(crate) const NOTE_TXT: &str = "note"; pub(crate) const WARNING_TXT: &str = "warning"; -/// Top-level user message -#[derive(Clone, Debug)] -pub struct Message<'a> { - pub(crate) id: Option>, // for "correctness", could be sloppy and be on Title - pub(crate) groups: Vec>, -} - -impl<'a> Message<'a> { - ///
- /// - /// Text passed to this function is considered "untrusted input", as such - /// all text is passed through a normalization function. Pre-styled text is - /// not allowed to be passed to this function. - /// - ///
- pub fn id(mut self, id: &'a str) -> Self { - self.id.get_or_insert(Id::default()).id = Some(id); - self - } - - ///
- /// - /// This is only relevant if the `id` present - /// - ///
- pub fn id_url(mut self, url: &'a str) -> Self { - self.id.get_or_insert(Id::default()).url = Some(url); - self - } - - /// Add an [`Element`] container - pub fn group(mut self, group: Group<'a>) -> Self { - self.groups.push(group); - self - } - - pub(crate) fn max_line_number(&self) -> usize { - self.groups - .iter() - .map(|v| { - v.elements - .iter() - .map(|s| match s { - Element::Title(_) | Element::Origin(_) | Element::Padding(_) => 0, - Element::Cause(cause) => { - let end = cause - .markers - .iter() - .map(|a| a.span.end) - .max() - .unwrap_or(cause.source.len()) - .min(cause.source.len()); - - cause.line_start + newline_count(&cause.source[..end]) - } - Element::Suggestion(suggestion) => { - let end = suggestion - .markers - .iter() - .map(|a| a.span.end) - .max() - .unwrap_or(suggestion.source.len()) - .min(suggestion.source.len()); - - suggestion.line_start + newline_count(&suggestion.source[..end]) - } - }) - .max() - .unwrap_or(1) - }) - .max() - .unwrap_or(1) - } -} - #[derive(Clone, Debug, Default)] pub(crate) struct Id<'a> { pub(crate) id: Option<&'a str>, @@ -174,7 +99,39 @@ pub struct Padding; #[derive(Clone, Debug)] pub struct Title<'a> { pub(crate) level: Level<'a>, + pub(crate) id: Option>, pub(crate) title: &'a str, + pub(crate) is_pre_styled: bool, +} + +impl<'a> Title<'a> { + ///
+ /// + /// This is only relevant if the title is the first element of a group. + /// + ///
+ ///
+ /// + /// Text passed to this function is considered "untrusted input", as such + /// all text is passed through a normalization function. Pre-styled text is + /// not allowed to be passed to this function. + /// + ///
+ pub fn id(mut self, id: &'a str) -> Self { + self.id.get_or_insert(Id::default()).id = Some(id); + self + } + + ///
+ /// + /// This is only relevant if the title is the first element of a group and + /// `id` present + /// + ///
+ pub fn id_url(mut self, url: &'a str) -> Self { + self.id.get_or_insert(Id::default()).url = Some(url); + self + } } /// A source view [`Element`] in a [`Group`] @@ -303,7 +260,8 @@ impl<'a> Annotation<'a> { /// The category of the [`Annotation`] #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum AnnotationKind { - /// Color to [`Message`]'s [`Level`] + /// Color to the [`Level`] the first [`Title`] in [`Group`]. If no [`Title`] + /// is present, it will default to `error`. Primary, /// "secondary"; fixed color Context, @@ -449,19 +407,6 @@ impl<'a> Origin<'a> { } } -fn newline_count(body: &str) -> usize { - #[cfg(feature = "simd")] - { - memchr::memchr_iter(b'\n', body.as_bytes()) - .count() - .saturating_sub(1) - } - #[cfg(not(feature = "simd"))] - { - body.lines().count().saturating_sub(1) - } -} - /// Given an original string like `AACC`, and a suggestion like `AABBCC`, try to detect /// the case where a substring of the suggestion is "sandwiched" in the original, like /// `BB` is. Return the length of the prefix, the "trimmed" suggestion, and the length diff --git a/tests/color/ann_eof.rs b/tests/color/ann_eof.rs index ea0c95b8..e550ba55 100644 --- a/tests/color/ann_eof.rs +++ b/tests/color/ann_eof.rs @@ -4,14 +4,14 @@ use snapbox::{assert_data_eq, file}; #[test] fn case() { - let input = Level::ERROR.header("expected `.`, `=`").group( - Group::new().element( + let input = &[Group::new() + .element(Level::ERROR.title("expected `.`, `=`")) + .element( Snippet::source("asdf") .path("Cargo.toml") .line_start(1) .annotation(AnnotationKind::Primary.span(4..4).label("")), - ), - ); + )]; let expected = file!["ann_eof.term.svg"]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected); diff --git a/tests/color/ann_insertion.rs b/tests/color/ann_insertion.rs index a0c538b8..73dd7d80 100644 --- a/tests/color/ann_insertion.rs +++ b/tests/color/ann_insertion.rs @@ -4,14 +4,14 @@ use snapbox::{assert_data_eq, file}; #[test] fn case() { - let input = Level::ERROR.header("expected `.`, `=`").group( - Group::new().element( + let input = &[Group::new() + .element(Level::ERROR.title("expected `.`, `=`")) + .element( Snippet::source("asf") .path("Cargo.toml") .line_start(1) .annotation(AnnotationKind::Primary.span(2..2).label("'d' belongs here")), - ), - ); + )]; let expected = file!["ann_insertion.term.svg"]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected); diff --git a/tests/color/ann_multiline.rs b/tests/color/ann_multiline.rs index 127c462e..29d4c309 100644 --- a/tests/color/ann_multiline.rs +++ b/tests/color/ann_multiline.rs @@ -9,22 +9,23 @@ fn case() { } = body[body_idx] "#; - let input = Level::ERROR - .header("pattern does not mention fields `lineno`, `content`") - .id("E0027") - .group( - Group::new().element( - Snippet::source(source) - .path("src/display_list.rs") - .line_start(139) - .fold(false) - .annotation( - AnnotationKind::Primary - .span(31..128) - .label("missing fields `lineno`, `content`"), - ), - ), - ); + let input = &[Group::new() + .element( + Level::ERROR + .title("pattern does not mention fields `lineno`, `content`") + .id("E0027"), + ) + .element( + Snippet::source(source) + .path("src/display_list.rs") + .line_start(139) + .fold(false) + .annotation( + AnnotationKind::Primary + .span(31..128) + .label("missing fields `lineno`, `content`"), + ), + )]; let expected = file!["ann_multiline.term.svg"]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected); diff --git a/tests/color/ann_multiline2.rs b/tests/color/ann_multiline2.rs index b8e36197..cf21e5ea 100644 --- a/tests/color/ann_multiline2.rs +++ b/tests/color/ann_multiline2.rs @@ -9,22 +9,19 @@ of an edge case of an annotation overflowing to exactly one character on next line. "#; - let input = Level::ERROR - .header("spacing error found") - .id("E####") - .group( - Group::new().element( - Snippet::source(source) - .path("foo.txt") - .line_start(26) - .fold(false) - .annotation( - AnnotationKind::Primary - .span(11..19) - .label("this should not be on separate lines"), - ), - ), - ); + let input = &[Group::new() + .element(Level::ERROR.title("spacing error found").id("E####")) + .element( + Snippet::source(source) + .path("foo.txt") + .line_start(26) + .fold(false) + .annotation( + AnnotationKind::Primary + .span(11..19) + .label("this should not be on separate lines"), + ), + )]; let expected = file!["ann_multiline2.term.svg"]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected); diff --git a/tests/color/ann_removed_nl.rs b/tests/color/ann_removed_nl.rs index b4398c47..68ec8326 100644 --- a/tests/color/ann_removed_nl.rs +++ b/tests/color/ann_removed_nl.rs @@ -4,14 +4,14 @@ use snapbox::{assert_data_eq, file}; #[test] fn case() { - let input = Level::ERROR.header("expected `.`, `=`").group( - Group::new().element( + let input = &[Group::new() + .element(Level::ERROR.title("expected `.`, `=`")) + .element( Snippet::source("asdf") .path("Cargo.toml") .line_start(1) .annotation(AnnotationKind::Primary.span(4..5).label("")), - ), - ); + )]; let expected = file!["ann_removed_nl.term.svg"]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected); diff --git a/tests/color/ensure_emoji_highlight_width.rs b/tests/color/ensure_emoji_highlight_width.rs index 59dcdaa2..bc22f9ab 100644 --- a/tests/color/ensure_emoji_highlight_width.rs +++ b/tests/color/ensure_emoji_highlight_width.rs @@ -7,17 +7,14 @@ fn case() { let source = r#""haha this isn't a valid name 🐛" = { package = "libc", version = "0.1" } "#; - let input = Level::ERROR.header("invalid character ` ` in package name: `haha this isn't a valid name 🐛`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters)") - .group( - Group::new() - .element( - Snippet::source(source) - .path("") - .line_start(7) - .annotation(AnnotationKind::Primary.span(0..35).label("")) - ) - ) -; + let input = &[Group::new() + .element(Level::ERROR.title("invalid character ` ` in package name: `haha this isn't a valid name 🐛`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters)")) + .element( + Snippet::source(source) + .path("") + .line_start(7) + .annotation(AnnotationKind::Primary.span(0..35).label("")) + )]; let expected = file!["ensure_emoji_highlight_width.term.svg"]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected); diff --git a/tests/color/fold_ann_multiline.rs b/tests/color/fold_ann_multiline.rs index b0ccdd55..1c035f41 100644 --- a/tests/color/fold_ann_multiline.rs +++ b/tests/color/fold_ann_multiline.rs @@ -28,8 +28,9 @@ fn case() { } "#; - let input = Level::ERROR.header("mismatched types").id("E0308").group( - Group::new().element( + let input = &[Group::new() + .element(Level::ERROR.title("mismatched types").id("E0308")) + .element( Snippet::source(source) .path("src/format.rs") .line_start(51) @@ -42,8 +43,7 @@ fn case() { .span(22..766) .label("expected enum `std::option::Option`, found ()"), ), - ), - ); + )]; let expected = file!["fold_ann_multiline.term.svg"]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected); diff --git a/tests/color/fold_bad_origin_line.rs b/tests/color/fold_bad_origin_line.rs index 852f9b54..9e4c5c0c 100644 --- a/tests/color/fold_bad_origin_line.rs +++ b/tests/color/fold_bad_origin_line.rs @@ -9,15 +9,13 @@ fn case() { invalid syntax "#; - let input = Level::ERROR.header("").group( - Group::new().element( - Snippet::source(source) - .path("path/to/error.rs") - .line_start(1) - .fold(true) - .annotation(AnnotationKind::Context.span(2..16).label("error here")), - ), - ); + let input = &[Group::new().element(Level::ERROR.title("")).element( + Snippet::source(source) + .path("path/to/error.rs") + .line_start(1) + .fold(true) + .annotation(AnnotationKind::Context.span(2..16).label("error here")), + )]; let expected = file!["fold_bad_origin_line.term.svg"]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected); diff --git a/tests/color/fold_leading.rs b/tests/color/fold_leading.rs index 965741d5..0e4ae61d 100644 --- a/tests/color/fold_leading.rs +++ b/tests/color/fold_leading.rs @@ -17,18 +17,19 @@ edition = "2021" workspace = 20 "#; - let input = Level::ERROR - .header("invalid type: integer `20`, expected a bool") - .id("E0308") - .group( - Group::new().element( - Snippet::source(source) - .path("Cargo.toml") - .line_start(1) - .fold(true) - .annotation(AnnotationKind::Primary.span(132..134).label("")), - ), - ); + let input = &[Group::new() + .element( + Level::ERROR + .title("invalid type: integer `20`, expected a bool") + .id("E0308"), + ) + .element( + Snippet::source(source) + .path("Cargo.toml") + .line_start(1) + .fold(true) + .annotation(AnnotationKind::Primary.span(132..134).label("")), + )]; let expected = file!["fold_leading.term.svg"]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected); diff --git a/tests/color/fold_trailing.rs b/tests/color/fold_trailing.rs index bbcf5d80..6421dd45 100644 --- a/tests/color/fold_trailing.rs +++ b/tests/color/fold_trailing.rs @@ -16,18 +16,19 @@ rust-version = "1.70" edition = "2021" "#; - let input = Level::ERROR - .header("invalid type: integer `20`, expected a lints table") - .id("E0308") - .group( - Group::new().element( - Snippet::source(source) - .path("Cargo.toml") - .line_start(1) - .fold(true) - .annotation(AnnotationKind::Primary.span(8..10).label("")), - ), - ); + let input = &[Group::new() + .element( + Level::ERROR + .title("invalid type: integer `20`, expected a lints table") + .id("E0308"), + ) + .element( + Snippet::source(source) + .path("Cargo.toml") + .line_start(1) + .fold(true) + .annotation(AnnotationKind::Primary.span(8..10).label("")), + )]; let expected = file!["fold_trailing.term.svg"]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected); diff --git a/tests/color/issue_9.rs b/tests/color/issue_9.rs index 36d13f44..f42c30b9 100644 --- a/tests/color/issue_9.rs +++ b/tests/color/issue_9.rs @@ -4,27 +4,24 @@ use snapbox::{assert_data_eq, file}; #[test] fn case() { - let input = Level::ERROR.header("expected one of `.`, `;`, `?`, or an operator, found `for`") - .group( - Group::new() - .element( - Snippet::source("let x = vec![1];") - .path("/code/rust/src/test/ui/annotate-snippet/suggestion.rs") - .line_start(4) - .annotation(AnnotationKind::Context.span(4..5).label("move occurs because `x` has type `std::vec::Vec`, which does not implement the `Copy` trait")) - ) - .element( - Snippet::source("let y = x;") - .line_start(7) - .annotation(AnnotationKind::Context.span(8..9).label("value moved here")) - ) - .element( - Snippet::source("x;") - .line_start(9) - .annotation(AnnotationKind::Primary.span(0..1).label("value used here after move")) - ) - ) -; + let input = &[Group::new().element(Level::ERROR.title("expected one of `.`, `;`, `?`, or an operator, found `for`")) + .element( + Snippet::source("let x = vec![1];") + .path("/code/rust/src/test/ui/annotate-snippet/suggestion.rs") + .line_start(4) + .annotation(AnnotationKind::Context.span(4..5).label("move occurs because `x` has type `std::vec::Vec`, which does not implement the `Copy` trait")) + ) + .element( + Snippet::source("let y = x;") + .line_start(7) + .annotation(AnnotationKind::Context.span(8..9).label("value moved here")) + ) + .element( + Snippet::source("x;") + .line_start(9) + .annotation(AnnotationKind::Primary.span(0..1).label("value used here after move")) + ) + ]; let expected = file!["issue_9.term.svg"]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected); diff --git a/tests/color/multiline_removal_suggestion.rs b/tests/color/multiline_removal_suggestion.rs index ced5e09d..fbaf4fff 100644 --- a/tests/color/multiline_removal_suggestion.rs +++ b/tests/color/multiline_removal_suggestion.rs @@ -64,49 +64,44 @@ fn bay() -> Vec<(bool, HashSet)> { fn main() {} "#; - let input = Level::ERROR - .header("`(bool, HashSet)` is not an iterator") - .id("E0277") - .group( - Group::new() - .element( - Snippet::source(source) - .path("$DIR/multiline-removal-suggestion.rs") - .fold(true) - .annotation( - AnnotationKind::Primary - .span(769..776) - .label("`(bool, HashSet)` is not an iterator"), - ), - ) - .element( - Level::HELP - .title("the trait `Iterator` is not implemented for `(bool, HashSet)`"), - ) - .element( - Level::NOTE - .title("required for `(bool, HashSet)` to implement `IntoIterator`"), - ), - ) - .group( - Group::new() - .element(Level::NOTE.title("required by a bound in `flatten`")) - .element( - Origin::new("/rustc/FAKE_PREFIX/library/core/src/iter/traits/iterator.rs") - .line(1556) - .char_column(4), - ), - ) - .group( - Group::new() - .element(Level::HELP.title("consider removing this method call, as the receiver has type `std::vec::IntoIter>` and `std::vec::IntoIter>: Iterator` trivially holds")) - .element( - Snippet::source(source) - .path("$DIR/multiline-removal-suggestion.rs") - .fold(true) - .patch(Patch::new(708..768, "")), - ), - ); + let input = &[ + Group::new() + .element( + Level::ERROR + .title("`(bool, HashSet)` is not an iterator") + .id("E0277"), + ) + .element( + Snippet::source(source) + .path("$DIR/multiline-removal-suggestion.rs") + .fold(true) + .annotation( + AnnotationKind::Primary + .span(769..776) + .label("`(bool, HashSet)` is not an iterator"), + ), + ) + .element( + Level::HELP + .title("the trait `Iterator` is not implemented for `(bool, HashSet)`"), + ) + .element( + Level::NOTE.title("required for `(bool, HashSet)` to implement `IntoIterator`"), + ), + Group::new() + .element(Level::NOTE.title("required by a bound in `flatten`")) + .element( + Origin::new("/rustc/FAKE_PREFIX/library/core/src/iter/traits/iterator.rs") + .line(1556) + .char_column(4), + ), + Group::new().element(Level::HELP.title("consider removing this method call, as the receiver has type `std::vec::IntoIter>` and `std::vec::IntoIter>: Iterator` trivially holds")).element( + Snippet::source(source) + .path("$DIR/multiline-removal-suggestion.rs") + .fold(true) + .patch(Patch::new(708..768, "")), + ), + ]; let expected = file!["multiline_removal_suggestion.term.svg"]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected); diff --git a/tests/color/multiple_annotations.rs b/tests/color/multiple_annotations.rs index b568b919..464d7672 100644 --- a/tests/color/multiple_annotations.rs +++ b/tests/color/multiple_annotations.rs @@ -15,27 +15,25 @@ fn case() { } "#; - let input = Level::ERROR.header("").group( - Group::new().element( - Snippet::source(source) - .line_start(96) - .annotation( - AnnotationKind::Primary - .span(100..110) - .label("Variable defined here"), - ) - .annotation( - AnnotationKind::Primary - .span(184..194) - .label("Referenced here"), - ) - .annotation( - AnnotationKind::Primary - .span(243..253) - .label("Referenced again here"), - ), - ), - ); + let input = &[Group::new().element(Level::ERROR.title("")).element( + Snippet::source(source) + .line_start(96) + .annotation( + AnnotationKind::Primary + .span(100..110) + .label("Variable defined here"), + ) + .annotation( + AnnotationKind::Primary + .span(184..194) + .label("Referenced here"), + ) + .annotation( + AnnotationKind::Primary + .span(243..253) + .label("Referenced again here"), + ), + )]; let expected = file!["multiple_annotations.term.svg"]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected); diff --git a/tests/color/simple.rs b/tests/color/simple.rs index 83834295..17287d94 100644 --- a/tests/color/simple.rs +++ b/tests/color/simple.rs @@ -9,25 +9,23 @@ fn case() { for line in &self.body { "#; - let input = Level::ERROR - .header("expected one of `.`, `;`, `?`, or an operator, found `for`") - .group( - Group::new().element( - Snippet::source(source) - .path("src/format_color.rs") - .line_start(169) - .annotation( - AnnotationKind::Primary - .span(20..23) - .label("unexpected token"), - ) - .annotation( - AnnotationKind::Context - .span(10..11) - .label("expected one of `.`, `;`, `?`, or an operator here"), - ), - ), - ); + let input = &[Group::new() + .element(Level::ERROR.title("expected one of `.`, `;`, `?`, or an operator, found `for`")) + .element( + Snippet::source(source) + .path("src/format_color.rs") + .line_start(169) + .annotation( + AnnotationKind::Primary + .span(20..23) + .label("unexpected token"), + ) + .annotation( + AnnotationKind::Context + .span(10..11) + .label("expected one of `.`, `;`, `?`, or an operator here"), + ), + )]; let expected = file!["simple.term.svg"]; let renderer = Renderer::styled(); assert_data_eq!(renderer.render(input), expected); diff --git a/tests/color/strip_line.rs b/tests/color/strip_line.rs index 4b21f9a1..fbb72506 100644 --- a/tests/color/strip_line.rs +++ b/tests/color/strip_line.rs @@ -6,8 +6,9 @@ use snapbox::{assert_data_eq, file}; fn case() { let source = r#" let _: () = 42;"#; - let input = Level::ERROR.header("mismatched types").id("E0308").group( - Group::new().element( + let input = &[Group::new() + .element(Level::ERROR.title("mismatched types").id("E0308")) + .element( Snippet::source(source) .path("$DIR/whitespace-trimming.rs") .line_start(4) @@ -16,8 +17,7 @@ fn case() { .span(192..194) .label("expected (), found integer"), ), - ), - ); + )]; let expected = file!["strip_line.term.svg"]; let renderer = Renderer::styled().anonymized_line_numbers(true); assert_data_eq!(renderer.render(input), expected); diff --git a/tests/color/strip_line_char.rs b/tests/color/strip_line_char.rs index f30d5e90..090e1dba 100644 --- a/tests/color/strip_line_char.rs +++ b/tests/color/strip_line_char.rs @@ -6,8 +6,9 @@ use snapbox::{assert_data_eq, file}; fn case() { let source = r#" let _: () = 42ñ"#; - let input = Level::ERROR.header("mismatched types").id("E0308").group( - Group::new().element( + let input = &[Group::new() + .element(Level::ERROR.title("mismatched types").id("E0308")) + .element( Snippet::source(source) .path("$DIR/whitespace-trimming.rs") .line_start(4) @@ -16,8 +17,7 @@ fn case() { .span(192..194) .label("expected (), found integer"), ), - ), - ); + )]; let expected = file!["strip_line_char.term.svg"]; let renderer = Renderer::styled().anonymized_line_numbers(true); assert_data_eq!(renderer.render(input), expected); diff --git a/tests/color/strip_line_non_ws.rs b/tests/color/strip_line_non_ws.rs index a67d70d1..da65e6a3 100644 --- a/tests/color/strip_line_non_ws.rs +++ b/tests/color/strip_line_non_ws.rs @@ -7,8 +7,9 @@ fn case() { let source = r#" let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = 42; let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); "#; - let input = Level::ERROR.header("mismatched types").id("E0308").group( - Group::new().element( + let input = &[Group::new() + .element(Level::ERROR.title("mismatched types").id("E0308")) + .element( Snippet::source(source) .path("$DIR/non-whitespace-trimming.rs") .line_start(4) @@ -22,8 +23,7 @@ fn case() { .span(232..234) .label("expected due to this"), ), - ), - ); + )]; let expected = file!["strip_line_non_ws.term.svg"]; let renderer = Renderer::styled().anonymized_line_numbers(true); assert_data_eq!(renderer.render(input), expected); diff --git a/tests/formatter.rs b/tests/formatter.rs index fb671dfd..34c40bf8 100644 --- a/tests/formatter.rs +++ b/tests/formatter.rs @@ -5,14 +5,12 @@ use snapbox::{assert_data_eq, str}; #[test] fn test_i_29() { - let snippets = Level::ERROR.header("oops").group( - Group::new().element( - Snippet::source("First line\r\nSecond oops line") - .path("") - .annotation(AnnotationKind::Primary.span(19..23).label("oops")) - .fold(true), - ), - ); + let snippets = &[Group::new().element(Level::ERROR.title("oops")).element( + Snippet::source("First line\r\nSecond oops line") + .path("") + .annotation(AnnotationKind::Primary.span(19..23).label("oops")) + .fold(true), + )]; let expected = str![[r#" error: oops --> :2:8 @@ -27,13 +25,11 @@ error: oops #[test] fn test_point_to_double_width_characters() { - let snippets = Level::ERROR.header("").group( - Group::new().element( - Snippet::source("こんにちは、世界") - .path("") - .annotation(AnnotationKind::Primary.span(18..24).label("world")), - ), - ); + let snippets = &[Group::new().element(Level::ERROR.title("")).element( + Snippet::source("こんにちは、世界") + .path("") + .annotation(AnnotationKind::Primary.span(18..24).label("world")), + )]; let expected = str![[r#" error: @@ -49,13 +45,11 @@ error: #[test] fn test_point_to_double_width_characters_across_lines() { - let snippets = Level::ERROR.header("").group( - Group::new().element( - Snippet::source("おはよう\nございます") - .path("") - .annotation(AnnotationKind::Primary.span(6..22).label("Good morning")), - ), - ); + let snippets = &[Group::new().element(Level::ERROR.title("")).element( + Snippet::source("おはよう\nございます") + .path("") + .annotation(AnnotationKind::Primary.span(6..22).label("Good morning")), + )]; let expected = str![[r#" error: @@ -73,14 +67,12 @@ error: #[test] fn test_point_to_double_width_characters_multiple() { - let snippets = Level::ERROR.header("").group( - Group::new().element( - Snippet::source("お寿司\n食べたい🍣") - .path("") - .annotation(AnnotationKind::Primary.span(0..9).label("Sushi1")) - .annotation(AnnotationKind::Context.span(16..22).label("Sushi2")), - ), - ); + let snippets = &[Group::new().element(Level::ERROR.title("")).element( + Snippet::source("お寿司\n食べたい🍣") + .path("") + .annotation(AnnotationKind::Primary.span(0..9).label("Sushi1")) + .annotation(AnnotationKind::Context.span(16..22).label("Sushi2")), + )]; let expected = str![[r#" error: @@ -98,13 +90,11 @@ error: #[test] fn test_point_to_double_width_characters_mixed() { - let snippets = Level::ERROR.header("").group( - Group::new().element( - Snippet::source("こんにちは、新しいWorld!") - .path("") - .annotation(AnnotationKind::Primary.span(18..32).label("New world")), - ), - ); + let snippets = &[Group::new().element(Level::ERROR.title("")).element( + Snippet::source("こんにちは、新しいWorld!") + .path("") + .annotation(AnnotationKind::Primary.span(18..32).label("New world")), + )]; let expected = str![[r#" error: @@ -120,7 +110,7 @@ error: #[test] fn test_format_title() { - let input = Level::ERROR.header("This is a title").id("E0001"); + let input = &[Group::new().element(Level::ERROR.title("This is a title").id("E0001"))]; let expected = str![r#"error[E0001]: This is a title"#]; let renderer = Renderer::plain(); @@ -130,9 +120,9 @@ fn test_format_title() { #[test] fn test_format_snippet_only() { let source = "This is line 1\nThis is line 2"; - let input = Level::ERROR - .header("") - .group(Group::new().element(Snippet::>::source(source).line_start(5402))); + let input = &[Group::new() + .element(Level::ERROR.title("")) + .element(Snippet::>::source(source).line_start(5402))]; let expected = str![[r#" error: @@ -148,19 +138,18 @@ error: fn test_format_snippets_continuation() { let src_0 = "This is slice 1"; let src_1 = "This is slice 2"; - let input = Level::ERROR.header("").group( - Group::new() - .element( - Snippet::>::source(src_0) - .line_start(5402) - .path("file1.rs"), - ) - .element( - Snippet::>::source(src_1) - .line_start(2) - .path("file2.rs"), - ), - ); + let input = &[Group::new() + .element(Level::ERROR.title("")) + .element( + Snippet::>::source(src_0) + .line_start(5402) + .path("file1.rs"), + ) + .element( + Snippet::>::source(src_1) + .line_start(2) + .path("file2.rs"), + )]; let expected = str![[r#" error: --> file1.rs @@ -182,15 +171,13 @@ fn test_format_snippet_annotation_standalone() { let source = [line_1, line_2].join("\n"); // In line 2 let range = 22..24; - let input = Level::ERROR.header("").group( - Group::new().element( - Snippet::source(&source).line_start(5402).annotation( - AnnotationKind::Context - .span(range.clone()) - .label("Test annotation"), - ), + let input = &[Group::new().element(Level::ERROR.title("")).element( + Snippet::source(&source).line_start(5402).annotation( + AnnotationKind::Context + .span(range.clone()) + .label("Test annotation"), ), - ); + )]; let expected = str![[r#" error: | @@ -204,9 +191,9 @@ error: #[test] fn test_format_footer_title() { - let input = Level::ERROR - .header("") - .group(Group::new().element(Level::ERROR.title("This __is__ a title"))); + let input = &[Group::new() + .element(Level::ERROR.title("")) + .element(Level::ERROR.title("This __is__ a title"))]; let expected = str![[r#" error: | @@ -221,15 +208,13 @@ error: fn test_i26() { let source = "short"; let label = "label"; - let input = Level::ERROR.header("").group( - Group::new().element( - Snippet::source(source).line_start(0).annotation( - AnnotationKind::Primary - .span(0..source.len() + 2) - .label(label), - ), + let input = &[Group::new().element(Level::ERROR.title("")).element( + Snippet::source(source).line_start(0).annotation( + AnnotationKind::Primary + .span(0..source.len() + 2) + .label(label), ), - ); + )]; let renderer = Renderer::plain(); let _ = renderer.render(input); } @@ -237,9 +222,9 @@ fn test_i26() { #[test] fn test_source_content() { let source = "This is an example\nof content lines"; - let input = Level::ERROR - .header("") - .group(Group::new().element(Snippet::>::source(source).line_start(56))); + let input = &[Group::new() + .element(Level::ERROR.title("")) + .element(Snippet::>::source(source).line_start(56))]; let expected = str![[r#" error: | @@ -253,13 +238,11 @@ error: #[test] fn test_source_annotation_standalone_singleline() { let source = "tests"; - let input = Level::ERROR.header("").group( - Group::new().element( - Snippet::source(source) - .line_start(1) - .annotation(AnnotationKind::Context.span(0..5).label("Example string")), - ), - ); + let input = &[Group::new().element(Level::ERROR.title("")).element( + Snippet::source(source) + .line_start(1) + .annotation(AnnotationKind::Context.span(0..5).label("Example string")), + )]; let expected = str![[r#" error: | @@ -273,14 +256,12 @@ error: #[test] fn test_source_annotation_standalone_multiline() { let source = "tests"; - let input = Level::ERROR.header("").group( - Group::new().element( - Snippet::source(source) - .line_start(1) - .annotation(AnnotationKind::Context.span(0..5).label("Example string")) - .annotation(AnnotationKind::Context.span(0..5).label("Second line")), - ), - ); + let input = &[Group::new().element(Level::ERROR.title("")).element( + Snippet::source(source) + .line_start(1) + .annotation(AnnotationKind::Context.span(0..5).label("Example string")) + .annotation(AnnotationKind::Context.span(0..5).label("Second line")), + )]; let expected = str![[r#" error: | @@ -296,9 +277,9 @@ error: #[test] fn test_only_source() { - let input = Level::ERROR - .header("") - .group(Group::new().element(Snippet::>::source("").path("file.rs"))); + let input = &[Group::new() + .element(Level::ERROR.title("")) + .element(Snippet::>::source("").path("file.rs"))]; let expected = str![[r#" error: --> file.rs @@ -312,9 +293,9 @@ error: #[test] fn test_anon_lines() { let source = "This is an example\nof content lines\n\nabc"; - let input = Level::ERROR - .header("") - .group(Group::new().element(Snippet::>::source(source).line_start(56))); + let input = &[Group::new() + .element(Level::ERROR.title("")) + .element(Snippet::>::source(source).line_start(56))]; let expected = str![[r#" error: | @@ -329,15 +310,14 @@ LL | abc #[test] fn issue_130() { - let input = Level::ERROR.header("dummy").group( - Group::new().element( - Snippet::source("foo\nbar\nbaz") - .path("file/path") - .line_start(3) - .fold(true) - .annotation(AnnotationKind::Primary.span(4..11)), - ), // bar\nbaz - ); + let input = &[Group::new().element(Level::ERROR.title("dummy")).element( + Snippet::source("foo\nbar\nbaz") + .path("file/path") + .line_start(3) + .fold(true) + .annotation(AnnotationKind::Primary.span(4..11)), + // bar\nbaz + )]; let expected = str![[r#" error: dummy @@ -357,15 +337,14 @@ fn unterminated_string_multiline() { a\" // ... "; - let input = Level::ERROR.header("").group( - Group::new().element( - Snippet::source(source) - .path("file/path") - .line_start(3) - .fold(true) - .annotation(AnnotationKind::Primary.span(0..10)), - ), // 1..10 works - ); + let input = &[Group::new().element(Level::ERROR.title("")).element( + Snippet::source(source) + .path("file/path") + .line_start(3) + .fold(true) + .annotation(AnnotationKind::Primary.span(0..10)), + // 1..10 works + )]; let expected = str![[r#" error: --> file/path:3:1 @@ -381,14 +360,13 @@ error: #[test] fn char_and_nl_annotate_char() { let source = "a\r\nb"; - let input = Level::ERROR.header("").group( - Group::new().element( - Snippet::source(source) - .path("file/path") - .line_start(3) - .annotation(AnnotationKind::Primary.span(0..2)), - ), // a\r - ); + let input = &[Group::new().element(Level::ERROR.title("")).element( + Snippet::source(source) + .path("file/path") + .line_start(3) + .annotation(AnnotationKind::Primary.span(0..2)), + // a\r + )]; let expected = str![[r#" error: --> file/path:3:1 @@ -404,14 +382,13 @@ error: #[test] fn char_eol_annotate_char() { let source = "a\r\nb"; - let input = Level::ERROR.header("").group( - Group::new().element( - Snippet::source(source) - .path("file/path") - .line_start(3) - .annotation(AnnotationKind::Primary.span(0..3)), - ), // a\r\n - ); + let input = &[Group::new().element(Level::ERROR.title("")).element( + Snippet::source(source) + .path("file/path") + .line_start(3) + .annotation(AnnotationKind::Primary.span(0..3)), + // a\r\n + )]; let expected = str![[r#" error: --> file/path:3:1 @@ -426,13 +403,12 @@ error: #[test] fn char_eol_annotate_char_double_width() { - let snippets = Level::ERROR.header("").group( - Group::new().element( - Snippet::source("こん\r\nにちは\r\n世界") - .path("") - .annotation(AnnotationKind::Primary.span(3..8)), - ), // ん\r\n - ); + let snippets = &[Group::new().element(Level::ERROR.title("")).element( + Snippet::source("こん\r\nにちは\r\n世界") + .path("") + .annotation(AnnotationKind::Primary.span(3..8)), + // ん\r\n + )]; let expected = str![[r#" error: @@ -452,14 +428,13 @@ error: #[test] fn annotate_eol() { let source = "a\r\nb"; - let input = Level::ERROR.header("").group( - Group::new().element( - Snippet::source(source) - .path("file/path") - .line_start(3) - .annotation(AnnotationKind::Primary.span(1..2)), - ), // \r - ); + let input = &[Group::new().element(Level::ERROR.title("")).element( + Snippet::source(source) + .path("file/path") + .line_start(3) + .annotation(AnnotationKind::Primary.span(1..2)), + // \r + )]; let expected = str![[r#" error: --> file/path:3:2 @@ -475,14 +450,13 @@ error: #[test] fn annotate_eol2() { let source = "a\r\nb"; - let input = Level::ERROR.header("").group( - Group::new().element( - Snippet::source(source) - .path("file/path") - .line_start(3) - .annotation(AnnotationKind::Primary.span(1..3)), - ), // \r\n - ); + let input = &[Group::new().element(Level::ERROR.title("")).element( + Snippet::source(source) + .path("file/path") + .line_start(3) + .annotation(AnnotationKind::Primary.span(1..3)), + // \r\n + )]; let expected = str![[r#" error: --> file/path:3:2 @@ -499,14 +473,13 @@ error: #[test] fn annotate_eol3() { let source = "a\r\nb"; - let input = Level::ERROR.header("").group( - Group::new().element( - Snippet::source(source) - .path("file/path") - .line_start(3) - .annotation(AnnotationKind::Primary.span(2..3)), - ), // \n - ); + let input = &[Group::new().element(Level::ERROR.title("")).element( + Snippet::source(source) + .path("file/path") + .line_start(3) + .annotation(AnnotationKind::Primary.span(2..3)), + // \n + )]; let expected = str![[r#" error: --> file/path:3:3 @@ -523,14 +496,13 @@ error: #[test] fn annotate_eol4() { let source = "a\r\nb"; - let input = Level::ERROR.header("").group( - Group::new().element( - Snippet::source(source) - .path("file/path") - .line_start(3) - .annotation(AnnotationKind::Primary.span(2..2)), - ), // \n - ); + let input = &[Group::new().element(Level::ERROR.title("")).element( + Snippet::source(source) + .path("file/path") + .line_start(3) + .annotation(AnnotationKind::Primary.span(2..2)), + // \n + )]; let expected = str![[r#" error: --> file/path:3:3 @@ -545,13 +517,12 @@ error: #[test] fn annotate_eol_double_width() { - let snippets = Level::ERROR.header("").group( - Group::new().element( - Snippet::source("こん\r\nにちは\r\n世界") - .path("") - .annotation(AnnotationKind::Primary.span(7..8)), - ), // \n - ); + let snippets = &[Group::new().element(Level::ERROR.title("")).element( + Snippet::source("こん\r\nにちは\r\n世界") + .path("") + .annotation(AnnotationKind::Primary.span(7..8)), + // \n + )]; let expected = str![[r#" error: @@ -571,14 +542,13 @@ error: #[test] fn multiline_eol_start() { let source = "a\r\nb"; - let input = Level::ERROR.header("").group( - Group::new().element( - Snippet::source(source) - .path("file/path") - .line_start(3) - .annotation(AnnotationKind::Primary.span(1..4)), - ), // \r\nb - ); + let input = &[Group::new().element(Level::ERROR.title("")).element( + Snippet::source(source) + .path("file/path") + .line_start(3) + .annotation(AnnotationKind::Primary.span(1..4)), + // \r\nb + )]; let expected = str![[r#" error: --> file/path:3:2 @@ -595,14 +565,13 @@ error: #[test] fn multiline_eol_start2() { let source = "a\r\nb"; - let input = Level::ERROR.header("").group( - Group::new().element( - Snippet::source(source) - .path("file/path") - .line_start(3) - .annotation(AnnotationKind::Primary.span(2..4)), - ), // \nb - ); + let input = &[Group::new().element(Level::ERROR.title("")).element( + Snippet::source(source) + .path("file/path") + .line_start(3) + .annotation(AnnotationKind::Primary.span(2..4)), + // \nb + )]; let expected = str![[r#" error: --> file/path:3:3 @@ -619,14 +588,13 @@ error: #[test] fn multiline_eol_start3() { let source = "a\nb"; - let input = Level::ERROR.header("").group( - Group::new().element( - Snippet::source(source) - .path("file/path") - .line_start(3) - .annotation(AnnotationKind::Primary.span(1..3)), - ), // \nb - ); + let input = &[Group::new().element(Level::ERROR.title("")).element( + Snippet::source(source) + .path("file/path") + .line_start(3) + .annotation(AnnotationKind::Primary.span(1..3)), + // \nb + )]; let expected = str![[r#" error: --> file/path:3:2 @@ -642,13 +610,12 @@ error: #[test] fn multiline_eol_start_double_width() { - let snippets = Level::ERROR.header("").group( - Group::new().element( - Snippet::source("こん\r\nにちは\r\n世界") - .path("") - .annotation(AnnotationKind::Primary.span(7..11)), - ), // \r\nに - ); + let snippets = &[Group::new().element(Level::ERROR.title("")).element( + Snippet::source("こん\r\nにちは\r\n世界") + .path("") + .annotation(AnnotationKind::Primary.span(7..11)), + // \r\nに + )]; let expected = str![[r#" error: @@ -668,14 +635,13 @@ error: #[test] fn multiline_eol_start_eol_end() { let source = "a\nb\nc"; - let input = Level::ERROR.header("").group( - Group::new().element( - Snippet::source(source) - .path("file/path") - .line_start(3) - .annotation(AnnotationKind::Primary.span(1..4)), - ), // \nb\n - ); + let input = &[Group::new().element(Level::ERROR.title("")).element( + Snippet::source(source) + .path("file/path") + .line_start(3) + .annotation(AnnotationKind::Primary.span(1..4)), + // \nb\n + )]; let expected = str![[r#" error: --> file/path:3:2 @@ -693,14 +659,13 @@ error: #[test] fn multiline_eol_start_eol_end2() { let source = "a\r\nb\r\nc"; - let input = Level::ERROR.header("").group( - Group::new().element( - Snippet::source(source) - .path("file/path") - .line_start(3) - .annotation(AnnotationKind::Primary.span(2..5)), - ), // \nb\r - ); + let input = &[Group::new().element(Level::ERROR.title("")).element( + Snippet::source(source) + .path("file/path") + .line_start(3) + .annotation(AnnotationKind::Primary.span(2..5)), + // \nb\r + )]; let expected = str![[r#" error: --> file/path:3:3 @@ -718,14 +683,13 @@ error: #[test] fn multiline_eol_start_eol_end3() { let source = "a\r\nb\r\nc"; - let input = Level::ERROR.header("").group( - Group::new().element( - Snippet::source(source) - .path("file/path") - .line_start(3) - .annotation(AnnotationKind::Primary.span(2..6)), - ), // \nb\r\n - ); + let input = &[Group::new().element(Level::ERROR.title("")).element( + Snippet::source(source) + .path("file/path") + .line_start(3) + .annotation(AnnotationKind::Primary.span(2..6)), + // \nb\r\n + )]; let expected = str![[r#" error: --> file/path:3:3 @@ -743,14 +707,13 @@ error: #[test] fn multiline_eol_start_eof_end() { let source = "a\r\nb"; - let input = Level::ERROR.header("").group( - Group::new().element( - Snippet::source(source) - .path("file/path") - .line_start(3) - .annotation(AnnotationKind::Primary.span(1..5)), - ), // \r\nb(EOF) - ); + let input = &[Group::new().element(Level::ERROR.title("")).element( + Snippet::source(source) + .path("file/path") + .line_start(3) + .annotation(AnnotationKind::Primary.span(1..5)), + // \r\nb(EOF) + )]; let expected = str![[r#" error: --> file/path:3:2 @@ -767,14 +730,13 @@ error: #[test] fn multiline_eol_start_eof_end_double_width() { let source = "ん\r\nに"; - let input = Level::ERROR.header("").group( - Group::new().element( - Snippet::source(source) - .path("file/path") - .line_start(3) - .annotation(AnnotationKind::Primary.span(3..9)), - ), // \r\nに(EOF) - ); + let input = &[Group::new().element(Level::ERROR.title("")).element( + Snippet::source(source) + .path("file/path") + .line_start(3) + .annotation(AnnotationKind::Primary.span(3..9)), + // \r\nに(EOF) + )]; let expected = str![[r#" error: --> file/path:3:2 @@ -791,8 +753,9 @@ error: #[test] fn two_single_line_same_line() { let source = r#"bar = { version = "0.1.0", optional = true }"#; - let input = Level::ERROR.header("unused optional dependency").group( - Group::new().element( + let input = &[Group::new() + .element(Level::ERROR.title("unused optional dependency")) + .element( Snippet::source(source) .path("Cargo.toml") .line_start(4) @@ -806,8 +769,7 @@ fn two_single_line_same_line() { .span(27..42) .label("This should also be long but not too long"), ), - ), - ); + )]; let expected = str![[r#" error: unused optional dependency --> Cargo.toml:4:1 @@ -828,8 +790,9 @@ this is another line so is this bar = { version = "0.1.0", optional = true } "#; - let input = Level::ERROR.header("unused optional dependency").group( - Group::new().element( + let input = &[Group::new() + .element(Level::ERROR.title("unused optional dependency")) + .element( Snippet::source(source) .line_start(4) .annotation( @@ -842,8 +805,7 @@ bar = { version = "0.1.0", optional = true } .span(27..42) .label("This should also be long but not too long"), ), - ), - ); + )]; let expected = str![[r#" error: unused optional dependency | @@ -867,8 +829,9 @@ this is another line so is this bar = { version = "0.1.0", optional = true } "#; - let input = Level::ERROR.header("unused optional dependency").group( - Group::new().element( + let input = &[Group::new() + .element(Level::ERROR.title("unused optional dependency")) + .element( Snippet::source(source) .line_start(4) .annotation( @@ -886,8 +849,7 @@ bar = { version = "0.1.0", optional = true } .span(27..42) .label("This should also be long but not too long"), ), - ), - ); + )]; let expected = str![[r#" error: unused optional dependency | @@ -915,8 +877,9 @@ so is this bar = { version = "0.1.0", optional = true } this is another line "#; - let input = Level::ERROR.header("unused optional dependency").group( - Group::new().element( + let input = &[Group::new() + .element(Level::ERROR.title("unused optional dependency")) + .element( Snippet::source(source) .line_start(4) .annotation( @@ -939,8 +902,7 @@ this is another line .span(27..42) .label("This should also be long but not too long"), ), - ), - ); + )]; let expected = str![[r#" error: unused optional dependency | @@ -966,14 +928,12 @@ error: unused optional dependency #[test] fn origin_correct_start_line() { let source = "aaa\nbbb\nccc\nddd\n"; - let input = Level::ERROR.header("title").group( - Group::new().element( - Snippet::source(source) - .path("origin.txt") - .fold(false) - .annotation(AnnotationKind::Primary.span(8..8 + 3).label("annotation")), - ), - ); + let input = &[Group::new().element(Level::ERROR.title("title")).element( + Snippet::source(source) + .path("origin.txt") + .fold(false) + .annotation(AnnotationKind::Primary.span(8..8 + 3).label("annotation")), + )]; let expected = str![[r#" error: title @@ -992,18 +952,16 @@ error: title #[test] fn origin_correct_mid_line() { let source = "aaa\nbbb\nccc\nddd\n"; - let input = Level::ERROR.header("title").group( - Group::new().element( - Snippet::source(source) - .path("origin.txt") - .fold(false) - .annotation( - AnnotationKind::Primary - .span(8 + 1..8 + 3) - .label("annotation"), - ), - ), - ); + let input = &[Group::new().element(Level::ERROR.title("title")).element( + Snippet::source(source) + .path("origin.txt") + .fold(false) + .annotation( + AnnotationKind::Primary + .span(8 + 1..8 + 3) + .label("annotation"), + ), + )]; let expected = str![[r#" error: title @@ -1022,33 +980,33 @@ error: title #[test] fn two_suggestions_same_span() { let source = r#" A.foo();"#; - let input_new = Level::ERROR - .header("expected value, found enum `A`") - .id("E0423") - .group( - Group::new().element( + let input_new = &[ + Group::new() + .element( + Level::ERROR + .title("expected value, found enum `A`") + .id("E0423"), + ) + .element( Snippet::source(source) .fold(true) .annotation(AnnotationKind::Primary.span(4..5)), ), - ) - .group( - Group::new() - .element( - Level::HELP - .title("you might have meant to use one of the following enum variants"), - ) - .element( - Snippet::source(source) - .fold(true) - .patch(Patch::new(4..5, "(A::Tuple())")), - ) - .element( - Snippet::source(source) - .fold(true) - .patch(Patch::new(4..5, "A::Unit")), - ), - ); + Group::new() + .element( + Level::HELP.title("you might have meant to use one of the following enum variants"), + ) + .element( + Snippet::source(source) + .fold(true) + .patch(Patch::new(4..5, "(A::Tuple())")), + ) + .element( + Snippet::source(source) + .fold(true) + .patch(Patch::new(4..5, "A::Unit")), + ), + ]; let expected = str![[r#" error[E0423]: expected value, found enum `A` @@ -1090,11 +1048,9 @@ fn main() { banana::Chaenomeles.pick() }"#; let input_new = - Level::ERROR - .header("no method named `pick` found for struct `Chaenomeles` in the current scope") - .id("E0599") - .group( - Group::new().element( + &[Group::new().element(Level::ERROR + .title("no method named `pick` found for struct `Chaenomeles` in the current scope") + .id("E0599")).element( Snippet::source(source) .line_start(1) .fold(true) @@ -1109,8 +1065,6 @@ fn main() { .label("method not found in `Chaenomeles`"), ), ), - ) - .group( Group::new() .element(Level::HELP.title( "the following traits which provide `pick` are implemented but not in scope; perhaps you want to import one of them", @@ -1124,8 +1078,7 @@ fn main() { Snippet::source(source) .fold(true) .patch(Patch::new(1..1, "use banana::Peach;\n")), - ), - ); + )]; let expected = str![[r#" error[E0599]: no method named `pick` found for struct `Chaenomeles` in the current scope | @@ -1150,28 +1103,29 @@ LL + use banana::Peach; fn single_line_non_overlapping_suggestions() { let source = r#" A.foo();"#; - let input_new = Level::ERROR - .header("expected value, found enum `A`") - .id("E0423") - .group( - Group::new().element( + let input_new = &[ + Group::new() + .element( + Level::ERROR + .title("expected value, found enum `A`") + .id("E0423"), + ) + .element( Snippet::source(source) .fold(true) .line_start(1) .annotation(AnnotationKind::Primary.span(4..5)), ), - ) - .group( - Group::new() - .element(Level::HELP.title("make these changes and things will work")) - .element( - Snippet::source(source) - .fold(true) - .fold(true) - .patch(Patch::new(4..5, "(A::Tuple())")) - .patch(Patch::new(6..9, "bar")), - ), - ); + Group::new() + .element(Level::HELP.title("make these changes and things will work")) + .element( + Snippet::source(source) + .fold(true) + .fold(true) + .patch(Patch::new(4..5, "(A::Tuple())")) + .patch(Patch::new(6..9, "bar")), + ), + ]; let expected = str![[r#" error[E0423]: expected value, found enum `A` @@ -1192,28 +1146,25 @@ LL + (A::Tuple()).bar(); #[test] fn single_line_non_overlapping_suggestions2() { let source = r#" ThisIsVeryLong.foo();"#; - let input_new = Level::ERROR - .header("Found `ThisIsVeryLong`") - .id("E0423") - .group( - Group::new().element( + let input_new = &[ + Group::new() + .element(Level::ERROR.title("Found `ThisIsVeryLong`").id("E0423")) + .element( Snippet::source(source) .fold(true) .line_start(1) .annotation(AnnotationKind::Primary.span(4..18)), ), - ) - .group( - Group::new() - .element(Level::HELP.title("make these changes and things will work")) - .element( - Snippet::source(source) - .fold(true) - .fold(true) - .patch(Patch::new(4..18, "(A::Tuple())")) - .patch(Patch::new(19..22, "bar")), - ), - ); + Group::new() + .element(Level::HELP.title("make these changes and things will work")) + .element( + Snippet::source(source) + .fold(true) + .fold(true) + .patch(Patch::new(4..18, "(A::Tuple())")) + .patch(Patch::new(19..22, "bar")), + ), + ]; let expected = str![[r#" error[E0423]: Found `ThisIsVeryLong` @@ -1241,11 +1192,16 @@ fn multiple_replacements() { y(); "#; - let input_new = Level::ERROR - .header("cannot borrow `*self` as mutable because it is also borrowed as immutable") - .id("E0502") - .group( - Group::new().element( + let input_new = &[ + Group::new() + .element( + Level::ERROR + .title( + "cannot borrow `*self` as mutable because it is also borrowed as immutable", + ) + .id("E0502"), + ) + .element( Snippet::source(source) .line_start(1) .fold(true) @@ -1270,21 +1226,18 @@ fn multiple_replacements() { .label("immutable borrow later used here"), ), ), - ) - .group( - Group::new() - .element( - Level::HELP - .title("try explicitly pass `&Self` into the Closure as an argument"), - ) - .element( - Snippet::source(source) - .fold(true) - .patch(Patch::new(14..14, "this: &Self")) - .patch(Patch::new(26..30, "this")) - .patch(Patch::new(66..68, "(self)")), - ), - ); + Group::new() + .element( + Level::HELP.title("try explicitly pass `&Self` into the Closure as an argument"), + ) + .element( + Snippet::source(source) + .fold(true) + .patch(Patch::new(14..14, "this: &Self")) + .patch(Patch::new(26..30, "this")) + .patch(Patch::new(66..68, "(self)")), + ), + ]; let expected = str![[r#" error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable | @@ -1325,11 +1278,9 @@ fn main() { test1(); }"#; - let input_new = Level::ERROR - .header("cannot borrow `chars` as mutable more than once at a time") - .id("E0499") - .group( - Group::new().element( + let input_new = &[Group::new().element(Level::ERROR + .title("cannot borrow `chars` as mutable more than once at a time") + .id("E0499")).element( Snippet::source(source) .line_start(1) .fold(true) @@ -1349,8 +1300,6 @@ fn main() { .label("first borrow later used here"), ), ), - ) - .group( Group::new() .element( Level::HELP @@ -1365,8 +1314,7 @@ fn main() { )) .patch(Patch::new(61..79, ") = iter.next()")) .patch(Patch::new(90..95, "iter")), - ), - ); + )]; let expected = str![[r#" error[E0499]: cannot borrow `chars` as mutable more than once at a time @@ -1409,45 +1357,42 @@ struct Foo { fn main() {}"#; - let input_new = Level::ERROR - .header("failed to resolve: use of undeclared crate or module `st`") - .id("E0433") - .group( - Group::new().element( + let input_new = &[ + Group::new() + .element( + Level::ERROR + .title("failed to resolve: use of undeclared crate or module `st`") + .id("E0433"), + ) + .element( Snippet::source(source).line_start(1).fold(true).annotation( AnnotationKind::Primary .span(122..124) .label("use of undeclared crate or module `st`"), ), ), - ) - .group( - Group::new() - .element(Level::HELP.title("there is a crate or module with a similar name")) - .element( - Snippet::source(source) - .fold(true) - .patch(Patch::new(122..124, "std")), - ), - ) - .group( - Group::new() - .element(Level::HELP.title("consider importing this module")) - .element( - Snippet::source(source) - .fold(true) - .patch(Patch::new(1..1, "use std::cell;\n")), - ), - ) - .group( - Group::new() - .element(Level::HELP.title("if you import `cell`, refer to it directly")) - .element( - Snippet::source(source) - .fold(true) - .patch(Patch::new(122..126, "")), - ), - ); + Group::new() + .element(Level::HELP.title("there is a crate or module with a similar name")) + .element( + Snippet::source(source) + .fold(true) + .patch(Patch::new(122..124, "std")), + ), + Group::new() + .element(Level::HELP.title("consider importing this module")) + .element( + Snippet::source(source) + .fold(true) + .patch(Patch::new(1..1, "use std::cell;\n")), + ), + Group::new() + .element(Level::HELP.title("if you import `cell`, refer to it directly")) + .element( + Snippet::source(source) + .fold(true) + .patch(Patch::new(122..126, "")), + ), + ]; let expected = str![[r#" error[E0433]: failed to resolve: use of undeclared crate or module `st` | @@ -1491,11 +1436,14 @@ where fn main() {}"#; - let input_new = Level::ERROR - .header("the size for values of type `T` cannot be known at compilation time") - .id("E0277") - .group( - Group::new().element( + let input_new = &[ + Group::new() + .element( + Level::ERROR + .title("the size for values of type `T` cannot be known at compilation time") + .id("E0277"), + ) + .element( Snippet::source(source) .line_start(1) .fold(true) @@ -1510,18 +1458,18 @@ fn main() {}"#; .label("this type parameter needs to be `Sized`"), ), ), - ) - .group( - Group::new() - .element(Level::HELP.title( + Group::new() + .element( + Level::HELP.title( "consider removing the `?Sized` bound to make the type parameter `Sized`", - )) - .element( - Snippet::source(source) - .fold(true) - .patch(Patch::new(52..85, "")), ), - ); + ) + .element( + Snippet::source(source) + .fold(true) + .patch(Patch::new(52..85, "")), + ), + ]; let expected = str![[r#" error[E0277]: the size for values of type `T` cannot be known at compilation time | @@ -1560,10 +1508,9 @@ and where } fn main() {}"#; - let input_new = Level::ERROR - .header("the size for values of type `T` cannot be known at compilation time") - .id("E0277") - .group(Group::new().element(Snippet::source(source) + let input_new = &[Group::new().element(Level::ERROR + .title("the size for values of type `T` cannot be known at compilation time") + .id("E0277")).element(Snippet::source(source) .line_start(1) .path("$DIR/removal-of-multiline-trait-bound-in-where-clause.rs") .fold(true) @@ -1576,8 +1523,8 @@ fn main() {}"#; AnnotationKind::Context .span(31..32) .label("this type parameter needs to be `Sized`"), - ))) - .group(Group::new().element( + )) + ,Group::new().element( Level::NOTE .title("required by an implicit `Sized` bound in `Wrapper`") ).element( @@ -1590,8 +1537,7 @@ fn main() {}"#; .span(16..17) .label("required by the implicit `Sized` requirement on this type parameter in `Wrapper`"), ) - )) - .group(Group::new().element( + ), Group::new().element( Level::HELP .title("you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box`") ) @@ -1611,8 +1557,7 @@ fn main() {}"#; .label("...if indirection were used here: `Box`"), ) - )) - .group(Group::new().element( + ),Group::new().element( Level::HELP .title("consider removing the `?Sized` bound to make the type parameter `Sized`") ).element( @@ -1621,7 +1566,7 @@ fn main() {}"#; .patch(Patch::new(56..89, "")) .patch(Patch::new(89..89, "+ Send")) , - )); + )]; let expected = str![[r#" error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:4:16 @@ -1669,12 +1614,14 @@ quack zappy "#; - let input_new = Level::ERROR - .header("the size for values of type `T` cannot be known at compilation time") - .id("E0277") - // We need an empty group here to ensure the HELP line is rendered correctly - .group(Group::new()) - .group( + let input_new = + &[ + Group::new().element( + Level::ERROR + .title("the size for values of type `T` cannot be known at compilation time") + .id("E0277"), + ), + // We need an empty group here to ensure the HELP line is rendered correctly Group::new() .element(Level::HELP.title( "consider removing the `?Sized` bound to make the type parameter `Sized`", @@ -1686,7 +1633,7 @@ zappy .patch(Patch::new(3..21, "")) .patch(Patch::new(22..40, "")), ), - ); + ]; let expected = str![[r#" error[E0277]: the size for values of type `T` cannot be known at compilation time | @@ -1739,10 +1686,9 @@ fn main() { } "#; - let input_new = Level::ERROR - .header("type mismatch resolving `>, ...>>, ...>>, ...> as Future>::Error == Foo`") - .id("E0271") - .group(Group::new().element(Snippet::source(source) + let input_new = &[Group::new().element(Level::ERROR + .title("type mismatch resolving `>, ...>>, ...>>, ...> as Future>::Error == Foo`") + .id("E0271")).element(Snippet::source(source) .line_start(4) .path("$DIR/E0271.rs") .fold(true) @@ -1750,8 +1696,7 @@ fn main() { AnnotationKind::Primary .span(208..510) .label("type mismatch resolving `, ...>>, ...> as Future>::Error == Foo`"), - ))) - .group(Group::new().element( + )),Group::new().element( Level::NOTE.title("expected this to be `Foo`") ).element( Snippet::source(source) @@ -1763,7 +1708,7 @@ fn main() { Level::NOTE .title("required for the cast from `Box>, ()>>, ()>>, ()>>` to `Box<(dyn Future + 'static)>`") , - )); + )]; let expected = str![[r#" error[E0271]: type mismatch resolving `>, ...>>, ...>>, ...> as Future>::Error == Foo` @@ -1827,10 +1772,9 @@ fn main() { } "#; - let input_new = Level::ERROR - .header("type mismatch resolving `>, ...>>, ...>>, ...> as Future>::Error == Foo`") - .id("E0271") - .group(Group::new().element(Snippet::source(source) + let input_new = &[Group::new().element(Level::ERROR + .title("type mismatch resolving `>, ...>>, ...>>, ...> as Future>::Error == Foo`") + .id("E0271")).element(Snippet::source(source) .line_start(4) .path("$DIR/E0271.rs") .fold(true) @@ -1838,8 +1782,7 @@ fn main() { AnnotationKind::Primary .span(208..510) .label("type mismatch resolving `, ...>>, ...> as Future>::Error == Foo`"), - ))) - .group(Group::new().element( + )),Group::new().element( Level::NOTE.title("expected this to be `Foo`") ).element( Snippet::source(source) @@ -1852,7 +1795,7 @@ fn main() { .title("required for the cast from `Box>, ()>>, ()>>, ()>>` to `Box<(dyn Future + 'static)>`") ).element( Level::NOTE.title("a second note"), - )); + )]; let expected = str![[r#" error[E0271]: type mismatch resolving `>, ...>>, ...>>, ...> as Future>::Error == Foo` @@ -1928,7 +1871,7 @@ fn main() { Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok( Ok("") )))))))))))))))))))))))))))))) - )))))))))))))))))))))))))))))); + )))))))))))))))))))))))))))))]; //~^^^^^ ERROR E0308 let _ = Some(Ok(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some( @@ -1941,7 +1884,7 @@ fn main() { Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok( Ok(Ok(Ok(Ok(Ok(Ok(Ok(""))))))) )))))))))))))))))))))))))))))) - )))))))))))))))))))))))); + )))))))))))))))))))))))]; //~^^^^^ ERROR E0308 let x: Atype< @@ -1975,15 +1918,14 @@ fn main() { Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok( Ok(Ok(Ok(Ok(Ok(Ok(Ok(""))))))) )))))))))))))))))))))))))))))) - )))))))))))))))))))))))); + )))))))))))))))))))))))]; //~^^^^^ ERROR E0308 } "#; - let input_new = Level::ERROR - .header("mismatched types") - .id("E0308") - .group(Group::new().element( + let input_new = &[Group::new().element(Level::ERROR + .title("mismatched types") + .id("E0308")).element( Snippet::source(source) .line_start(7) .path("$DIR/long-E0308.rs") @@ -2008,7 +1950,7 @@ fn main() { Level::NOTE .title("consider using `--verbose` to print the full type name to the console") , - )); + )]; let expected = str![[r#" error[E0308]: mismatched types @@ -2028,7 +1970,7 @@ LL │ │ > = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O… LL │ ┃ Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O… LL │ ┃ Ok("") LL │ ┃ )))))))))))))))))))))))))))))) -LL │ ┃ )))))))))))))))))))))))))))))); +LL │ ┃ )))))))))))))))))))))))))))))]; │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ expected `Atype, i32>, i32>`, found `Result, _>, _>` │ ├ note: expected struct `Atype, i32>` @@ -2065,10 +2007,9 @@ fn main() { } "#; - let input_new = Level::ERROR - .header("mismatched types") - .id("E0308") - .group(Group::new().element( + let input_new = &[Group::new().element(Level::ERROR + .title("mismatched types") + .id("E0308")).element( Snippet::source(source) .line_start(7) .path("$DIR/unicode-output.rs") @@ -2087,8 +2028,7 @@ fn main() { Level::NOTE .title("expected fn pointer `for<'a> fn(Box<(dyn Any + Send + 'a)>) -> Pin<_>`\n found fn item `fn(Box<(dyn Any + Send + 'static)>) -> Pin<_> {wrapped_fn}`") , - )) - .group(Group::new().element( + ),Group::new().element( Level::NOTE.title("function defined here"), ).element( Snippet::source(source) @@ -2097,7 +2037,7 @@ fn main() { .fold(true) .annotation(AnnotationKind::Primary.span(77..210)) .annotation(AnnotationKind::Context.span(71..76)), - )); + )]; let expected = str![[r#" error[E0308]: mismatched types @@ -2134,13 +2074,11 @@ LL │ ┃ )>>) {} #[test] fn unicode_cut_handling() { let source = "version = \"0.1.0\"\n# Ensure that the spans from toml handle utf-8 correctly\nauthors = [\n { name = \"Z\u{351}\u{36b}\u{343}\u{36a}\u{302}\u{36b}\u{33d}\u{34f}\u{334}\u{319}\u{324}\u{31e}\u{349}\u{35a}\u{32f}\u{31e}\u{320}\u{34d}A\u{36b}\u{357}\u{334}\u{362}\u{335}\u{31c}\u{330}\u{354}L\u{368}\u{367}\u{369}\u{358}\u{320}G\u{311}\u{357}\u{30e}\u{305}\u{35b}\u{341}\u{334}\u{33b}\u{348}\u{34d}\u{354}\u{339}O\u{342}\u{30c}\u{30c}\u{358}\u{328}\u{335}\u{339}\u{33b}\u{31d}\u{333}\", email = 1 }\n]\n"; - let input = Level::ERROR.header("title").group( - Group::new().element( - Snippet::source(source) - .fold(false) - .annotation(AnnotationKind::Primary.span(85..228).label("annotation")), - ), - ); + let input = &[Group::new().element(Level::ERROR.title("title")).element( + Snippet::source(source) + .fold(false) + .annotation(AnnotationKind::Primary.span(85..228).label("annotation")), + )]; let expected_ascii = str![[r#" error: title | @@ -2153,7 +2091,7 @@ error: title | |_^ annotation "#]]; let renderer_ascii = Renderer::plain(); - assert_data_eq!(renderer_ascii.render(input.clone()), expected_ascii); + assert_data_eq!(renderer_ascii.render(input), expected_ascii); let expected_unicode = str![[r#" error: title @@ -2173,17 +2111,15 @@ error: title #[test] fn unicode_cut_handling2() { let source = "/*这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/?"; - let input = Level::ERROR - .header("expected item, found `?`") - .group( - Group::new().element( + let input = &[Group::new().element(Level::ERROR + .title("expected item, found `?`")).element( Snippet::source(source) .fold(false) .annotation(AnnotationKind::Primary.span(499..500).label("expected item")) ).element( Level::NOTE.title("for a full list of items that can appear in modules, see ") - ) - ); + + )]; let expected_ascii = str![[r#" error: expected item, found `?` @@ -2195,7 +2131,7 @@ error: expected item, found `?` "#]]; let renderer_ascii = Renderer::plain(); - assert_data_eq!(renderer_ascii.render(input.clone()), expected_ascii); + assert_data_eq!(renderer_ascii.render(input), expected_ascii); let expected_unicode = str![[r#" error: expected item, found `?` @@ -2212,17 +2148,15 @@ error: expected item, found `?` #[test] fn unicode_cut_handling3() { let source = "/*这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/?"; - let input = Level::ERROR - .header("expected item, found `?`") - .group( - Group::new().element( + let input = &[Group::new().element(Level::ERROR + .title("expected item, found `?`")).element( Snippet::source(source) .fold(false) .annotation(AnnotationKind::Primary.span(251..254).label("expected item")) ).element( Level::NOTE.title("for a full list of items that can appear in modules, see ") - ) - ); + + )]; let expected_ascii = str![[r#" error: expected item, found `?` @@ -2234,7 +2168,7 @@ error: expected item, found `?` "#]]; let renderer_ascii = Renderer::plain().term_width(43); - assert_data_eq!(renderer_ascii.render(input.clone()), expected_ascii); + assert_data_eq!(renderer_ascii.render(input), expected_ascii); let expected_unicode = str![[r#" error: expected item, found `?` @@ -2251,17 +2185,15 @@ error: expected item, found `?` #[test] fn unicode_cut_handling4() { let source = "/*aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa*/?"; - let input = Level::ERROR - .header("expected item, found `?`") - .group( - Group::new().element( + let input = &[Group::new().element(Level::ERROR + .title("expected item, found `?`")).element( Snippet::source(source) .fold(false) .annotation(AnnotationKind::Primary.span(334..335).label("expected item")) ).element( Level::NOTE.title("for a full list of items that can appear in modules, see ") - ) - ); + + )]; let expected_ascii = str![[r#" error: expected item, found `?` @@ -2273,7 +2205,7 @@ error: expected item, found `?` "#]]; let renderer_ascii = Renderer::plain(); - assert_data_eq!(renderer_ascii.render(input.clone()), expected_ascii); + assert_data_eq!(renderer_ascii.render(input), expected_ascii); let expected_unicode = str![[r#" error: expected item, found `?` @@ -2296,8 +2228,9 @@ fn main() { //~^ ERROR mismatched types } "##; - let input = Level::ERROR.header("mismatched types").id("E0308").group( - Group::new().element( + let input = &[Group::new() + .element(Level::ERROR.title("mismatched types").id("E0308")) + .element( Snippet::source(source) .path("$DIR/non-whitespace-trimming-unicode.rs") .fold(true) @@ -2311,8 +2244,7 @@ fn main() { .span(1202..1204) .label("expected due to this"), ), - ), - ); + )]; let expected_ascii = str![[r#" error[E0308]: mismatched types @@ -2325,7 +2257,7 @@ LL | ...♧♨♩♪♫♬♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾ "#]]; let renderer_ascii = Renderer::plain().anonymized_line_numbers(true); - assert_data_eq!(renderer_ascii.render(input.clone()), expected_ascii); + assert_data_eq!(renderer_ascii.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0308]: mismatched types @@ -2352,38 +2284,37 @@ fn main() { //[ascii]~^ ERROR cannot add `&str` to `&str` } "##; - let input = Level::ERROR - .header("cannot add `&str` to `&str`") - .id("E0369") - .group( - Group::new() - .element( - Snippet::source(source) - .path("$DIR/non-1-width-unicode-multiline-label.rs") - .fold(true) - .annotation(AnnotationKind::Context.span(970..984).label("&str")) - .annotation(AnnotationKind::Context.span(987..1001).label("&str")) - .annotation( - AnnotationKind::Primary - .span(985..986) - .label("`+` cannot be used to concatenate two `&str` strings"), - ), - ) - .element( - Level::NOTE - .title("string concatenation requires an owned `String` on the left"), - ), - ) - .group( - Group::new() - .element(Level::HELP.title("create an owned `String` from a string reference")) - .element( - Snippet::source(source) - .path("$DIR/non-1-width-unicode-multiline-label.rs") - .fold(true) - .patch(Patch::new(984..984, ".to_owned()")), - ), - ); + let input = &[ + Group::new() + .element( + Level::ERROR + .title("cannot add `&str` to `&str`") + .id("E0369"), + ) + .element( + Snippet::source(source) + .path("$DIR/non-1-width-unicode-multiline-label.rs") + .fold(true) + .annotation(AnnotationKind::Context.span(970..984).label("&str")) + .annotation(AnnotationKind::Context.span(987..1001).label("&str")) + .annotation( + AnnotationKind::Primary + .span(985..986) + .label("`+` cannot be used to concatenate two `&str` strings"), + ), + ) + .element( + Level::NOTE.title("string concatenation requires an owned `String` on the left"), + ), + Group::new() + .element(Level::HELP.title("create an owned `String` from a string reference")) + .element( + Snippet::source(source) + .path("$DIR/non-1-width-unicode-multiline-label.rs") + .fold(true) + .patch(Patch::new(984..984, ".to_owned()")), + ), + ]; let expected_ascii = str![[r#" error[E0369]: cannot add `&str` to `&str` @@ -2403,7 +2334,7 @@ LL | let _ = "ༀ༁༂༃༄༅༆༇༈༉༊་༌།༎༏༐༑༒༓ "#]]; let renderer_ascii = Renderer::plain().anonymized_line_numbers(true); - assert_data_eq!(renderer_ascii.render(input.clone()), expected_ascii); + assert_data_eq!(renderer_ascii.render(input), expected_ascii); let expected_unicode = str![[r#" error[E0369]: cannot add `&str` to `&str` @@ -2437,17 +2368,13 @@ fn foo() { } "##; let bin_source = "�|�\u{0002}!5�cc\u{0015}\u{0002}�Ӻi��WWj�ȥ�'�}�\u{0012}�J�ȉ��W�\u{001e}O�@����\u{001c}w�V���LO����\u{0014}[ \u{0003}_�'���SQ�~ذ��ų&��-\t��lN~��!@␌ _#���kQ��h�\u{001d}�:�\u{001c}\u{0007}�"; - let input = Level::ERROR - .header("couldn't read `$DIR/not-utf8.bin`: stream did not contain valid UTF-8") - .group( - Group::new().element( + let input = &[Group::new().element(Level::ERROR + .title("couldn't read `$DIR/not-utf8.bin`: stream did not contain valid UTF-8")).element( Snippet::source(source) .path("$DIR/not-utf8.rs") .fold(true) .annotation(AnnotationKind::Primary.span(136..160)), ), - ) - .group( Group::new() .element(Level::NOTE.title("byte `193` is not valid utf-8")) .element( @@ -2457,7 +2384,7 @@ fn foo() { .annotation(AnnotationKind::Primary.span(0..0)), ) .element(Level::NOTE.title("this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info)")), - ); + ]; let expected_ascii = str![[r#" error: couldn't read `$DIR/not-utf8.bin`: stream did not contain valid UTF-8 @@ -2475,7 +2402,7 @@ LL | �|�␂!5�cc␕␂�Ӻi��WWj�ȥ�'�}�␒�J�ȉ��W "#]]; let renderer_ascii = Renderer::plain().anonymized_line_numbers(true); - assert_data_eq!(renderer_ascii.render(input.clone()), expected_ascii); + assert_data_eq!(renderer_ascii.render(input), expected_ascii); let expected_unicode = str![[r#" error: couldn't read `$DIR/not-utf8.bin`: stream did not contain valid UTF-8 @@ -2502,29 +2429,28 @@ fn secondary_title_no_level_text() { let s: &str = include_bytes!("file.txt"); //~ ERROR mismatched types }"#; - let input = Level::ERROR.header("mismatched types").id("E0308").group( - Group::new() - .element( - Snippet::source(source) - .path("$DIR/mismatched-types.rs") - .fold(true) - .annotation( - AnnotationKind::Primary - .span(105..131) - .label("expected `&str`, found `&[u8; 0]`"), - ) - .annotation( - AnnotationKind::Context - .span(98..102) - .label("expected due to this"), - ), - ) - .element( - Level::NOTE - .text(None) - .title("expected reference `&str`\nfound reference `&'static [u8; 0]`"), - ), - ); + let input = &[Group::new() + .element(Level::ERROR.title("mismatched types").id("E0308")) + .element( + Snippet::source(source) + .path("$DIR/mismatched-types.rs") + .fold(true) + .annotation( + AnnotationKind::Primary + .span(105..131) + .label("expected `&str`, found `&[u8; 0]`"), + ) + .annotation( + AnnotationKind::Context + .span(98..102) + .label("expected due to this"), + ), + ) + .element( + Level::NOTE + .text(None) + .title("expected reference `&str`\nfound reference `&'static [u8; 0]`"), + )]; let expected = str![[r#" error[E0308]: mismatched types @@ -2548,42 +2474,155 @@ fn secondary_title_custom_level_text() { let s: &str = include_bytes!("file.txt"); //~ ERROR mismatched types }"#; - let input = Level::ERROR.header("mismatched types").id("E0308").group( + let input = &[Group::new() + .element(Level::ERROR.title("mismatched types").id("E0308")) + .element( + Snippet::source(source) + .path("$DIR/mismatched-types.rs") + .fold(true) + .annotation( + AnnotationKind::Primary + .span(105..131) + .label("expected `&str`, found `&[u8; 0]`"), + ) + .annotation( + AnnotationKind::Context + .span(98..102) + .label("expected due to this"), + ), + ) + .element( + Level::NOTE + .text(Some("custom")) + .title("expected reference `&str`\nfound reference `&'static [u8; 0]`"), + )]; + + let expected = str![[r#" +error[E0308]: mismatched types + --> $DIR/mismatched-types.rs:3:19 + | +LL | let s: &str = include_bytes!("file.txt"); //~ ERROR mismatched types + | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&str`, found `&[u8; 0]` + | | + | expected due to this + | + = custom: expected reference `&str` + found reference `&'static [u8; 0]` +"#]]; + let renderer = Renderer::plain().anonymized_line_numbers(true); + assert_data_eq!(renderer.render(input), expected); +} + +#[test] +fn id_on_title() { + let source = r#"// Regression test for issue #114529 +// Tests that we do not ICE during const eval for a +// break-with-value in contexts where it is illegal + +#[allow(while_true)] +fn main() { + [(); { + while true { + break 9; //~ ERROR `break` with value from a `while` loop + }; + 51 + }]; + + [(); { + while let Some(v) = Some(9) { + break v; //~ ERROR `break` with value from a `while` loop + }; + 51 + }]; + + while true { + break (|| { //~ ERROR `break` with value from a `while` loop + let local = 9; + }); + } +} +"#; + let input = &[ Group::new() + .element( + Level::ERROR + .title("`break` with value from a `while` loop") + .id("E0571"), + ) .element( Snippet::source(source) - .path("$DIR/mismatched-types.rs") + .line_start(1) + .path("$DIR/issue-114529-illegal-break-with-value.rs") .fold(true) .annotation( AnnotationKind::Primary - .span(105..131) - .label("expected `&str`, found `&[u8; 0]`"), + .span(483..581) + .label("can only break with a value inside `loop` or breakable block"), ) .annotation( AnnotationKind::Context - .span(98..102) - .label("expected due to this"), + .span(462..472) + .label("you can't `break` with a value in a `while` loop"), ), + ), + Group::new() + .element( + Level::HELP + .text(Some("suggestion")) + .title("use `break` on its own without a value inside this `while` loop") + .id("S0123"), ) .element( - Level::NOTE - .text(Some("custom")) - .title("expected reference `&str`\nfound reference `&'static [u8; 0]`"), + Snippet::source(source) + .line_start(1) + .path("$DIR/issue-114529-illegal-break-with-value.rs") + .fold(true) + .patch(Patch::new(483..581, "break")), ), - ); + ]; - let expected = str![[r#" -error[E0308]: mismatched types - --> $DIR/mismatched-types.rs:3:19 + let expected_ascii = str![[r#" +error[E0571]: `break` with value from a `while` loop + --> $DIR/issue-114529-illegal-break-with-value.rs:22:9 | -LL | let s: &str = include_bytes!("file.txt"); //~ ERROR mismatched types - | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&str`, found `&[u8; 0]` - | | - | expected due to this +LL | while true { + | ---------- you can't `break` with a value in a `while` loop +LL | / break (|| { //~ ERROR `break` with value from a `while` loop +LL | | let local = 9; +LL | | }); + | |__________^ can only break with a value inside `loop` or breakable block + | +suggestion[S0123]: use `break` on its own without a value inside this `while` loop + | +LL - break (|| { //~ ERROR `break` with value from a `while` loop +LL - let local = 9; +LL - }); +LL + break; | - = custom: expected reference `&str` - found reference `&'static [u8; 0]` "#]]; - let renderer = Renderer::plain().anonymized_line_numbers(true); - assert_data_eq!(renderer.render(input), expected); + + let renderer_ascii = Renderer::plain().anonymized_line_numbers(true); + assert_data_eq!(renderer_ascii.render(input), expected_ascii); + + let expected_unicode = str![[r#" +error[E0571]: `break` with value from a `while` loop + ╭▸ $DIR/issue-114529-illegal-break-with-value.rs:22:9 + │ +LL │ while true { + │ ────────── you can't `break` with a value in a `while` loop +LL │ ┏ break (|| { //~ ERROR `break` with value from a `while` loop +LL │ ┃ let local = 9; +LL │ ┃ }); + │ ┗━━━━━━━━━━┛ can only break with a value inside `loop` or breakable block + ╰╴ +suggestion[S0123]: use `break` on its own without a value inside this `while` loop + ╭╴ +LL - break (|| { //~ ERROR `break` with value from a `while` loop +LL - let local = 9; +LL - }); +LL + break; + ╰╴ +"#]]; + let renderer_unicode = renderer_ascii.theme(OutputTheme::Unicode); + assert_data_eq!(renderer_unicode.render(input), expected_unicode); } diff --git a/tests/rustc_tests.rs b/tests/rustc_tests.rs index c5e0602f..de5f615f 100644 --- a/tests/rustc_tests.rs +++ b/tests/rustc_tests.rs @@ -13,15 +13,13 @@ fn ends_on_col0() { fn foo() { } "#; - let input = Level::ERROR.header("foo").group( - Group::new().element( - Snippet::source(source) - .line_start(1) - .path("test.rs") - .fold(true) - .annotation(AnnotationKind::Primary.span(10..13).label("test")), - ), - ); + let input = &[Group::new().element(Level::ERROR.title("foo")).element( + Snippet::source(source) + .line_start(1) + .path("test.rs") + .fold(true) + .annotation(AnnotationKind::Primary.span(10..13).label("test")), + )]; let expected = str![[r#" error: foo @@ -43,16 +41,13 @@ fn foo() { } "#; - let input = Level::ERROR.header("foo").group( - Group::new().element( - Snippet::source(source) - .line_start(1) - .path("test.rs") - .fold(true) - .annotation(AnnotationKind::Primary.span(10..17).label("test")), - ), - ); - + let input = &[Group::new().element(Level::ERROR.title("foo")).element( + Snippet::source(source) + .line_start(1) + .path("test.rs") + .fold(true) + .annotation(AnnotationKind::Primary.span(10..17).label("test")), + )]; let expected = str![[r#" error: foo --> test.rs:2:10 @@ -75,24 +70,22 @@ fn foo() { X2 Y2 } "#; - let input = Level::ERROR.header("foo").group( - Group::new().element( - Snippet::source(source) - .line_start(1) - .path("test.rs") - .fold(true) - .annotation( - AnnotationKind::Primary - .span(14..32) - .label("`X` is a good letter"), - ) - .annotation( - AnnotationKind::Context - .span(17..35) - .label("`Y` is a good letter too"), - ), - ), - ); + let input = &[Group::new().element(Level::ERROR.title("foo")).element( + Snippet::source(source) + .line_start(1) + .path("test.rs") + .fold(true) + .annotation( + AnnotationKind::Primary + .span(14..32) + .label("`X` is a good letter"), + ) + .annotation( + AnnotationKind::Context + .span(17..35) + .label("`Y` is a good letter too"), + ), + )]; let expected = str![[r#" error: foo @@ -118,24 +111,22 @@ fn foo() { Y1 X1 } "#; - let input = Level::ERROR.header("foo").group( - Group::new().element( - Snippet::source(source) - .line_start(1) - .path("test.rs") - .fold(true) - .annotation( - AnnotationKind::Primary - .span(14..27) - .label("`X` is a good letter"), - ) - .annotation( - AnnotationKind::Context - .span(17..24) - .label("`Y` is a good letter too"), - ), - ), - ); + let input = &[Group::new().element(Level::ERROR.title("foo")).element( + Snippet::source(source) + .line_start(1) + .path("test.rs") + .fold(true) + .annotation( + AnnotationKind::Primary + .span(14..27) + .label("`X` is a good letter"), + ) + .annotation( + AnnotationKind::Context + .span(17..24) + .label("`Y` is a good letter too"), + ), + )]; let expected = str![[r#" error: foo @@ -162,24 +153,22 @@ fn foo() { X3 Y3 Z3 } "#; - let input = Level::ERROR.header("foo").group( - Group::new().element( - Snippet::source(source) - .line_start(1) - .path("test.rs") - .fold(true) - .annotation( - AnnotationKind::Primary - .span(17..38) - .label("`X` is a good letter"), - ) - .annotation( - AnnotationKind::Context - .span(31..49) - .label("`Y` is a good letter too"), - ), - ), - ); + let input = &[Group::new().element(Level::ERROR.title("foo")).element( + Snippet::source(source) + .line_start(1) + .path("test.rs") + .fold(true) + .annotation( + AnnotationKind::Primary + .span(17..38) + .label("`X` is a good letter"), + ) + .annotation( + AnnotationKind::Context + .span(31..49) + .label("`Y` is a good letter too"), + ), + )]; let expected = str![[r#" error: foo @@ -206,25 +195,23 @@ fn foo() { X2 Y2 Z2 } "#; - let input = Level::ERROR.header("foo").group( - Group::new().element( - Snippet::source(source) - .line_start(1) - .path("test.rs") - .fold(true) - .annotation( - AnnotationKind::Primary - .span(14..38) - .label("`X` is a good letter"), - ) - .annotation( - AnnotationKind::Context - .span(17..41) - .label("`Y` is a good letter too"), - ) - .annotation(AnnotationKind::Context.span(20..44).label("`Z` label")), - ), - ); + let input = &[Group::new().element(Level::ERROR.title("foo")).element( + Snippet::source(source) + .line_start(1) + .path("test.rs") + .fold(true) + .annotation( + AnnotationKind::Primary + .span(14..38) + .label("`X` is a good letter"), + ) + .annotation( + AnnotationKind::Context + .span(17..41) + .label("`Y` is a good letter too"), + ) + .annotation(AnnotationKind::Context.span(20..44).label("`Z` label")), + )]; let expected = str![[r#" error: foo @@ -253,25 +240,23 @@ fn foo() { X2 Y2 Z2 } "#; - let input = Level::ERROR.header("foo").group( - Group::new().element( - Snippet::source(source) - .line_start(1) - .path("test.rs") - .fold(true) - .annotation( - AnnotationKind::Primary - .span(14..38) - .label("`X` is a good letter"), - ) - .annotation( - AnnotationKind::Context - .span(14..38) - .label("`Y` is a good letter too"), - ) - .annotation(AnnotationKind::Context.span(14..38).label("`Z` label")), - ), - ); + let input = &[Group::new().element(Level::ERROR.title("foo")).element( + Snippet::source(source) + .line_start(1) + .path("test.rs") + .fold(true) + .annotation( + AnnotationKind::Primary + .span(14..38) + .label("`X` is a good letter"), + ) + .annotation( + AnnotationKind::Context + .span(14..38) + .label("`Y` is a good letter too"), + ) + .annotation(AnnotationKind::Context.span(14..38).label("`Z` label")), + )]; // This should have a `^` but we currently don't support the idea of a // "primary" annotation, which would solve this @@ -301,25 +286,23 @@ fn foo() { X3 Y3 Z3 } "#; - let input = Level::ERROR.header("foo").group( - Group::new().element( - Snippet::source(source) - .line_start(1) - .path("test.rs") - .fold(true) - .annotation( - AnnotationKind::Primary - .span(17..27) - .label("`X` is a good letter"), - ) - .annotation( - AnnotationKind::Context - .span(28..44) - .label("`Y` is a good letter too"), - ) - .annotation(AnnotationKind::Context.span(36..52).label("`Z`")), - ), - ); + let input = &[Group::new().element(Level::ERROR.title("foo")).element( + Snippet::source(source) + .line_start(1) + .path("test.rs") + .fold(true) + .annotation( + AnnotationKind::Primary + .span(17..27) + .label("`X` is a good letter"), + ) + .annotation( + AnnotationKind::Context + .span(28..44) + .label("`Y` is a good letter too"), + ) + .annotation(AnnotationKind::Context.span(36..52).label("`Z`")), + )]; let expected = str![[r#" error: foo @@ -351,24 +334,22 @@ fn foo() { X3 Y3 Z3 } "#; - let input = Level::ERROR.header("foo").group( - Group::new().element( - Snippet::source(source) - .line_start(1) - .path("test.rs") - .fold(true) - .annotation( - AnnotationKind::Primary - .span(14..27) - .label("`X` is a good letter"), - ) - .annotation( - AnnotationKind::Context - .span(39..55) - .label("`Y` is a good letter too"), - ), - ), - ); + let input = &[Group::new().element(Level::ERROR.title("foo")).element( + Snippet::source(source) + .line_start(1) + .path("test.rs") + .fold(true) + .annotation( + AnnotationKind::Primary + .span(14..27) + .label("`X` is a good letter"), + ) + .annotation( + AnnotationKind::Context + .span(39..55) + .label("`Y` is a good letter too"), + ), + )]; let expected = str![[r#" error: foo @@ -395,24 +376,22 @@ fn foo() { X3 Y3 Z3 } "#; - let input = Level::ERROR.header("foo").group( - Group::new().element( - Snippet::source(source) - .line_start(1) - .path("test.rs") - .fold(true) - .annotation( - AnnotationKind::Primary - .span(17..27) - .label("`X` is a good letter"), - ) - .annotation( - AnnotationKind::Context - .span(31..55) - .label("`Y` is a good letter too"), - ), - ), - ); + let input = &[Group::new().element(Level::ERROR.title("foo")).element( + Snippet::source(source) + .line_start(1) + .path("test.rs") + .fold(true) + .annotation( + AnnotationKind::Primary + .span(17..27) + .label("`X` is a good letter"), + ) + .annotation( + AnnotationKind::Context + .span(31..55) + .label("`Y` is a good letter too"), + ), + )]; let expected = str![[r#" error: foo @@ -438,21 +417,19 @@ fn foo() { a { b { c } d } } "#; - let input = Level::ERROR.header("foo").group( - Group::new().element( - Snippet::source(source) - .line_start(1) - .path("test.rs") - .fold(true) - .annotation(AnnotationKind::Primary.span(18..25).label("")) - .annotation( - AnnotationKind::Context - .span(14..27) - .label("`a` is a good letter"), - ) - .annotation(AnnotationKind::Context.span(22..23).label("")), - ), - ); + let input = &[Group::new().element(Level::ERROR.title("foo")).element( + Snippet::source(source) + .line_start(1) + .path("test.rs") + .fold(true) + .annotation(AnnotationKind::Primary.span(18..25).label("")) + .annotation( + AnnotationKind::Context + .span(14..27) + .label("`a` is a good letter"), + ) + .annotation(AnnotationKind::Context.span(22..23).label("")), + )]; let expected = str![[r#" error: foo @@ -471,20 +448,18 @@ fn foo() { a { b { c } d } } "#; - let input = Level::ERROR.header("foo").group( - Group::new().element( - Snippet::source(source) - .line_start(1) - .path("test.rs") - .fold(true) - .annotation( - AnnotationKind::Primary - .span(14..27) - .label("`a` is a good letter"), - ) - .annotation(AnnotationKind::Context.span(18..25).label("")), - ), - ); + let input = &[Group::new().element(Level::ERROR.title("foo")).element( + Snippet::source(source) + .line_start(1) + .path("test.rs") + .fold(true) + .annotation( + AnnotationKind::Primary + .span(14..27) + .label("`a` is a good letter"), + ) + .annotation(AnnotationKind::Context.span(18..25).label("")), + )]; let expected = str![[r#" error: foo @@ -503,21 +478,19 @@ fn foo() { a { b { c } d } } "#; - let input = Level::ERROR.header("foo").group( - Group::new().element( - Snippet::source(source) - .line_start(1) - .path("test.rs") - .fold(true) - .annotation( - AnnotationKind::Primary - .span(18..25) - .label("`b` is a good letter"), - ) - .annotation(AnnotationKind::Context.span(14..27).label("")) - .annotation(AnnotationKind::Context.span(22..23).label("")), - ), - ); + let input = &[Group::new().element(Level::ERROR.title("foo")).element( + Snippet::source(source) + .line_start(1) + .path("test.rs") + .fold(true) + .annotation( + AnnotationKind::Primary + .span(18..25) + .label("`b` is a good letter"), + ) + .annotation(AnnotationKind::Context.span(14..27).label("")) + .annotation(AnnotationKind::Context.span(22..23).label("")), + )]; let expected = str![[r#" error: foo @@ -538,20 +511,18 @@ fn foo() { a { b { c } d } } "#; - let input = Level::ERROR.header("foo").group( - Group::new().element( - Snippet::source(source) - .line_start(1) - .path("test.rs") - .fold(true) - .annotation(AnnotationKind::Primary.span(14..27).label("")) - .annotation( - AnnotationKind::Context - .span(18..25) - .label("`b` is a good letter"), - ), - ), - ); + let input = &[Group::new().element(Level::ERROR.title("foo")).element( + Snippet::source(source) + .line_start(1) + .path("test.rs") + .fold(true) + .annotation(AnnotationKind::Primary.span(14..27).label("")) + .annotation( + AnnotationKind::Context + .span(18..25) + .label("`b` is a good letter"), + ), + )]; let expected = str![[r#" error: foo @@ -572,20 +543,18 @@ fn foo() { a bc d } "#; - let input = Level::ERROR.header("foo").group( - Group::new().element( - Snippet::source(source) - .line_start(1) - .path("test.rs") - .fold(true) - .annotation( - AnnotationKind::Primary - .span(14..18) - .label("`a` is a good letter"), - ) - .annotation(AnnotationKind::Context.span(18..22).label("")), - ), - ); + let input = &[Group::new().element(Level::ERROR.title("foo")).element( + Snippet::source(source) + .line_start(1) + .path("test.rs") + .fold(true) + .annotation( + AnnotationKind::Primary + .span(14..18) + .label("`a` is a good letter"), + ) + .annotation(AnnotationKind::Context.span(18..22).label("")), + )]; let expected = str![[r#" error: foo @@ -606,16 +575,14 @@ fn foo() { a { b { c } d } } "#; - let input = Level::ERROR.header("foo").group( - Group::new().element( - Snippet::source(source) - .line_start(1) - .path("test.rs") - .fold(true) - .annotation(AnnotationKind::Primary.span(14..27).label("")) - .annotation(AnnotationKind::Context.span(18..25).label("")), - ), - ); + let input = &[Group::new().element(Level::ERROR.title("foo")).element( + Snippet::source(source) + .line_start(1) + .path("test.rs") + .fold(true) + .annotation(AnnotationKind::Primary.span(14..27).label("")) + .annotation(AnnotationKind::Context.span(18..25).label("")), + )]; let expected = str![[r#" error: foo @@ -634,17 +601,15 @@ fn foo() { a { b { c } d } } "#; - let input = Level::ERROR.header("foo").group( - Group::new().element( - Snippet::source(source) - .line_start(1) - .path("test.rs") - .fold(true) - .annotation(AnnotationKind::Primary.span(18..25).label("")) - .annotation(AnnotationKind::Context.span(14..27).label("")) - .annotation(AnnotationKind::Context.span(22..23).label("")), - ), - ); + let input = &[Group::new().element(Level::ERROR.title("foo")).element( + Snippet::source(source) + .line_start(1) + .path("test.rs") + .fold(true) + .annotation(AnnotationKind::Primary.span(18..25).label("")) + .annotation(AnnotationKind::Context.span(14..27).label("")) + .annotation(AnnotationKind::Context.span(22..23).label("")), + )]; let expected = str![[r#" error: foo @@ -663,24 +628,22 @@ fn foo() { a { b { c } d } } "#; - let input = Level::ERROR.header("foo").group( - Group::new().element( - Snippet::source(source) - .line_start(1) - .path("test.rs") - .fold(true) - .annotation( - AnnotationKind::Primary - .span(14..27) - .label("`a` is a good letter"), - ) - .annotation( - AnnotationKind::Context - .span(18..25) - .label("`b` is a good letter"), - ), - ), - ); + let input = &[Group::new().element(Level::ERROR.title("foo")).element( + Snippet::source(source) + .line_start(1) + .path("test.rs") + .fold(true) + .annotation( + AnnotationKind::Primary + .span(14..27) + .label("`a` is a good letter"), + ) + .annotation( + AnnotationKind::Context + .span(18..25) + .label("`b` is a good letter"), + ), + )]; let expected = str![[r#" error: foo @@ -702,19 +665,17 @@ fn foo() { a { b { c } d } } "#; - let input = Level::ERROR.header("foo").group( - Group::new().element( - Snippet::source(source) - .line_start(1) - .path("test.rs") - .fold(true) - .annotation( - AnnotationKind::Primary - .span(14..27) - .label("`a` is a good letter"), - ), - ), - ); + let input = &[Group::new().element(Level::ERROR.title("foo")).element( + Snippet::source(source) + .line_start(1) + .path("test.rs") + .fold(true) + .annotation( + AnnotationKind::Primary + .span(14..27) + .label("`a` is a good letter"), + ), + )]; let expected = str![[r#" error: foo @@ -733,15 +694,13 @@ fn foo() { a { b { c } d } } "#; - let input = Level::ERROR.header("foo").group( - Group::new().element( - Snippet::source(source) - .line_start(1) - .path("test.rs") - .fold(true) - .annotation(AnnotationKind::Primary.span(14..27).label("")), - ), - ); + let input = &[Group::new().element(Level::ERROR.title("foo")).element( + Snippet::source(source) + .line_start(1) + .path("test.rs") + .fold(true) + .annotation(AnnotationKind::Primary.span(14..27).label("")), + )]; let expected = str![[r#" error: foo @@ -773,24 +732,22 @@ fn foo() { X3 Y3 Z3 } "#; - let input = Level::ERROR.header("foo").group( - Group::new().element( - Snippet::source(source) - .line_start(1) - .path("test.rs") - .fold(true) - .annotation( - AnnotationKind::Primary - .span(17..27) - .label("`X` is a good letter"), - ) - .annotation( - AnnotationKind::Context - .span(31..76) - .label("`Y` is a good letter too"), - ), - ), - ); + let input = &[Group::new().element(Level::ERROR.title("foo")).element( + Snippet::source(source) + .line_start(1) + .path("test.rs") + .fold(true) + .annotation( + AnnotationKind::Primary + .span(17..27) + .label("`X` is a good letter"), + ) + .annotation( + AnnotationKind::Context + .span(31..76) + .label("`Y` is a good letter too"), + ), + )]; let expected = str![[r#" error: foo @@ -833,24 +790,22 @@ fn foo() { X3 Y3 Z3 } "#; - let input = Level::ERROR.header("foo").group( - Group::new().element( - Snippet::source(source) - .line_start(1) - .path("test.rs") - .fold(true) - .annotation( - AnnotationKind::Primary - .span(17..73) - .label("`Y` is a good letter"), - ) - .annotation( - AnnotationKind::Context - .span(37..56) - .label("`Z` is a good letter too"), - ), - ), - ); + let input = &[Group::new().element(Level::ERROR.title("foo")).element( + Snippet::source(source) + .line_start(1) + .path("test.rs") + .fold(true) + .annotation( + AnnotationKind::Primary + .span(17..73) + .label("`Y` is a good letter"), + ) + .annotation( + AnnotationKind::Context + .span(37..56) + .label("`Z` is a good letter too"), + ), + )]; let expected = str![[r#" error: foo @@ -887,32 +842,30 @@ fn issue_91334() { fn f(){||yield(((){), "#; - let input = Level::ERROR - .header("this file contains an unclosed delimiter") - .group( - Group::new().element( - Snippet::source(source) - .line_start(1) - .path("$DIR/issue-91334.rs") - .fold(true) - .annotation( - AnnotationKind::Context - .span(151..152) - .label("unclosed delimiter"), - ) - .annotation( - AnnotationKind::Context - .span(159..160) - .label("unclosed delimiter"), - ) - .annotation( - AnnotationKind::Context - .span(164..164) - .label("missing open `(` for this delimiter"), - ) - .annotation(AnnotationKind::Primary.span(167..167)), - ), - ); + let input = &[Group::new() + .element(Level::ERROR.title("this file contains an unclosed delimiter")) + .element( + Snippet::source(source) + .line_start(1) + .path("$DIR/issue-91334.rs") + .fold(true) + .annotation( + AnnotationKind::Context + .span(151..152) + .label("unclosed delimiter"), + ) + .annotation( + AnnotationKind::Context + .span(159..160) + .label("unclosed delimiter"), + ) + .annotation( + AnnotationKind::Context + .span(164..164) + .label("missing open `(` for this delimiter"), + ) + .annotation(AnnotationKind::Primary.span(167..167)), + )]; let expected = str![[r#" error: this file contains an unclosed delimiter --> $DIR/issue-91334.rs:7:23 @@ -958,11 +911,14 @@ fn main() { } } "#; - let input = Level::ERROR - .header("`break` with value from a `while` loop") - .id("E0571") - .group( - Group::new().element( + let input = &[ + Group::new() + .element( + Level::ERROR + .title("`break` with value from a `while` loop") + .id("E0571"), + ) + .element( Snippet::source(source) .line_start(1) .path("$DIR/issue-114529-illegal-break-with-value.rs") @@ -978,21 +934,19 @@ fn main() { .label("you can't `break` with a value in a `while` loop"), ), ), - ) - .group( - Group::new() - .element( - Level::HELP - .title("use `break` on its own without a value inside this `while` loop"), - ) - .element( - Snippet::source(source) - .line_start(1) - .path("$DIR/issue-114529-illegal-break-with-value.rs") - .fold(true) - .annotation(AnnotationKind::Context.span(483..581).label("break")), - ), - ); + Group::new() + .element( + Level::HELP + .title("use `break` on its own without a value inside this `while` loop"), + ) + .element( + Snippet::source(source) + .line_start(1) + .path("$DIR/issue-114529-illegal-break-with-value.rs") + .fold(true) + .annotation(AnnotationKind::Context.span(483..581).label("break")), + ), + ]; let expected = str![[r#" error[E0571]: `break` with value from a `while` loop --> $DIR/issue-114529-illegal-break-with-value.rs:22:9 @@ -1168,11 +1122,14 @@ fn nsize() { } "#; let input = - Level::ERROR - .header("`V0usize` cannot be safely transmuted into `[usize; 2]`") - .id("E0277") - .group( - Group::new().element( + &[ + Group::new() + .element( + Level::ERROR + .title("`V0usize` cannot be safely transmuted into `[usize; 2]`") + .id("E0277"), + ) + .element( Snippet::source(source) .line_start(1) .path("$DIR/primitive_reprs_should_have_correct_length.rs") @@ -1181,27 +1138,25 @@ fn nsize() { "the size of `V0usize` is smaller than the size of `[usize; 2]`", )), ), - ) - .group( - Group::new() - .element(Level::NOTE.title("required by a bound in `is_transmutable`")) - .element( - Snippet::source(source) - .line_start(1) - .path("$DIR/primitive_reprs_should_have_correct_length.rs") - .fold(true) - .annotation( - AnnotationKind::Context - .span(225..240) - .label("required by a bound in this function"), - ) - .annotation( - AnnotationKind::Primary - .span(276..470) - .label("required by this bound in `is_transmutable`"), - ), - ), - ); + Group::new() + .element(Level::NOTE.title("required by a bound in `is_transmutable`")) + .element( + Snippet::source(source) + .line_start(1) + .path("$DIR/primitive_reprs_should_have_correct_length.rs") + .fold(true) + .annotation( + AnnotationKind::Context + .span(225..240) + .label("required by a bound in this function"), + ) + .annotation( + AnnotationKind::Primary + .span(276..470) + .label("required by this bound in `is_transmutable`"), + ), + ), + ]; let expected = str![[r#" error[E0277]: `V0usize` cannot be safely transmuted into `[usize; 2]` --> $DIR/primitive_reprs_should_have_correct_length.rs:144:44 @@ -1254,11 +1209,9 @@ fn main() { assert::is_maybe_transmutable::<&'static [u8; 0], &'static [u16; 0]>(); //~ ERROR `&[u8; 0]` cannot be safely transmuted into `&[u16; 0]` } "#; - let input = Level::ERROR - .header("`&[u8; 0]` cannot be safely transmuted into `&[u16; 0]`") - .id("E027s7") - .group( - Group::new().element( + let input = &[Group::new().element(Level::ERROR + .title("`&[u8; 0]` cannot be safely transmuted into `&[u16; 0]`") + .id("E027s7")).element( Snippet::source(source) .line_start(1) .fold(true) @@ -1268,8 +1221,7 @@ fn main() { .span(442..459) .label("the minimum alignment of `&[u8; 0]` (1) should be greater than that of `&[u16; 0]` (2)") ), - ), - ); + )]; let expected = str![[r#" error[E027s7]: `&[u8; 0]` cannot be safely transmuted into `&[u16; 0]` --> $DIR/align-fail.rs:21:55 @@ -1323,11 +1275,14 @@ fn g() { } fn main() {} "#; - let input = Level::ERROR - .header("expected function, found `{integer}`") - .id("E0618") - .group( - Group::new().element( + let input = + &[Group::new() + .element( + Level::ERROR + .title("expected function, found `{integer}`") + .id("E0618"), + ) + .element( Snippet::source(source) .line_start(1) .path("$DIR/missing-semicolon.rs") @@ -1346,8 +1301,7 @@ fn main() {} "help: consider using a semicolon here to finish the statement: `;`", )) .annotation(AnnotationKind::Primary.span(108..109)), - ), - ); + )]; let expected = str![[r#" error[E0618]: expected function, found `{integer}` --> $DIR/missing-semicolon.rs:5:13 @@ -1414,10 +1368,9 @@ macro_rules! outer_macro { outer_macro!(FirstStruct, FirstAttrStruct); "#; - let input = Level::WARNING - .header("non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module") - .group( - Group::new() + let input = + &[ Group::new().element(Level::WARNING + .title("non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module")) .element( Snippet::source(aux_source) .line_start(1) @@ -1449,8 +1402,6 @@ outer_macro!(FirstStruct, FirstAttrStruct); Level::NOTE .title("a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute") ), - ) - .group( Group::new() .element(Level::NOTE.title("the lint level is defined here")) .element( @@ -1459,8 +1410,7 @@ outer_macro!(FirstStruct, FirstAttrStruct); .path("$DIR/nested-macro-rules.rs") .fold(true) .annotation(AnnotationKind::Primary.span(224..245)), - ), - ); + )]; let expected = str![[r#" warning: non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module --> $DIR/auxiliary/nested-macro-rules.rs:7:9 @@ -1547,29 +1497,30 @@ macro_rules! inline { () => () } "#; - let input = Level::ERROR - .header("can't call method `pow` on ambiguous numeric type `{integer}`") - .id("E0689") - .group( - Group::new().element( + let input = &[ + Group::new() + .element( + Level::ERROR + .title("can't call method `pow` on ambiguous numeric type `{integer}`") + .id("E0689"), + ) + .element( Snippet::source(source) .line_start(1) .path("$DIR/method-on-ambiguous-numeric-type.rs") .fold(true) .annotation(AnnotationKind::Primary.span(916..919)), ), - ) - .group( - Group::new() - .element(Level::HELP.title("you must specify a type for this binding, like `i32`")) - .element( - Snippet::source(aux_source) - .line_start(1) - .path("$DIR/auxiliary/macro-in-other-crate.rs") - .fold(true) - .annotation(AnnotationKind::Context.span(69..69).label(": i32")), - ), - ); + Group::new() + .element(Level::HELP.title("you must specify a type for this binding, like `i32`")) + .element( + Snippet::source(aux_source) + .line_start(1) + .path("$DIR/auxiliary/macro-in-other-crate.rs") + .fold(true) + .annotation(AnnotationKind::Context.span(69..69).label(": i32")), + ), + ]; let expected = str![[r#" error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}` --> $DIR/method-on-ambiguous-numeric-type.rs:37:9 @@ -1611,20 +1562,17 @@ fn courier_to_des_moines_and_points_west(data: &[u32]) -> String { fn main() {} "#; - let input = Level::ERROR - .header("type annotations needed") - .id("E0282") - .group( - Group::new().element( - Snippet::source(source) - .line_start(1) - .path("$DIR/issue-42234-unknown-receiver-type.rs") - .fold(true) - .annotation(AnnotationKind::Primary.span(536..539).label( - "cannot infer type of the type parameter `S` declared on the method `sum`", - )), - ), - ); + let input = &[Group::new() + .element(Level::ERROR.title("type annotations needed").id("E0282")) + .element( + Snippet::source(source) + .line_start(1) + .path("$DIR/issue-42234-unknown-receiver-type.rs") + .fold(true) + .annotation(AnnotationKind::Primary.span(536..539).label( + "cannot infer type of the type parameter `S` declared on the method `sum`", + )), + )]; let expected = str![[r#" error[E0282]: type annotations needed --> $DIR/issue-42234-unknown-receiver-type.rs:15:10 @@ -1717,13 +1665,12 @@ fn nonempty(arrayN_of_empty: [!; N]) { fn main() {} "##; - let input = Level::ERROR - .header( - "non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered" - ) - .id("E0004") - .group( - Group::new().element( + let input = + &[ Group::new().element( Level::ERROR + .title( + "non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered" + ) + .id("E0004")).element( Snippet::source(source) .line_start(1) .path("$DIR/empty-match.rs") @@ -1734,8 +1681,6 @@ fn main() {} .label("patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered") ), ), - ) - .group( Group::new() .element(Level::NOTE.title("`NonEmptyEnum5` defined here")) .element( @@ -1751,9 +1696,8 @@ fn main() {} .annotation(AnnotationKind::Context.span(890..892).label("not covered")) ) .element(Level::NOTE.title("the matched value is of type `NonEmptyEnum5`")) - .element(Level::NOTE.title("match arms with guards don't count towards exhaustivity")) - ) - .group( + .element(Level::NOTE.title("match arms with guards don't count towards exhaustivity") + ), Group::new() .element( Level::HELP @@ -1765,8 +1709,8 @@ fn main() {} .path("$DIR/empty-match.rs") .fold(true) .annotation(AnnotationKind::Context.span(485..485).label(",\n _ => todo!()")) - ) - ); + + )]; let expected = str![[r#" error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered --> $DIR/empty-match.rs:71:24 @@ -1819,11 +1763,9 @@ fn main() { //~^ ERROR must be specified } "#; - let input = Level::ERROR - .header("the trait alias `EqAlias` is not dyn compatible") - .id("E0038") - .group( - Group::new().element( + let input = &[Group::new().element(Level::ERROR + .title("the trait alias `EqAlias` is not dyn compatible") + .id("E0038")).element( Snippet::source(source) .line_start(1) .path("$DIR/object-fail.rs") @@ -1834,8 +1776,6 @@ fn main() { .label("`EqAlias` is not dyn compatible"), ), ), - ) - .group( Group::new() .element( Level::NOTE @@ -1858,8 +1798,7 @@ fn main() { .span(32..39) .label("this trait is not dyn compatible..."), ), - ), - ); + )]; let expected = str![[r#" error[E0038]: the trait alias `EqAlias` is not dyn compatible --> $DIR/object-fail.rs:7:17 @@ -1891,8 +1830,9 @@ const C: u8 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, fn main() {} "#; - let input = Level::ERROR.header("mismatched types").id("E0038").group( - Group::new().element( + let input = &[Group::new() + .element(Level::ERROR.title("mismatched types").id("E0038")) + .element( Snippet::source(source) .path("$DIR/long-span.rs") .fold(true) @@ -1901,8 +1841,7 @@ fn main() {} .span(15..5055) .label("expected `u8`, found `[{integer}; 1680]`"), ), - ), - ); + )]; let expected = str![[r#" error[E0038]: mismatched types --> $DIR/long-span.rs:2:15 @@ -1925,8 +1864,9 @@ const C: u8 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, fn main() {} "#; - let input = Level::ERROR.header("mismatched types").id("E0038").group( - Group::new().element( + let input = &[Group::new() + .element(Level::ERROR.title("mismatched types").id("E0038")) + .element( Snippet::source(source) .path("$DIR/long-span.rs") .fold(true) @@ -1935,8 +1875,7 @@ fn main() {} .span(15..5055) .label("expected `u8`, found `[{integer}; 1680]`"), ), - ), - ); + )]; let expected = str![[r#" error[E0038]: mismatched types ╭▸ $DIR/long-span.rs:2:15 @@ -1960,8 +1899,9 @@ const C: u8 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, fn main() {} "#; - let input = Level::ERROR.header("mismatched types").id("E0038").group( - Group::new().element( + let input = &[Group::new() + .element(Level::ERROR.title("mismatched types").id("E0038")) + .element( Snippet::source(source) .path("$DIR/long-span.rs") .fold(true) @@ -1970,8 +1910,7 @@ fn main() {} .span(15..5055) .label("expected `u8`, found `[{integer}; 1680]`"), ), - ), - ); + )]; let expected = str![[r#" error[E0038]: mismatched types ╭▸ $DIR/long-span.rs:2:15 @@ -1995,8 +1934,9 @@ const C: u8 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, fn main() {} "#; - let input = Level::ERROR.header("mismatched types").id("E0038").group( - Group::new().element( + let input = &[Group::new() + .element(Level::ERROR.title("mismatched types").id("E0038")) + .element( Snippet::source(source) .path("$DIR/long-span.rs") .fold(true) @@ -2005,8 +1945,7 @@ fn main() {} .span(15..5055) .label("expected `u8`, found `[{integer}; 1680]`"), ), - ), - ); + )]; let expected = str![[r#" error[E0038]: mismatched types --> $DIR/long-span.rs:2:15 @@ -2046,10 +1985,8 @@ fn main() { } "#; - let input = Level::ERROR - .header("`Iterator::map` call that discard the iterator's values") - .group( - Group::new() + let input = &[Group::new().element(Level::ERROR + .title("`Iterator::map` call that discard the iterator's values")) .element( Snippet::source(source) .path("$DIR/lint_map_unit_fn.rs") @@ -2071,8 +2008,6 @@ fn main() { ) .element( Level::NOTE.title("`Iterator::map`, like many of the methods on `Iterator`, gets executed lazily, meaning that its effects won't be visible until it is iterated")), - ) - .group( Group::new() .element(Level::HELP.title("you might have meant to use `Iterator::for_each`")) .element( @@ -2080,8 +2015,7 @@ fn main() { .path("$DIR/lint_map_unit_fn.rs") .fold(true) .patch(Patch::new(267..270, r#"for_each"#)), - ), - ); + )]; let expected = str![[r#" error: `Iterator::map` call that discard the iterator's values @@ -2141,27 +2075,25 @@ fn main() { } "#; - let input = Level::ERROR - .header("character constant must be escaped: `\\n`") - .group( - Group::new().element( + let input = &[ + Group::new() + .element(Level::ERROR.title("character constant must be escaped: `\\n`")) + .element( Snippet::source(source) .path("$DIR/bad-char-literals.rs") .fold(true) .annotation(AnnotationKind::Primary.span(204..205)), ), - ) - .group( - Group::new() - .element(Level::HELP.title("escape the character")) - .element( - Snippet::source(source) - .path("$DIR/bad-char-literals.rs") - .line_start(1) - .fold(true) - .patch(Patch::new(204..205, r#"\n"#)), - ), - ); + Group::new() + .element(Level::HELP.title("escape the character")) + .element( + Snippet::source(source) + .path("$DIR/bad-char-literals.rs") + .line_start(1) + .fold(true) + .patch(Patch::new(204..205, r#"\n"#)), + ), + ]; let expected = str![[r#" error: character constant must be escaped: `/n` --> $DIR/bad-char-literals.rs:10:6 @@ -2196,26 +2128,24 @@ fn unclosed_1() { fn main() {} "#; - let input = Level::ERROR - .header("unclosed frontmatter") - .group( - Group::new().element( + let input = &[ + Group::new() + .element(Level::ERROR.title("unclosed frontmatter")) + .element( Snippet::source(source) .path("$DIR/unclosed-1.rs") .fold(true) .annotation(AnnotationKind::Primary.span(0..221)), ), - ) - .group( - Group::new() - .element(Level::NOTE.title("frontmatter opening here was not closed")) - .element( - Snippet::source(source) - .path("$DIR/unclosed-1.rs") - .fold(true) - .annotation(AnnotationKind::Primary.span(0..4)), - ), - ); + Group::new() + .element(Level::NOTE.title("frontmatter opening here was not closed")) + .element( + Snippet::source(source) + .path("$DIR/unclosed-1.rs") + .fold(true) + .annotation(AnnotationKind::Primary.span(0..4)), + ), + ]; let expected = str![[r#" error: unclosed frontmatter --> $DIR/unclosed-1.rs:1:1 @@ -2256,26 +2186,24 @@ fn foo() -> &str { } "#; - let input = Level::ERROR - .header("unclosed frontmatter") - .group( - Group::new().element( + let input = &[ + Group::new() + .element(Level::ERROR.title("unclosed frontmatter")) + .element( Snippet::source(source) .path("$DIR/unclosed-2.rs") .fold(true) .annotation(AnnotationKind::Primary.span(0..377)), ), - ) - .group( - Group::new() - .element(Level::NOTE.title("frontmatter opening here was not closed")) - .element( - Snippet::source(source) - .path("$DIR/unclosed-2.rs") - .fold(true) - .annotation(AnnotationKind::Primary.span(0..4)), - ), - ); + Group::new() + .element(Level::NOTE.title("frontmatter opening here was not closed")) + .element( + Snippet::source(source) + .path("$DIR/unclosed-2.rs") + .fold(true) + .annotation(AnnotationKind::Primary.span(0..4)), + ), + ]; let expected = str![[r#" error: unclosed frontmatter --> $DIR/unclosed-2.rs:1:1 @@ -2318,28 +2246,24 @@ fn foo(x: i32) -> i32 { //~^ ERROR: unexpected closing delimiter: `}` "#; - let input = Level::ERROR - .header("invalid preceding whitespace for frontmatter close") - .group( - Group::new().element( + let input = &[ + Group::new() + .element(Level::ERROR.title("invalid preceding whitespace for frontmatter close")) + .element( Snippet::source(source) .path("$DIR/unclosed-3.rs") .fold(true) .annotation(AnnotationKind::Primary.span(302..310)), ), - ) - .group( - Group::new() - .element( - Level::NOTE.title("frontmatter close should not be preceded by whitespace"), - ) - .element( - Snippet::source(source) - .path("$DIR/unclosed-3.rs") - .fold(true) - .annotation(AnnotationKind::Primary.span(302..306)), - ), - ); + Group::new() + .element(Level::NOTE.title("frontmatter close should not be preceded by whitespace")) + .element( + Snippet::source(source) + .path("$DIR/unclosed-3.rs") + .fold(true) + .annotation(AnnotationKind::Primary.span(302..306)), + ), + ]; let expected = str![[r#" error: invalid preceding whitespace for frontmatter close --> $DIR/unclosed-3.rs:12:1 @@ -2372,26 +2296,24 @@ fn unclosed_4() { fn main() {} "#; - let input = Level::ERROR - .header("unclosed frontmatter") - .group( - Group::new().element( + let input = &[ + Group::new() + .element(Level::ERROR.title("unclosed frontmatter")) + .element( Snippet::source(source) .path("$DIR/unclosed-4.rs") .fold(true) .annotation(AnnotationKind::Primary.span(0..43)), ), - ) - .group( - Group::new() - .element(Level::NOTE.title("frontmatter opening here was not closed")) - .element( - Snippet::source(source) - .path("$DIR/unclosed-4.rs") - .fold(true) - .annotation(AnnotationKind::Primary.span(0..4)), - ), - ); + Group::new() + .element(Level::NOTE.title("frontmatter opening here was not closed")) + .element( + Snippet::source(source) + .path("$DIR/unclosed-4.rs") + .fold(true) + .annotation(AnnotationKind::Primary.span(0..4)), + ), + ]; let expected = str![[r#" error: unclosed frontmatter --> $DIR/unclosed-4.rs:1:1 @@ -2427,26 +2349,24 @@ use std::env; fn main() {} "#; - let input = Level::ERROR - .header("unclosed frontmatter") - .group( - Group::new().element( + let input = &[ + Group::new() + .element(Level::ERROR.title("unclosed frontmatter")) + .element( Snippet::source(source) .path("$DIR/unclosed-5.rs") .fold(true) .annotation(AnnotationKind::Primary.span(0..176)), ), - ) - .group( - Group::new() - .element(Level::NOTE.title("frontmatter opening here was not closed")) - .element( - Snippet::source(source) - .path("$DIR/unclosed-5.rs") - .fold(true) - .annotation(AnnotationKind::Primary.span(0..4)), - ), - ); + Group::new() + .element(Level::NOTE.title("frontmatter opening here was not closed")) + .element( + Snippet::source(source) + .path("$DIR/unclosed-5.rs") + .fold(true) + .annotation(AnnotationKind::Primary.span(0..4)), + ), + ]; let expected = str![[r#" error: unclosed frontmatter @@ -2551,11 +2471,9 @@ pub enum E2 { } "#; - let input = Level::ERROR - .header("expected unit struct, unit variant or constant, found tuple variant `E1::Z1`") - .id(r#"E0532"#) - .group( - Group::new() + let input = &[Group::new().element(Level::ERROR + .title("expected unit struct, unit variant or constant, found tuple variant `E1::Z1`") + .id(r#"E0532"#)) .element( Snippet::source(source) .path("$DIR/pat-tuple-field-count-cross.rs") @@ -2577,8 +2495,6 @@ pub enum E2 { .label("similarly named unit variant `Z0` defined here"), ), ), - ) - .group( Group::new() .element(Level::HELP.title("use the tuple variant pattern syntax instead")) .element( @@ -2587,8 +2503,6 @@ pub enum E2 { .fold(true) .patch(Patch::new(1760..1766, r#"E1::Z1()"#)), ), - ) - .group( Group::new() .element(Level::HELP.title("a unit variant with a similar name exists")) .element( @@ -2596,8 +2510,7 @@ pub enum E2 { .path("$DIR/pat-tuple-field-count-cross.rs") .fold(true) .patch(Patch::new(1764..1766, r#"Z0"#)), - ), - ); + )]; let expected = str![[r#" error[E0532]: expected unit struct, unit variant or constant, found tuple variant `E1::Z1` --> $DIR/pat-tuple-field-count-cross.rs:35:9 @@ -2636,8 +2549,9 @@ fn unterminated_nested_comment() { */ "#; - let input = Level::ERROR.header("unterminated block comment").id("E0758").group( - Group::new().element( + let input = &[Group::new() + .element(Level::ERROR.title("unterminated block comment").id("E0758")) + .element( Snippet::source(source) .path("$DIR/unterminated-nested-comment.rs") .fold(true) @@ -2655,8 +2569,7 @@ fn unterminated_nested_comment() { .label("...and last nested comment terminates here."), ) .annotation(AnnotationKind::Primary.span(0..31)), - ), - ); + )]; let expected = str![[r#" error[E0758]: unterminated block comment @@ -2692,38 +2605,37 @@ fn mismatched_types1() { let s: &str = include_bytes!("file.txt"); //~ ERROR mismatched types }"#; - let input = Level::ERROR.header("mismatched types").id("E0308").group( - Group::new() - .element( - Snippet::source(file_txt_source) - .fold(true) - .line_start(3) - .path("$DIR/file.txt") - .annotation( - AnnotationKind::Primary - .span(0..0) - .label("expected `&[u8]`, found `&str`"), - ), - ) - .element( - Snippet::source(rust_source) - .path("$DIR/mismatched-types.rs") - .fold(true) - .annotation( - AnnotationKind::Context - .span(23..28) - .label("expected due to this"), - ) - .annotation( - AnnotationKind::Context - .span(31..55) - .label("in this macro invocation"), - ), - ) - .element( - Level::NOTE.title("expected reference `&[u8]`\n found reference `&'static str`"), - ), - ); + let input = &[Group::new() + .element(Level::ERROR.title("mismatched types").id("E0308")) + .element( + Snippet::source(file_txt_source) + .fold(true) + .line_start(3) + .path("$DIR/file.txt") + .annotation( + AnnotationKind::Primary + .span(0..0) + .label("expected `&[u8]`, found `&str`"), + ), + ) + .element( + Snippet::source(rust_source) + .path("$DIR/mismatched-types.rs") + .fold(true) + .annotation( + AnnotationKind::Context + .span(23..28) + .label("expected due to this"), + ) + .annotation( + AnnotationKind::Context + .span(31..55) + .label("in this macro invocation"), + ), + ) + .element( + Level::NOTE.title("expected reference `&[u8]`\n found reference `&'static str`"), + )]; let expected = str![[r#" error[E0308]: mismatched types @@ -2755,28 +2667,26 @@ fn mismatched_types2() { let s: &str = include_bytes!("file.txt"); //~ ERROR mismatched types }"#; - let input = Level::ERROR.header("mismatched types").id("E0308").group( - Group::new() - .element( - Snippet::source(source) - .path("$DIR/mismatched-types.rs") - .fold(true) - .annotation( - AnnotationKind::Primary - .span(105..131) - .label("expected `&str`, found `&[u8; 0]`"), - ) - .annotation( - AnnotationKind::Context - .span(98..102) - .label("expected due to this"), - ), - ) - .element( - Level::NOTE - .title("expected reference `&str`\n found reference `&'static [u8; 0]`"), - ), - ); + let input = &[Group::new() + .element(Level::ERROR.title("mismatched types").id("E0308")) + .element( + Snippet::source(source) + .path("$DIR/mismatched-types.rs") + .fold(true) + .annotation( + AnnotationKind::Primary + .span(105..131) + .label("expected `&str`, found `&[u8; 0]`"), + ) + .annotation( + AnnotationKind::Context + .span(98..102) + .label("expected due to this"), + ), + ) + .element( + Level::NOTE.title("expected reference `&str`\n found reference `&'static [u8; 0]`"), + )]; let expected = str![[r#" error[E0308]: mismatched types @@ -2809,11 +2719,10 @@ fn main() { } "#; - let input = Level::ERROR - .header("mismatched types") - .id("E0308") - .group( - Group::new().element( + let input = &[ + Group::new() + .element(Level::ERROR.title("mismatched types").id("E0308")) + .element( Snippet::source(source) .path("$DIR/short-error-format.rs") .fold(true) @@ -2828,18 +2737,16 @@ fn main() { .label("arguments to this function are incorrect"), ), ), - ) - .group( - Group::new() - .element(Level::NOTE.title("function defined here")) - .element( - Snippet::source(source) - .path("$DIR/short-error-format.rs") - .fold(true) - .annotation(AnnotationKind::Context.span(48..54).label("")) - .annotation(AnnotationKind::Primary.span(44..47)), - ), - ); + Group::new() + .element(Level::NOTE.title("function defined here")) + .element( + Snippet::source(source) + .path("$DIR/short-error-format.rs") + .fold(true) + .annotation(AnnotationKind::Context.span(48..54).label("")) + .annotation(AnnotationKind::Primary.span(44..47)), + ), + ]; let expected = str![[r#" $DIR/short-error-format.rs:6:9: error[E0308]: mismatched types: expected `u32`, found `String` @@ -2865,21 +2772,22 @@ fn main() { } "#; - let input = Level::ERROR - .header("no method named `salut` found for type `u32` in the current scope") - .id("E0599") - .group( - Group::new().element( - Snippet::source(source) - .path("$DIR/short-error-format.rs") - .fold(true) - .annotation( - AnnotationKind::Primary - .span(127..132) - .label("method not found in `u32`"), - ), - ), - ); + let input = &[Group::new() + .element( + Level::ERROR + .title("no method named `salut` found for type `u32` in the current scope") + .id("E0599"), + ) + .element( + Snippet::source(source) + .path("$DIR/short-error-format.rs") + .fold(true) + .annotation( + AnnotationKind::Primary + .span(127..132) + .label("method not found in `u32`"), + ), + )]; let expected = str![[r#" $DIR/short-error-format.rs:8:7: error[E0599]: no method named `salut` found for type `u32` in the current scope: method not found in `u32` @@ -2903,43 +2811,37 @@ pub struct Foo; //~^ ERROR let source_1 = r#"/// This is a long line that contains a http://link.com "#; - let input = Level::ERROR - .header("this URL is not a hyperlink") - .group( - Group::new() - .element( - Snippet::source(source_0) - .path("$DIR/diagnostic-width.rs") - .fold(true) - .annotation(AnnotationKind::Primary.span(111..126)), - ) - .element( - Level::NOTE - .title("bare URLs are not automatically turned into clickable links"), - ), - ) - .group( - Group::new() - .element(Level::NOTE.title("the lint level is defined here")) - .element( - Snippet::source(source_0) - .path("$DIR/diagnostic-width.rs") - .fold(true) - .annotation(AnnotationKind::Primary.span(49..67)), - ), - ) - .group( - Group::new() - .element(Level::HELP.title("use an automatic link instead")) - .element( - Snippet::source(source_1) - .path("$DIR/diagnostic-width.rs") - .line_start(4) - .fold(true) - .patch(Patch::new(40..40, "<")) - .patch(Patch::new(55..55, ">")), - ), - ); + let input = &[ + Group::new() + .element(Level::ERROR.title("this URL is not a hyperlink")) + .element( + Snippet::source(source_0) + .path("$DIR/diagnostic-width.rs") + .fold(true) + .annotation(AnnotationKind::Primary.span(111..126)), + ) + .element( + Level::NOTE.title("bare URLs are not automatically turned into clickable links"), + ), + Group::new() + .element(Level::NOTE.title("the lint level is defined here")) + .element( + Snippet::source(source_0) + .path("$DIR/diagnostic-width.rs") + .fold(true) + .annotation(AnnotationKind::Primary.span(49..67)), + ), + Group::new() + .element(Level::HELP.title("use an automatic link instead")) + .element( + Snippet::source(source_1) + .path("$DIR/diagnostic-width.rs") + .line_start(4) + .fold(true) + .patch(Patch::new(40..40, "<")) + .patch(Patch::new(55..55, ">")), + ), + ]; let expected = str![[r#" error: this URL is not a hyperlink @@ -2979,45 +2881,40 @@ fn main() { let long_title2 = "for more information, see "; let long_title3 = "or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value"; - let input = Level::WARNING - .header(long_title1) - .group( - Group::new() - .element( - Snippet::source(source1) - .path("lint_example.rs") - .fold(true) - .annotation(AnnotationKind::Primary.span(40..49)), - ) - .element(Level::WARNING.title("this changes meaning in Rust 2021")) - .element(Level::NOTE.title(long_title2)) - .element(Level::NOTE.title("`#[warn(array_into_iter)]` on by default")), - ) - .group( - Group::new() - .element( - Level::HELP.title("use `.iter()` instead of `.into_iter()` to avoid ambiguity"), - ) - .element( - Snippet::source(source2) - .path("lint_example.rs") - .line_start(3) - .fold(true) - .patch(Patch::new(10..19, "iter")), - ), - ) - .group( - Group::new() - .element(Level::HELP.title(long_title3)) - .element( - Snippet::source(source2) - .path("lint_example.rs") - .line_start(3) - .fold(true) - .patch(Patch::new(0..0, "IntoIterator::into_iter(")) - .patch(Patch::new(9..21, ")")), - ), - ); + let input = &[ + Group::new() + .element(Level::WARNING.title(long_title1)) + .element( + Snippet::source(source1) + .path("lint_example.rs") + .fold(true) + .annotation(AnnotationKind::Primary.span(40..49)), + ) + .element(Level::WARNING.title("this changes meaning in Rust 2021")) + .element(Level::NOTE.title(long_title2)) + .element(Level::NOTE.title("`#[warn(array_into_iter)]` on by default")), + Group::new() + .element( + Level::HELP.title("use `.iter()` instead of `.into_iter()` to avoid ambiguity"), + ) + .element( + Snippet::source(source2) + .path("lint_example.rs") + .line_start(3) + .fold(true) + .patch(Patch::new(10..19, "iter")), + ), + Group::new() + .element(Level::HELP.title(long_title3)) + .element( + Snippet::source(source2) + .path("lint_example.rs") + .line_start(3) + .fold(true) + .patch(Patch::new(0..0, "IntoIterator::into_iter(")) + .patch(Patch::new(9..21, ")")), + ), + ]; let expected = str![[r#" warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021