diff --git a/benches/bench.rs b/benches/bench.rs index d50cf43..c3799fb 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -1,4 +1,4 @@ -use annotate_snippets::{level::Level, AnnotationKind, Group, Renderer, Snippet}; +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; #[divan::bench] fn simple() -> String { @@ -24,7 +24,7 @@ fn simple() -> String { _ => continue, } }"#; - let message = Level::ERROR.message("mismatched types").id("E0308").group( + let message = Level::ERROR.header("mismatched types").id("E0308").group( Group::new().element( Snippet::source(source) .line_start(51) @@ -69,7 +69,7 @@ fn fold(bencher: divan::Bencher<'_, '_>, context: usize) { (input, span) }) .bench_values(|(input, span)| { - let message = Level::ERROR.message("mismatched types").id("E0308").group( + let message = Level::ERROR.header("mismatched types").id("E0308").group( Group::new().element( Snippet::source(&input) .fold(true) diff --git a/examples/custom_error.rs b/examples/custom_error.rs index 4050d40..b9e27b3 100644 --- a/examples/custom_error.rs +++ b/examples/custom_error.rs @@ -1,5 +1,5 @@ use annotate_snippets::renderer::OutputTheme; -use annotate_snippets::{level::Level, AnnotationKind, Group, Renderer, Snippet}; +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; fn main() { let source = r#"//@ compile-flags: -Ztreat-err-as-bug @@ -17,7 +17,7 @@ pub static C: u32 = 0 - 1; "#; let message = Level::ERROR .text(Some("error: internal compiler error")) - .message("could not evaluate static initializer") + .header("could not evaluate static initializer") .id("E0080") .group( Group::new().element( diff --git a/examples/custom_level.rs b/examples/custom_level.rs index 804f774..b2af361 100644 --- a/examples/custom_level.rs +++ b/examples/custom_level.rs @@ -1,5 +1,5 @@ use annotate_snippets::renderer::OutputTheme; -use annotate_snippets::{level::Level, AnnotationKind, Group, Patch, Renderer, Snippet}; +use annotate_snippets::{AnnotationKind, Group, Level, Patch, Renderer, Snippet}; fn main() { let source = r#"// Regression test for issue #114529 @@ -30,7 +30,7 @@ fn main() { } "#; let message = Level::ERROR - .message("`break` with value from a `while` loop") + .header("`break` with value from a `while` loop") .id("E0571") .group( Group::new().element( diff --git a/examples/expected_type.rs b/examples/expected_type.rs index 9a51dce..02abdec 100644 --- a/examples/expected_type.rs +++ b/examples/expected_type.rs @@ -1,4 +1,4 @@ -use annotate_snippets::{level::Level, AnnotationKind, Group, Renderer, Snippet}; +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; fn main() { let source = r#" annotations: vec![SourceAnnotation { @@ -6,7 +6,7 @@ fn main() { , range: <22, 25>,"#; let message = - Level::ERROR.message("expected type, found `22`").group( + Level::ERROR.header("expected type, found `22`").group( Group::new().element( Snippet::source(source) .line_start(26) diff --git a/examples/footer.rs b/examples/footer.rs index d61e84b..ca6f1dc 100644 --- a/examples/footer.rs +++ b/examples/footer.rs @@ -1,8 +1,8 @@ -use annotate_snippets::{level::Level, AnnotationKind, Group, Renderer, Snippet}; +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; fn main() { let message = Level::ERROR - .message("mismatched types") + .header("mismatched types") .id("E0308") .group( Group::new().element( diff --git a/examples/format.rs b/examples/format.rs index 5324413..4b688d4 100644 --- a/examples/format.rs +++ b/examples/format.rs @@ -1,4 +1,4 @@ -use annotate_snippets::{level::Level, AnnotationKind, Group, Renderer, Snippet}; +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; fn main() { let source = r#") -> Option { @@ -23,7 +23,7 @@ fn main() { _ => continue, } }"#; - let message = Level::ERROR.message("mismatched types").id("E0308").group( + let message = Level::ERROR.header("mismatched types").id("E0308").group( Group::new().element( Snippet::source(source) .line_start(51) diff --git a/examples/highlight_source.rs b/examples/highlight_source.rs index 9962542..92d8114 100644 --- a/examples/highlight_source.rs +++ b/examples/highlight_source.rs @@ -1,4 +1,4 @@ -use annotate_snippets::{level::Level, AnnotationKind, Group, Renderer, Snippet}; +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; fn main() { let source = r#"//@ compile-flags: -Z teach @@ -10,7 +10,7 @@ const CON: Vec = vec![1, 2, 3]; //~ ERROR E0010 fn main() {} "#; let message = Level::ERROR - .message("allocations are not allowed in constants") + .header("allocations are not allowed in constants") .id("E0010") .group( Group::new() diff --git a/examples/highlight_title.rs b/examples/highlight_title.rs index e2da54f..12c106a 100644 --- a/examples/highlight_title.rs +++ b/examples/highlight_title.rs @@ -1,4 +1,4 @@ -use annotate_snippets::{level::Level, AnnotationKind, Group, Renderer, Snippet}; +use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet}; use anstyle::Effects; fn main() { @@ -43,7 +43,7 @@ fn main() { magenta.render_reset() ); - let message = Level::ERROR.message("mismatched types").id("E0308").group( + let message = Level::ERROR.header("mismatched types").id("E0308").group( Group::new() .element( Snippet::source(source) diff --git a/examples/multislice.rs b/examples/multislice.rs index ddd938e..a7d340a 100644 --- a/examples/multislice.rs +++ b/examples/multislice.rs @@ -1,7 +1,7 @@ -use annotate_snippets::{level::Level, Annotation, Group, Renderer, Snippet}; +use annotate_snippets::{Annotation, Group, Level, Renderer, Snippet}; fn main() { - let message = Level::ERROR.message("mismatched types").group( + let message = Level::ERROR.header("mismatched types").group( Group::new() .element( Snippet::>::source("Foo") diff --git a/src/level.rs b/src/level.rs index 7f92024..87d1a9f 100644 --- a/src/level.rs +++ b/src/level.rs @@ -1,49 +1,47 @@ +//! [`Level`] constants for easy importing + 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 anstyle::Style; +/// Default `error:` [`Level`] pub const ERROR: Level<'_> = Level { name: None, level: LevelInner::Error, }; +/// Default `warning:` [`Level`] pub const WARNING: Level<'_> = Level { name: None, level: LevelInner::Warning, }; +/// Default `info:` [`Level`] pub const INFO: Level<'_> = Level { name: None, level: LevelInner::Info, }; +/// Default `note:` [`Level`] pub const NOTE: Level<'_> = Level { name: None, level: LevelInner::Note, }; +/// Default `help:` [`Level`] pub const HELP: Level<'_> = Level { name: None, level: LevelInner::Help, }; +/// [`Message`] or [`Title`] severity level #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct Level<'a> { pub(crate) name: Option>, pub(crate) level: LevelInner, } -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub enum Level2<'a> { - Builtin(LevelInner), - Custom { - name: Option<&'a str>, - level: LevelInner, - }, - None, -} - impl<'a> Level<'a> { pub const ERROR: Level<'a> = ERROR; pub const WARNING: Level<'a> = WARNING; @@ -51,9 +49,13 @@ impl<'a> Level<'a> { pub const NOTE: Level<'a> = NOTE; pub const HELP: Level<'a> = HELP; + ///
+ /// /// 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 text(self, text: Option<&'a str>) -> Level<'a> { Level { name: Some(text), @@ -63,24 +65,32 @@ impl<'a> Level<'a> { } impl<'a> Level<'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 message(self, title: &'a str) -> Message<'a> { + /// + ///
+ pub fn header(self, header: &'a str) -> Message<'a> { Message { id: None, groups: vec![Group::new().element(Element::Title(Title { level: self, - title, + title: header, primary: true, }))], } } + ///
+ /// /// Text passed to this function is allowed to be pre-styled, as such all /// text is considered "trusted input" and has no normalizations applied to /// it. [`normalize_untrusted_str`](crate::normalize_untrusted_str) can be /// used to normalize untrusted text before it is passed to this function. + /// + ///
pub fn title(self, title: &'a str) -> Title<'a> { Title { level: self, @@ -107,7 +117,7 @@ impl<'a> Level<'a> { } #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub enum LevelInner { +pub(crate) enum LevelInner { Error, Warning, Info, diff --git a/src/lib.rs b/src/lib.rs index eee2b6f..76836d0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -53,7 +53,8 @@ pub fn normalize_untrusted_str(s: &str) -> String { renderer::normalize_whitespace(s) } +#[doc(inline)] +pub use level::Level; #[doc(inline)] pub use renderer::Renderer; -pub use snippet::ColumnSeparator; pub use snippet::*; diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index 8efcff8..be2abab 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -5,7 +5,7 @@ //! # Example //! ``` //! use annotate_snippets::*; -//! use annotate_snippets::level::Level; +//! use annotate_snippets::Level; //! //! let source = r#" //! use baz::zed::bar; @@ -19,7 +19,7 @@ //! } //! "#; //! Level::ERROR -//! .message("unresolved import `baz::zed`") +//! .header("unresolved import `baz::zed`") //! .id("E0432") //! .group( //! Group::new().element( @@ -101,7 +101,7 @@ impl Renderer { info: BRIGHT_BLUE.effects(Effects::BOLD), note: AnsiColor::BrightGreen.on_default().effects(Effects::BOLD), help: AnsiColor::BrightCyan.on_default().effects(Effects::BOLD), - line_no: BRIGHT_BLUE.effects(Effects::BOLD), + line_num: BRIGHT_BLUE.effects(Effects::BOLD), emphasis: if USE_WINDOWS_COLORS { AnsiColor::BrightWhite.on_default() } else { @@ -178,8 +178,8 @@ impl Renderer { } /// Set the output style for line numbers - pub const fn line_no(mut self, style: Style) -> Self { - self.stylesheet.line_no = style; + pub const fn line_num(mut self, style: Style) -> Self { + self.stylesheet.line_num = style; self } @@ -383,7 +383,7 @@ impl Renderer { self.render_origin(buffer, max_line_num_len, origin); last_was_suggestion = false; } - Element::ColumnSeparator(_) => { + Element::Padding(_) => { self.draw_col_separator_no_space( buffer, buffer.num_lines(), @@ -430,7 +430,7 @@ impl Renderer { let (has_primary_spans, has_span_labels) = next_section.map_or((false, false), |s| match s { - Element::Title(_) | Element::ColumnSeparator(_) => (false, false), + Element::Title(_) | Element::Padding(_) => (false, false), Element::Cause(cause) => ( cause.markers.iter().any(|m| m.kind.is_primary()), cause.markers.iter().any(|m| m.label.is_some()), @@ -1523,7 +1523,7 @@ impl Renderer { } if suggestion.origin != primary_origin { if let Some(origin) = suggestion.origin { - let (loc, _) = sm.span_to_locations(parts[0].range.clone()); + let (loc, _) = sm.span_to_locations(parts[0].span.clone()); // --> file.rs:line:col // | let arrow = self.file_start(); @@ -1563,8 +1563,8 @@ impl Renderer { row_num += 1; } - let file_lines = sm.span_to_lines(parts[0].range.clone()); - let (line_start, line_end) = sm.span_to_locations(parts[0].range.clone()); + let file_lines = sm.span_to_lines(parts[0].span.clone()); + let (line_start, line_end) = sm.span_to_locations(parts[0].span.clone()); let mut lines = complete.lines(); if lines.clone().next().is_none() { // Account for a suggestion to completely remove a line(s) with whitespace (#94192). @@ -1697,8 +1697,8 @@ impl Renderer { // already existing code, despite the colors and UI elements. // We special case `#[derive(_)]\n` and other attribute suggestions, because those // are the ones where context is most useful. - let file_lines = sm.span_to_lines(parts[0].range.end..parts[0].range.end); - let (lo, _) = sm.span_to_locations(parts[0].range.clone()); + let file_lines = sm.span_to_lines(parts[0].span.end..parts[0].span.end); + let (lo, _) = sm.span_to_locations(parts[0].span.clone()); let line_num = lo.line; if let Some(line) = sm.get_line(line_num) { let line = normalize_whitespace(line); @@ -1724,7 +1724,7 @@ impl Renderer { show_code_change { for part in parts { - let (span_start, span_end) = sm.span_to_locations(part.range.clone()); + let (span_start, span_end) = sm.span_to_locations(part.span.clone()); let span_start_pos = span_start.display; let span_end_pos = span_end.display; @@ -1764,7 +1764,7 @@ impl Renderer { let padding: usize = max_line_num_len + 3; for p in underline_start..underline_end { if matches!(show_code_change, DisplaySuggestion::Underline) - && is_different(sm, part.replacement, part.range.clone()) + && is_different(sm, part.replacement, part.span.clone()) { // If this is a replacement, underline with `~`, if this is an addition // underline with `+`. @@ -2665,7 +2665,7 @@ impl ElementStyle { ElementStyle::Addition => stylesheet.addition, ElementStyle::Removal => stylesheet.removal, ElementStyle::LineAndColumn => stylesheet.none, - ElementStyle::LineNumber => stylesheet.line_no, + ElementStyle::LineNumber => stylesheet.line_num, ElementStyle::Quotation => stylesheet.none, ElementStyle::MainHeaderMsg => stylesheet.emphasis, ElementStyle::UnderlinePrimary | ElementStyle::LabelPrimary => level.style(stylesheet), diff --git a/src/renderer/source_map.rs b/src/renderer/source_map.rs index 33fe189..d014bb0 100644 --- a/src/renderer/source_map.rs +++ b/src/renderer/source_map.rs @@ -129,8 +129,8 @@ impl<'a> SourceMap<'a> { let source_len = self.source.len(); if let Some(bigger) = annotations.iter().find_map(|x| { // Allow highlighting one past the last character in the source. - if source_len + 1 < x.range.end { - Some(&x.range) + if source_len + 1 < x.span.end { + Some(&x.span) } else { None } @@ -150,13 +150,13 @@ impl<'a> SourceMap<'a> { let mut multiline_annotations = vec![]; for Annotation { - range, + span, label, kind, highlight_source, } in annotations { - let (lo, mut hi) = self.span_to_locations(range.clone()); + let (lo, mut hi) = self.span_to_locations(span.clone()); // Watch out for "empty spans". If we get a span like 6..6, we // want to just display a `^` at 6, so convert that to @@ -374,13 +374,13 @@ impl<'a> SourceMap<'a> { } // Assumption: all spans are in the same file, and all spans // are disjoint. Sort in ascending order. - patches.sort_by_key(|p| p.range.start); + patches.sort_by_key(|p| p.span.start); // Find the bounding span. - let Some(lo) = patches.iter().map(|p| p.range.start).min() else { + let Some(lo) = patches.iter().map(|p| p.span.start).min() else { return Vec::new(); }; - let Some(hi) = patches.iter().map(|p| p.range.end).max() else { + let Some(hi) = patches.iter().map(|p| p.span.end).max() else { return Vec::new(); }; @@ -410,7 +410,7 @@ impl<'a> SourceMap<'a> { // suggestion and snippet to look as if we just suggested to add // `"b"`, which is typically much easier for the user to understand. part.trim_trivial_replacements(self); - let (cur_lo, cur_hi) = self.span_to_locations(part.range.clone()); + let (cur_lo, cur_hi) = self.span_to_locations(part.span.clone()); if prev_hi.line == cur_lo.line { let mut count = push_trailing(&mut buf, prev_line, &prev_hi, Some(&cur_lo)); while count > 0 { @@ -454,7 +454,7 @@ impl<'a> SourceMap<'a> { _ => 1, }) .sum(); - if !is_different(self, part.replacement, part.range.clone()) { + if !is_different(self, part.replacement, part.span.clone()) { // Account for cases where we are suggesting the same code that's already // there. This shouldn't happen often, but in some cases for multipart // suggestions it's much easier to handle it here than in the origin. diff --git a/src/renderer/styled_buffer.rs b/src/renderer/styled_buffer.rs index 7114683..c9b805a 100644 --- a/src/renderer/styled_buffer.rs +++ b/src/renderer/styled_buffer.rs @@ -2,9 +2,9 @@ //! //! [styled_buffer]: https://github.com/rust-lang/rust/blob/894f7a4ba6554d3797404bbf550d9919df060b97/compiler/rustc_errors/src/styled_buffer.rs -use crate::level::Level; use crate::renderer::stylesheet::Stylesheet; use crate::renderer::ElementStyle; +use crate::Level; use std::fmt; use std::fmt::Write; diff --git a/src/renderer/stylesheet.rs b/src/renderer/stylesheet.rs index 4aa21a5..075cad4 100644 --- a/src/renderer/stylesheet.rs +++ b/src/renderer/stylesheet.rs @@ -7,7 +7,7 @@ pub(crate) struct Stylesheet { pub(crate) info: Style, pub(crate) note: Style, pub(crate) help: Style, - pub(crate) line_no: Style, + pub(crate) line_num: Style, pub(crate) emphasis: Style, pub(crate) none: Style, pub(crate) context: Style, @@ -29,7 +29,7 @@ impl Stylesheet { info: Style::new(), note: Style::new(), help: Style::new(), - line_no: Style::new(), + line_num: Style::new(), emphasis: Style::new(), none: Style::new(), context: Style::new(), diff --git a/src/snippet.rs b/src/snippet.rs index fe1239d..03bfe3d 100644 --- a/src/snippet.rs +++ b/src/snippet.rs @@ -1,7 +1,7 @@ //! Structures used as an input for the library. -use crate::level::Level; use crate::renderer::source_map::SourceMap; +use crate::Level; use std::ops::Range; pub(crate) const ERROR_TXT: &str = "error"; @@ -10,6 +10,7 @@ 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(Debug)] pub struct Message<'a> { pub(crate) id: Option<&'a str>, // for "correctness", could be sloppy and be on Title @@ -17,11 +18,19 @@ pub struct Message<'a> { } 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 = Some(id); self } + /// Add an [`Element`] container pub fn group(mut self, group: Group<'a>) -> Self { self.groups.push(group); self @@ -34,12 +43,12 @@ impl<'a> Message<'a> { v.elements .iter() .map(|s| match s { - Element::Title(_) | Element::Origin(_) | Element::ColumnSeparator(_) => 0, + Element::Title(_) | Element::Origin(_) | Element::Padding(_) => 0, Element::Cause(cause) => { let end = cause .markers .iter() - .map(|a| a.range.end) + .map(|a| a.span.end) .max() .unwrap_or(cause.source.len()) .min(cause.source.len()); @@ -50,7 +59,7 @@ impl<'a> Message<'a> { let end = suggestion .markers .iter() - .map(|a| a.range.end) + .map(|a| a.span.end) .max() .unwrap_or(suggestion.source.len()) .min(suggestion.source.len()); @@ -66,6 +75,7 @@ impl<'a> Message<'a> { } } +/// An [`Element`] container #[derive(Debug)] pub struct Group<'a> { pub(crate) elements: Vec>, @@ -97,6 +107,7 @@ impl<'a> Group<'a> { } } +/// A section of content within a [`Group`] #[derive(Debug)] #[non_exhaustive] pub enum Element<'a> { @@ -104,7 +115,7 @@ pub enum Element<'a> { Cause(Snippet<'a, Annotation<'a>>), Suggestion(Snippet<'a, Patch<'a>>), Origin(Origin<'a>), - ColumnSeparator(ColumnSeparator), + Padding(Padding), } impl<'a> From> for Element<'a> { @@ -131,15 +142,19 @@ impl<'a> From> for Element<'a> { } } -impl From for Element<'_> { - fn from(value: ColumnSeparator) -> Self { - Self::ColumnSeparator(value) +impl From for Element<'_> { + fn from(value: Padding) -> Self { + Self::Padding(value) } } +/// A whitespace [`Element`] in a [`Group`] #[derive(Debug)] -pub struct ColumnSeparator; +pub struct Padding; +/// A text [`Element`] in a [`Group`] +/// +/// See [`Level::title`] to create this. #[derive(Debug)] pub struct Title<'a> { pub(crate) level: Level<'a>, @@ -154,6 +169,7 @@ impl Title<'_> { } } +/// A source view [`Element`] in a [`Group`] #[derive(Debug)] pub struct Snippet<'a, T> { pub(crate) origin: Option<&'a str>, @@ -164,9 +180,15 @@ pub struct Snippet<'a, T> { } impl<'a, T: Clone> Snippet<'a, T> { + /// The source code to be rendered + /// + ///
+ /// /// 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 source(source: &'a str) -> Self { Self { origin: None, @@ -177,19 +199,28 @@ impl<'a, T: Clone> Snippet<'a, T> { } } + /// When manually [`fold`][Self::fold]ing, + /// the [`source`][Self::source]s line offset from the original start pub fn line_start(mut self, line_start: usize) -> Self { self.line_start = line_start; self } + /// The location of the [`source`][Self::source] (e.g. a path) + /// + ///
+ /// /// 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 origin(mut self, origin: &'a str) -> Self { self.origin = Some(origin); self } + /// Hide lines without [`Annotation`]s pub fn fold(mut self, fold: bool) -> Self { self.fold = fold; self @@ -197,11 +228,13 @@ impl<'a, T: Clone> Snippet<'a, T> { } impl<'a> Snippet<'a, Annotation<'a>> { + /// Highlight and describe a span of text within the [`source`][Self::source] pub fn annotation(mut self, annotation: Annotation<'a>) -> Snippet<'a, Annotation<'a>> { self.markers.push(annotation); self } + /// Highlight and describe spans of text within the [`source`][Self::source] pub fn annotations(mut self, annotation: impl IntoIterator>) -> Self { self.markers.extend(annotation); self @@ -209,40 +242,55 @@ impl<'a> Snippet<'a, Annotation<'a>> { } impl<'a> Snippet<'a, Patch<'a>> { + /// Suggest to the user an edit to the [`source`][Self::source] pub fn patch(mut self, patch: Patch<'a>) -> Snippet<'a, Patch<'a>> { self.markers.push(patch); self } + /// Suggest to the user edits to the [`source`][Self::source] pub fn patches(mut self, patches: impl IntoIterator>) -> Self { self.markers.extend(patches); self } } +/// Highlighted and describe a span of text within a [`Snippet`] +/// +/// See [`AnnotationKind`] to create an annotation. #[derive(Clone, Debug)] pub struct Annotation<'a> { - pub(crate) range: Range, + pub(crate) span: Range, pub(crate) label: Option<&'a str>, pub(crate) kind: AnnotationKind, pub(crate) highlight_source: bool, } impl<'a> Annotation<'a> { + /// Describe the reason the span is highlighted + /// + /// This will be styled according to the [`AnnotationKind`] + /// + ///
+ /// /// 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 label(mut self, label: &'a str) -> Self { self.label = Some(label); self } + /// Style the source according to the [`AnnotationKind`] pub fn highlight_source(mut self, highlight_source: bool) -> Self { self.highlight_source = highlight_source; self } } +/// The category of the [`Annotation`] #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum AnnotationKind { /// Color to [`Message`]'s [`Level`] @@ -254,7 +302,7 @@ pub enum AnnotationKind { impl AnnotationKind { pub fn span<'a>(self, span: Range) -> Annotation<'a> { Annotation { - range: span, + span, label: None, kind: self, highlight_source: false, @@ -266,18 +314,25 @@ impl AnnotationKind { } } +/// Suggested edit to the [`Snippet`] #[derive(Clone, Debug)] pub struct Patch<'a> { - pub(crate) range: Range, + pub(crate) span: Range, pub(crate) replacement: &'a str, } impl<'a> Patch<'a> { + /// Splice `replacement` into the [`Snippet`] at the `span` + /// + ///
+ /// /// 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 new(range: Range, replacement: &'a str) -> Self { - Self { range, replacement } + /// + ///
+ pub fn new(span: Range, replacement: &'a str) -> Self { + Self { span, replacement } } pub(crate) fn is_addition(&self, sm: &SourceMap<'_>) -> bool { @@ -299,7 +354,7 @@ impl<'a> Patch<'a> { pub(crate) fn is_destructive_replacement(&self, sm: &SourceMap<'_>) -> bool { self.is_replacement(sm) && !sm - .span_to_snippet(self.range.clone()) + .span_to_snippet(self.span.clone()) // This should use `is_some_and` when our MSRV is >= 1.70 .map_or(false, |s| { as_substr(s.trim(), self.replacement.trim()).is_some() @@ -307,8 +362,8 @@ impl<'a> Patch<'a> { } fn replaces_meaningful_content(&self, sm: &SourceMap<'_>) -> bool { - sm.span_to_snippet(self.range.clone()) - .map_or(!self.range.is_empty(), |snippet| !snippet.trim().is_empty()) + sm.span_to_snippet(self.span.clone()) + .map_or(!self.span.is_empty(), |snippet| !snippet.trim().is_empty()) } /// Try to turn a replacement into an addition when the span that is being @@ -317,17 +372,18 @@ impl<'a> Patch<'a> { if self.replacement.is_empty() { return; } - let Some(snippet) = sm.span_to_snippet(self.range.clone()) else { + let Some(snippet) = sm.span_to_snippet(self.span.clone()) else { return; }; if let Some((prefix, substr, suffix)) = as_substr(snippet, self.replacement) { - self.range = self.range.start + prefix..self.range.end.saturating_sub(suffix); + self.span = self.span.start + prefix..self.span.end.saturating_sub(suffix); self.replacement = substr; } } } +/// The location of the [`Snippet`] (e.g. a path) #[derive(Clone, Debug)] pub struct Origin<'a> { pub(crate) origin: &'a str, @@ -338,9 +394,13 @@ pub struct Origin<'a> { } impl<'a> Origin<'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 new(origin: &'a str) -> Self { Self { origin, @@ -351,11 +411,17 @@ impl<'a> Origin<'a> { } } + /// Set the default line number to display + /// + /// Otherwise this will be inferred from the primary [`Annotation`] pub fn line(mut self, line: usize) -> Self { self.line = Some(line); self } + /// Set the default column to display + /// + /// Otherwise this will be inferred from the primary [`Annotation`] pub fn char_column(mut self, char_column: usize) -> Self { self.char_column = Some(char_column); self @@ -366,9 +432,15 @@ impl<'a> Origin<'a> { self } + /// Like [`Annotation::label`], but when there is no source + /// + ///
+ /// /// 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 label(mut self, label: &'a str) -> Self { self.label = Some(label); self diff --git a/tests/fixtures/color/ann_eof.toml b/tests/fixtures/color/ann_eof.toml index ac129f3..ef711de 100644 --- a/tests/fixtures/color/ann_eof.toml +++ b/tests/fixtures/color/ann_eof.toml @@ -1,6 +1,6 @@ [message] level = "Error" -title = "expected `.`, `=`" +header = "expected `.`, `=`" [[message.sections]] type = "Cause" diff --git a/tests/fixtures/color/ann_insertion.toml b/tests/fixtures/color/ann_insertion.toml index 13bc13c..30af1bf 100644 --- a/tests/fixtures/color/ann_insertion.toml +++ b/tests/fixtures/color/ann_insertion.toml @@ -1,6 +1,6 @@ [message] level = "Error" -title = "expected `.`, `=`" +header = "expected `.`, `=`" [[message.sections]] type = "Cause" diff --git a/tests/fixtures/color/ann_multiline.toml b/tests/fixtures/color/ann_multiline.toml index 722c3e1..2a5f206 100644 --- a/tests/fixtures/color/ann_multiline.toml +++ b/tests/fixtures/color/ann_multiline.toml @@ -1,7 +1,7 @@ [message] level = "Error" id = "E0027" -title = "pattern does not mention fields `lineno`, `content`" +header = "pattern does not mention fields `lineno`, `content`" [[message.sections]] type = "Cause" diff --git a/tests/fixtures/color/ann_multiline2.toml b/tests/fixtures/color/ann_multiline2.toml index 329beb4..854b38a 100644 --- a/tests/fixtures/color/ann_multiline2.toml +++ b/tests/fixtures/color/ann_multiline2.toml @@ -1,7 +1,7 @@ [message] level = "Error" id = "E####" -title = "spacing error found" +header = "spacing error found" [[message.sections]] type = "Cause" diff --git a/tests/fixtures/color/ann_removed_nl.toml b/tests/fixtures/color/ann_removed_nl.toml index 8ed96bc..6ffeb7a 100644 --- a/tests/fixtures/color/ann_removed_nl.toml +++ b/tests/fixtures/color/ann_removed_nl.toml @@ -1,6 +1,6 @@ [message] level = "Error" -title = "expected `.`, `=`" +header = "expected `.`, `=`" [[message.sections]] type = "Cause" diff --git a/tests/fixtures/color/ensure-emoji-highlight-width.toml b/tests/fixtures/color/ensure-emoji-highlight-width.toml index 8d7a14a..669959f 100644 --- a/tests/fixtures/color/ensure-emoji-highlight-width.toml +++ b/tests/fixtures/color/ensure-emoji-highlight-width.toml @@ -1,5 +1,5 @@ [message] -title = "invalid character ` ` in package name: `haha this isn't a valid name 🐛`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters)" +header = "invalid character ` ` in package name: `haha this isn't a valid name 🐛`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters)" level = "Error" diff --git a/tests/fixtures/color/fold_ann_multiline.toml b/tests/fixtures/color/fold_ann_multiline.toml index 745ef42..2cee27d 100644 --- a/tests/fixtures/color/fold_ann_multiline.toml +++ b/tests/fixtures/color/fold_ann_multiline.toml @@ -1,7 +1,7 @@ [message] level = "Error" id = "E0308" -title = "mismatched types" +header = "mismatched types" [[message.sections]] type = "Cause" diff --git a/tests/fixtures/color/fold_bad_origin_line.toml b/tests/fixtures/color/fold_bad_origin_line.toml index 3b0d827..2fab2d6 100644 --- a/tests/fixtures/color/fold_bad_origin_line.toml +++ b/tests/fixtures/color/fold_bad_origin_line.toml @@ -1,6 +1,6 @@ [message] level = "Error" -title = "" +header = "" [[message.sections]] type = "Cause" diff --git a/tests/fixtures/color/fold_leading.toml b/tests/fixtures/color/fold_leading.toml index 564187b..0ef043c 100644 --- a/tests/fixtures/color/fold_leading.toml +++ b/tests/fixtures/color/fold_leading.toml @@ -1,7 +1,7 @@ [message] level = "Error" id = "E0308" -title = "invalid type: integer `20`, expected a bool" +header = "invalid type: integer `20`, expected a bool" [[message.sections]] type = "Cause" diff --git a/tests/fixtures/color/fold_trailing.toml b/tests/fixtures/color/fold_trailing.toml index eea6365..91e4ab4 100644 --- a/tests/fixtures/color/fold_trailing.toml +++ b/tests/fixtures/color/fold_trailing.toml @@ -1,7 +1,7 @@ [message] level = "Error" id = "E0308" -title = "invalid type: integer `20`, expected a lints table" +header = "invalid type: integer `20`, expected a lints table" [[message.sections]] type = "Cause" diff --git a/tests/fixtures/color/issue_9.toml b/tests/fixtures/color/issue_9.toml index 96ad2c0..f423915 100644 --- a/tests/fixtures/color/issue_9.toml +++ b/tests/fixtures/color/issue_9.toml @@ -1,6 +1,6 @@ [message] level = "Error" -title = "expected one of `.`, `;`, `?`, or an operator, found `for`" +header = "expected one of `.`, `;`, `?`, or an operator, found `for`" [[message.sections]] type = "Cause" diff --git a/tests/fixtures/color/multiple_annotations.toml b/tests/fixtures/color/multiple_annotations.toml index f4c90a4..367c53e 100644 --- a/tests/fixtures/color/multiple_annotations.toml +++ b/tests/fixtures/color/multiple_annotations.toml @@ -1,6 +1,6 @@ [message] level = "Error" -title = "" +header = "" [[message.sections]] type = "Cause" diff --git a/tests/fixtures/color/simple.toml b/tests/fixtures/color/simple.toml index b70f11c..d5a3647 100644 --- a/tests/fixtures/color/simple.toml +++ b/tests/fixtures/color/simple.toml @@ -1,6 +1,6 @@ [message] level = "Error" -title = "expected one of `.`, `;`, `?`, or an operator, found `for`" +header = "expected one of `.`, `;`, `?`, or an operator, found `for`" [[message.sections]] type = "Cause" diff --git a/tests/fixtures/color/strip_line.toml b/tests/fixtures/color/strip_line.toml index d7af686..18a7805 100644 --- a/tests/fixtures/color/strip_line.toml +++ b/tests/fixtures/color/strip_line.toml @@ -1,7 +1,7 @@ [message] level = "Error" id = "E0308" -title = "mismatched types" +header = "mismatched types" [[message.sections]] type = "Cause" diff --git a/tests/fixtures/color/strip_line_char.toml b/tests/fixtures/color/strip_line_char.toml index 6585005..3174ced 100644 --- a/tests/fixtures/color/strip_line_char.toml +++ b/tests/fixtures/color/strip_line_char.toml @@ -1,7 +1,7 @@ [message] level = "Error" id = "E0308" -title = "mismatched types" +header = "mismatched types" [[message.sections]] type = "Cause" diff --git a/tests/fixtures/color/strip_line_non_ws.toml b/tests/fixtures/color/strip_line_non_ws.toml index 1f085b5..b7844ec 100644 --- a/tests/fixtures/color/strip_line_non_ws.toml +++ b/tests/fixtures/color/strip_line_non_ws.toml @@ -1,7 +1,7 @@ [message] level = "Error" id = "E0308" -title = "mismatched types" +header = "mismatched types" [[message.sections]] type = "Cause" diff --git a/tests/fixtures/deserialize.rs b/tests/fixtures/deserialize.rs index 8f45b36..2042966 100644 --- a/tests/fixtures/deserialize.rs +++ b/tests/fixtures/deserialize.rs @@ -3,7 +3,7 @@ use std::ops::Range; use annotate_snippets::renderer::DEFAULT_TERM_WIDTH; use annotate_snippets::{ - level::Level, Annotation, AnnotationKind, Element, Group, Message, Patch, Renderer, Snippet, + Annotation, AnnotationKind, Element, Group, Level, Message, Patch, Renderer, Snippet, }; #[derive(Deserialize)] @@ -16,7 +16,7 @@ pub(crate) struct Fixture { #[derive(Deserialize)] pub struct MessageDef { pub level: LevelDef, - pub title: String, + pub header: String, #[serde(default)] pub id: Option, #[serde(default)] @@ -27,11 +27,11 @@ impl<'a> From<&'a MessageDef> for Message<'a> { fn from(val: &'a MessageDef) -> Self { let MessageDef { level, - title, + header, id, sections, } = val; - let mut message = Level::from(level).message(title); + let mut message = Level::from(level).header(header); if let Some(id) = id { message = message.id(id); } diff --git a/tests/formatter.rs b/tests/formatter.rs index 3f0e7cd..75cf853 100644 --- a/tests/formatter.rs +++ b/tests/formatter.rs @@ -1,13 +1,11 @@ -use annotate_snippets::{ - level::Level, Annotation, AnnotationKind, Group, Patch, Renderer, Snippet, -}; +use annotate_snippets::{Annotation, AnnotationKind, Group, Level, Patch, Renderer, Snippet}; use annotate_snippets::renderer::OutputTheme; use snapbox::{assert_data_eq, str}; #[test] fn test_i_29() { - let snippets = Level::ERROR.message("oops").group( + let snippets = Level::ERROR.header("oops").group( Group::new().element( Snippet::source("First line\r\nSecond oops line") .origin("") @@ -29,7 +27,7 @@ error: oops #[test] fn test_point_to_double_width_characters() { - let snippets = Level::ERROR.message("").group( + let snippets = Level::ERROR.header("").group( Group::new().element( Snippet::source("こんにちは、世界") .origin("") @@ -51,7 +49,7 @@ error: #[test] fn test_point_to_double_width_characters_across_lines() { - let snippets = Level::ERROR.message("").group( + let snippets = Level::ERROR.header("").group( Group::new().element( Snippet::source("おはよう\nございます") .origin("") @@ -75,7 +73,7 @@ error: #[test] fn test_point_to_double_width_characters_multiple() { - let snippets = Level::ERROR.message("").group( + let snippets = Level::ERROR.header("").group( Group::new().element( Snippet::source("お寿司\n食べたい🍣") .origin("") @@ -100,7 +98,7 @@ error: #[test] fn test_point_to_double_width_characters_mixed() { - let snippets = Level::ERROR.message("").group( + let snippets = Level::ERROR.header("").group( Group::new().element( Snippet::source("こんにちは、新しいWorld!") .origin("") @@ -122,7 +120,7 @@ error: #[test] fn test_format_title() { - let input = Level::ERROR.message("This is a title").id("E0001"); + let input = Level::ERROR.header("This is a title").id("E0001"); let expected = str![r#"error[E0001]: This is a title"#]; let renderer = Renderer::plain(); @@ -133,7 +131,7 @@ fn test_format_title() { fn test_format_snippet_only() { let source = "This is line 1\nThis is line 2"; let input = Level::ERROR - .message("") + .header("") .group(Group::new().element(Snippet::>::source(source).line_start(5402))); let expected = str![[r#" @@ -150,7 +148,7 @@ error: fn test_format_snippets_continuation() { let src_0 = "This is slice 1"; let src_1 = "This is slice 2"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new() .element( Snippet::>::source(src_0) @@ -184,7 +182,7 @@ 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.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(&source).line_start(5402).annotation( AnnotationKind::Context @@ -207,7 +205,7 @@ error: #[test] fn test_format_footer_title() { let input = Level::ERROR - .message("") + .header("") .group(Group::new().element(Level::ERROR.title("This __is__ a title"))); let expected = str![[r#" error: @@ -223,7 +221,7 @@ error: fn test_i26() { let source = "short"; let label = "label"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source).line_start(0).annotation( AnnotationKind::Primary @@ -240,7 +238,7 @@ fn test_i26() { fn test_source_content() { let source = "This is an example\nof content lines"; let input = Level::ERROR - .message("") + .header("") .group(Group::new().element(Snippet::>::source(source).line_start(56))); let expected = str![[r#" error: @@ -255,7 +253,7 @@ error: #[test] fn test_source_annotation_standalone_singleline() { let source = "tests"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -275,7 +273,7 @@ error: #[test] fn test_source_annotation_standalone_multiline() { let source = "tests"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -299,7 +297,7 @@ error: #[test] fn test_only_source() { let input = Level::ERROR - .message("") + .header("") .group(Group::new().element(Snippet::>::source("").origin("file.rs"))); let expected = str![[r#" error: @@ -314,7 +312,7 @@ error: fn test_anon_lines() { let source = "This is an example\nof content lines\n\nabc"; let input = Level::ERROR - .message("") + .header("") .group(Group::new().element(Snippet::>::source(source).line_start(56))); let expected = str![[r#" error: @@ -330,7 +328,7 @@ LL | abc #[test] fn issue_130() { - let input = Level::ERROR.message("dummy").group( + let input = Level::ERROR.header("dummy").group( Group::new().element( Snippet::source("foo\nbar\nbaz") .origin("file/path") @@ -358,7 +356,7 @@ fn unterminated_string_multiline() { a\" // ... "; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -382,7 +380,7 @@ error: #[test] fn char_and_nl_annotate_char() { let source = "a\r\nb"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -405,7 +403,7 @@ error: #[test] fn char_eol_annotate_char() { let source = "a\r\nb"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -427,7 +425,7 @@ error: #[test] fn char_eol_annotate_char_double_width() { - let snippets = Level::ERROR.message("").group( + let snippets = Level::ERROR.header("").group( Group::new().element( Snippet::source("こん\r\nにちは\r\n世界") .origin("") @@ -452,7 +450,7 @@ error: #[test] fn annotate_eol() { let source = "a\r\nb"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -475,7 +473,7 @@ error: #[test] fn annotate_eol2() { let source = "a\r\nb"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -498,7 +496,7 @@ error: #[test] fn annotate_eol3() { let source = "a\r\nb"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -521,7 +519,7 @@ error: #[test] fn annotate_eol4() { let source = "a\r\nb"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -543,7 +541,7 @@ error: #[test] fn annotate_eol_double_width() { - let snippets = Level::ERROR.message("").group( + let snippets = Level::ERROR.header("").group( Group::new().element( Snippet::source("こん\r\nにちは\r\n世界") .origin("") @@ -568,7 +566,7 @@ error: #[test] fn multiline_eol_start() { let source = "a\r\nb"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -592,7 +590,7 @@ error: #[test] fn multiline_eol_start2() { let source = "a\r\nb"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -616,7 +614,7 @@ error: #[test] fn multiline_eol_start3() { let source = "a\nb"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -639,7 +637,7 @@ error: #[test] fn multiline_eol_start_double_width() { - let snippets = Level::ERROR.message("").group( + let snippets = Level::ERROR.header("").group( Group::new().element( Snippet::source("こん\r\nにちは\r\n世界") .origin("") @@ -665,7 +663,7 @@ error: #[test] fn multiline_eol_start_eol_end() { let source = "a\nb\nc"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -690,7 +688,7 @@ error: #[test] fn multiline_eol_start_eol_end2() { let source = "a\r\nb\r\nc"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -715,7 +713,7 @@ error: #[test] fn multiline_eol_start_eol_end3() { let source = "a\r\nb\r\nc"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -740,7 +738,7 @@ error: #[test] fn multiline_eol_start_eof_end() { let source = "a\r\nb"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -764,7 +762,7 @@ error: #[test] fn multiline_eol_start_eof_end_double_width() { let source = "ん\r\nに"; - let input = Level::ERROR.message("").group( + let input = Level::ERROR.header("").group( Group::new().element( Snippet::source(source) .origin("file/path") @@ -788,7 +786,7 @@ error: #[test] fn two_single_line_same_line() { let source = r#"bar = { version = "0.1.0", optional = true }"#; - let input = Level::ERROR.message("unused optional dependency").group( + let input = Level::ERROR.header("unused optional dependency").group( Group::new().element( Snippet::source(source) .origin("Cargo.toml") @@ -825,7 +823,7 @@ this is another line so is this bar = { version = "0.1.0", optional = true } "#; - let input = Level::ERROR.message("unused optional dependency").group( + let input = Level::ERROR.header("unused optional dependency").group( Group::new().element( Snippet::source(source) .line_start(4) @@ -864,7 +862,7 @@ this is another line so is this bar = { version = "0.1.0", optional = true } "#; - let input = Level::ERROR.message("unused optional dependency").group( + let input = Level::ERROR.header("unused optional dependency").group( Group::new().element( Snippet::source(source) .line_start(4) @@ -912,7 +910,7 @@ so is this bar = { version = "0.1.0", optional = true } this is another line "#; - let input = Level::ERROR.message("unused optional dependency").group( + let input = Level::ERROR.header("unused optional dependency").group( Group::new().element( Snippet::source(source) .line_start(4) @@ -963,7 +961,7 @@ error: unused optional dependency #[test] fn origin_correct_start_line() { let source = "aaa\nbbb\nccc\nddd\n"; - let input = Level::ERROR.message("title").group( + let input = Level::ERROR.header("title").group( Group::new().element( Snippet::source(source) .origin("origin.txt") @@ -989,7 +987,7 @@ error: title #[test] fn origin_correct_mid_line() { let source = "aaa\nbbb\nccc\nddd\n"; - let input = Level::ERROR.message("title").group( + let input = Level::ERROR.header("title").group( Group::new().element( Snippet::source(source) .origin("origin.txt") @@ -1020,7 +1018,7 @@ error: title fn two_suggestions_same_span() { let source = r#" A.foo();"#; let input_new = Level::ERROR - .message("expected value, found enum `A`") + .header("expected value, found enum `A`") .id("E0423") .group( Group::new().element( @@ -1088,7 +1086,7 @@ fn main() { }"#; let input_new = Level::ERROR - .message("no method named `pick` found for struct `Chaenomeles` in the current scope") + .header("no method named `pick` found for struct `Chaenomeles` in the current scope") .id("E0599") .group( Group::new().element( @@ -1148,7 +1146,7 @@ fn single_line_non_overlapping_suggestions() { let source = r#" A.foo();"#; let input_new = Level::ERROR - .message("expected value, found enum `A`") + .header("expected value, found enum `A`") .id("E0423") .group( Group::new().element( @@ -1190,7 +1188,7 @@ LL + (A::Tuple()).bar(); fn single_line_non_overlapping_suggestions2() { let source = r#" ThisIsVeryLong.foo();"#; let input_new = Level::ERROR - .message("Found `ThisIsVeryLong`") + .header("Found `ThisIsVeryLong`") .id("E0423") .group( Group::new().element( @@ -1239,7 +1237,7 @@ fn multiple_replacements() { "#; let input_new = Level::ERROR - .message("cannot borrow `*self` as mutable because it is also borrowed as immutable") + .header("cannot borrow `*self` as mutable because it is also borrowed as immutable") .id("E0502") .group( Group::new().element( @@ -1323,7 +1321,7 @@ fn main() { }"#; let input_new = Level::ERROR - .message("cannot borrow `chars` as mutable more than once at a time") + .header("cannot borrow `chars` as mutable more than once at a time") .id("E0499") .group( Group::new().element( @@ -1407,7 +1405,7 @@ struct Foo { fn main() {}"#; let input_new = Level::ERROR - .message("failed to resolve: use of undeclared crate or module `st`") + .header("failed to resolve: use of undeclared crate or module `st`") .id("E0433") .group( Group::new().element( @@ -1489,7 +1487,7 @@ where fn main() {}"#; let input_new = Level::ERROR - .message("the size for values of type `T` cannot be known at compilation time") + .header("the size for values of type `T` cannot be known at compilation time") .id("E0277") .group( Group::new().element( @@ -1558,7 +1556,7 @@ and where fn main() {}"#; let input_new = Level::ERROR - .message("the size for values of type `T` cannot be known at compilation time") + .header("the size for values of type `T` cannot be known at compilation time") .id("E0277") .group(Group::new().element(Snippet::source(source) .line_start(1) @@ -1663,7 +1661,7 @@ zappy "#; let input_new = Level::ERROR - .message("the size for values of type `T` cannot be known at compilation time") + .header("the size for values of type `T` cannot be known at compilation time") .id("E0277") .group( Group::new() @@ -1731,7 +1729,7 @@ fn main() { "#; let input_new = Level::ERROR - .message("type mismatch resolving `>, ...>>, ...>>, ...> as Future>::Error == Foo`") + .header("type mismatch resolving `>, ...>>, ...>>, ...> as Future>::Error == Foo`") .id("E0271") .group(Group::new().element(Snippet::source(source) .line_start(4) @@ -1819,7 +1817,7 @@ fn main() { "#; let input_new = Level::ERROR - .message("type mismatch resolving `>, ...>>, ...>>, ...> as Future>::Error == Foo`") + .header("type mismatch resolving `>, ...>>, ...>>, ...> as Future>::Error == Foo`") .id("E0271") .group(Group::new().element(Snippet::source(source) .line_start(4) @@ -1972,7 +1970,7 @@ fn main() { "#; let input_new = Level::ERROR - .message("mismatched types") + .header("mismatched types") .id("E0308") .group(Group::new().element( Snippet::source(source) @@ -2056,7 +2054,7 @@ fn main() { "#; let input_new = Level::ERROR - .message("mismatched types") + .header("mismatched types") .id("E0308") .group(Group::new().element( Snippet::source(source) @@ -2124,7 +2122,7 @@ 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.message("title").group( + let input = Level::ERROR.header("title").group( Group::new().element( Snippet::source(source) .fold(false) @@ -2150,7 +2148,7 @@ error: title fn unicode_cut_handling2() { let source = "/*这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/?"; let input = Level::ERROR - .message("expected item, found `?`") + .header("expected item, found `?`") .group( Group::new().element( Snippet::source(source) @@ -2177,7 +2175,7 @@ error: expected item, found `?` fn unicode_cut_handling3() { let source = "/*这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。这是宽的。*/?"; let input = Level::ERROR - .message("expected item, found `?`") + .header("expected item, found `?`") .group( Group::new().element( Snippet::source(source) @@ -2204,7 +2202,7 @@ error: expected item, found `?` fn unicode_cut_handling4() { let source = "/*aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa*/?"; let input = Level::ERROR - .message("expected item, found `?`") + .header("expected item, found `?`") .group( Group::new().element( Snippet::source(source) @@ -2236,7 +2234,7 @@ fn main() { //~^ ERROR mismatched types } "##; - let input = Level::ERROR.message("mismatched types").id("E0308").group( + let input = Level::ERROR.header("mismatched types").id("E0308").group( Group::new().element( Snippet::source(source) .origin("$DIR/non-whitespace-trimming-unicode.rs") @@ -2281,7 +2279,7 @@ fn main() { } "##; let input = Level::ERROR - .message("cannot add `&str` to `&str`") + .header("cannot add `&str` to `&str`") .id("E0369") .group( Group::new() @@ -2348,7 +2346,7 @@ 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 - .message("couldn't read `$DIR/not-utf8.bin`: stream did not contain valid UTF-8") + .header("couldn't read `$DIR/not-utf8.bin`: stream did not contain valid UTF-8") .group( Group::new().element( Snippet::source(source) diff --git a/tests/rustc_tests.rs b/tests/rustc_tests.rs index 7a795db..6998629 100644 --- a/tests/rustc_tests.rs +++ b/tests/rustc_tests.rs @@ -2,7 +2,7 @@ //! //! [parser-tests]: https://github.com/rust-lang/rust/blob/894f7a4ba6554d3797404bbf550d9919df060b97/compiler/rustc_parse/src/parser/tests.rs -use annotate_snippets::{level::Level, AnnotationKind, Group, Origin, Renderer, Snippet}; +use annotate_snippets::{AnnotationKind, Group, Level, Origin, Renderer, Snippet}; use snapbox::{assert_data_eq, str}; @@ -12,7 +12,7 @@ fn ends_on_col0() { fn foo() { } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -42,7 +42,7 @@ fn foo() { } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -74,7 +74,7 @@ fn foo() { X2 Y2 } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -117,7 +117,7 @@ fn foo() { Y1 X1 } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -161,7 +161,7 @@ fn foo() { X3 Y3 Z3 } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -205,7 +205,7 @@ fn foo() { X2 Y2 Z2 } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -252,7 +252,7 @@ fn foo() { X2 Y2 Z2 } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -300,7 +300,7 @@ fn foo() { X3 Y3 Z3 } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -350,7 +350,7 @@ fn foo() { X3 Y3 Z3 } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -394,7 +394,7 @@ fn foo() { X3 Y3 Z3 } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -437,7 +437,7 @@ fn foo() { a { b { c } d } } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -470,7 +470,7 @@ fn foo() { a { b { c } d } } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -502,7 +502,7 @@ fn foo() { a { b { c } d } } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -537,7 +537,7 @@ fn foo() { a { b { c } d } } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -571,7 +571,7 @@ fn foo() { a bc d } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -605,7 +605,7 @@ fn foo() { a { b { c } d } } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -633,7 +633,7 @@ fn foo() { a { b { c } d } } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -662,7 +662,7 @@ fn foo() { a { b { c } d } } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -701,7 +701,7 @@ fn foo() { a { b { c } d } } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -732,7 +732,7 @@ fn foo() { a { b { c } d } } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -772,7 +772,7 @@ fn foo() { X3 Y3 Z3 } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -832,7 +832,7 @@ fn foo() { X3 Y3 Z3 } "#; - let input = Level::ERROR.message("foo").group( + let input = Level::ERROR.header("foo").group( Group::new().element( Snippet::source(source) .line_start(1) @@ -887,7 +887,7 @@ fn issue_91334() { fn f(){||yield(((){), "#; let input = Level::ERROR - .message("this file contains an unclosed delimiter") + .header("this file contains an unclosed delimiter") .group( Group::new().element( Snippet::source(source) @@ -958,7 +958,7 @@ fn main() { } "#; let input = Level::ERROR - .message("`break` with value from a `while` loop") + .header("`break` with value from a `while` loop") .id("E0571") .group( Group::new().element( @@ -1168,7 +1168,7 @@ fn nsize() { "#; let input = Level::ERROR - .message("`V0usize` cannot be safely transmuted into `[usize; 2]`") + .header("`V0usize` cannot be safely transmuted into `[usize; 2]`") .id("E0277") .group( Group::new().element( @@ -1254,7 +1254,7 @@ fn main() { } "#; let input = Level::ERROR - .message("`&[u8; 0]` cannot be safely transmuted into `&[u16; 0]`") + .header("`&[u8; 0]` cannot be safely transmuted into `&[u16; 0]`") .id("E027s7") .group( Group::new().element( @@ -1323,7 +1323,7 @@ fn g() { fn main() {} "#; let input = Level::ERROR - .message("expected function, found `{integer}`") + .header("expected function, found `{integer}`") .id("E0618") .group( Group::new().element( @@ -1414,7 +1414,7 @@ macro_rules! outer_macro { outer_macro!(FirstStruct, FirstAttrStruct); "#; let input = Level::WARNING - .message("non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module") + .header("non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module") .group( Group::new() .element( @@ -1547,7 +1547,7 @@ macro_rules! inline { } "#; let input = Level::ERROR - .message("can't call method `pow` on ambiguous numeric type `{integer}`") + .header("can't call method `pow` on ambiguous numeric type `{integer}`") .id("E0689") .group( Group::new().element( @@ -1611,7 +1611,7 @@ fn main() {} "#; let input = Level::ERROR - .message("type annotations needed") + .header("type annotations needed") .id("E0282") .group( Group::new().element( @@ -1717,7 +1717,7 @@ fn main() {} "##; let input = Level::ERROR - .message( + .header( "non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered" ) .id("E0004") @@ -1819,7 +1819,7 @@ fn main() { } "#; let input = Level::ERROR - .message("the trait alias `EqAlias` is not dyn compatible") + .header("the trait alias `EqAlias` is not dyn compatible") .id("E0038") .group( Group::new().element(