feat(highlighting): implement syntax highlighting for unnamed source codes

This commit is contained in:
Gabriel Levcovitz 2025-02-19 14:02:32 -03:00
parent b8c144f2a6
commit 97b0cb27c0
No known key found for this signature in database
17 changed files with 393 additions and 379 deletions

View File

@ -100,7 +100,7 @@ You can derive a `Diagnostic` from any `std::error::Error` type.
`thiserror` is a great way to define them, and plays nicely with `miette`! `thiserror` is a great way to define them, and plays nicely with `miette`!
*/ */
use miette::{Diagnostic, NamedSource, SourceSpan}; use miette::{Diagnostic, MietteSourceCode, SourceSpan};
use thiserror::Error; use thiserror::Error;
#[derive(Error, Debug, Diagnostic)] #[derive(Error, Debug, Diagnostic)]
@ -114,7 +114,7 @@ struct MyBad {
// The Source that we're gonna be printing snippets out of. // The Source that we're gonna be printing snippets out of.
// This can be a String if you don't have or care about file names. // This can be a String if you don't have or care about file names.
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
// Snippets and highlights can be included in the diagnostic! // Snippets and highlights can be included in the diagnostic!
#[label("This bit here")] #[label("This bit here")]
bad_bit: SourceSpan, bad_bit: SourceSpan,
@ -134,7 +134,7 @@ fn this_fails() -> Result<()> {
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
Err(MyBad { Err(MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
bad_bit: (9, 4).into(), bad_bit: (9, 4).into(),
})?; })?;
@ -649,7 +649,6 @@ If you...
[`MietteDiagnostic`] directly to create diagnostic on the fly. [`MietteDiagnostic`] directly to create diagnostic on the fly.
```rust ```rust
let source = "2 + 2 * 2 = 8".to_string(); let source = "2 + 2 * 2 = 8".to_string();
let report = miette!( let report = miette!(
labels = vec![ labels = vec![
@ -665,23 +664,32 @@ println!("{:?}", report)
`miette` can be configured to highlight syntax in source code snippets. `miette` can be configured to highlight syntax in source code snippets.
<!-- TODO: screenshot goes here once default Theme is decided --> <img src="https://raw.githubusercontent.com/zkat/miette/main/images/syntax_highlight.png"/>
To use the built-in highlighting functionality, you must enable the To use the built-in highlighting functionality, you must enable the
`syntect-highlighter` crate feature. When this feature is enabled, `miette` will `syntect-highlighter` crate feature. When this feature is enabled, `miette` will
automatically use the [`syntect`] crate to highlight the `#[source_code]` automatically use the [`syntect`] crate to highlight the `#[source_code]`
field of your [`Diagnostic`]. field of your [`Diagnostic`].
Syntax detection with [`syntect`] is handled by checking 2 methods on the [`SpanContents`] trait, in order: Syntax detection with [`syntect`] is handled by checking 2 methods on the [`SourceCode`] trait, in order:
* [`language()`](SpanContents::language) - Provides the name of the language * [`language()`](SourceCode::language) - Provides the name of the language
as a string. For example `"Rust"` will indicate Rust syntax highlighting. as a string. For example `"Rust"` will indicate Rust syntax highlighting.
You can set the language of the [`SpanContents`] produced by a You can set the language of a [`SourceCode`] by using a
[`NamedSource`] via the [`with_language`](NamedSource::with_language) [`MietteSourceCode`], via the [`with_language`](MietteSourceCode::with_language)
method. method.
* [`name()`](SpanContents::name) - In the absence of an explicitly set * [`name()`](SourceCode::name) - In the absence of an explicitly set
language, the name is assumed to contain a file name or file path. language, the name is assumed to contain a file name or file path.
The highlighter will check for a file extension at the end of the name and The highlighter will check for a file extension at the end of the name and
try to guess the syntax from that. try to guess the syntax from that. Can also be set via the
[`with_name`](MietteSourceCod::with_name) method.
```rust
let src = MietteSourceCode::new("fn hello(oops) -> &str { \"hello!\" }").with_language("Rust");
let report = miette!(
labels = vec![LabeledSpan::at((9, 4), "this is wrong")],
"invalid syntax!",
).with_source_code(src);
```
If you want to use a custom highlighter, you can provide a custom If you want to use a custom highlighter, you can provide a custom
implementation of the [`Highlighter`](highlighters::Highlighter) implementation of the [`Highlighter`](highlighters::Highlighter)

BIN
images/syntax_highlight.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -619,7 +619,7 @@ impl GraphicalReportHandler {
.map(|(label, st)| FancySpan::new(label.label().map(String::from), *label.inner(), st)) .map(|(label, st)| FancySpan::new(label.label().map(String::from), *label.inner(), st))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let mut highlighter_state = self.highlighter.start_highlighter_state(&*contents); let mut highlighter_state = self.highlighter.start_highlighter_state(source, &*contents);
// The max number of gutter-lines that will be active at any given // The max number of gutter-lines that will be active at any given
// point. We need this to figure out indentation, so we do one loop // point. We need this to figure out indentation, so we do one loop
@ -663,7 +663,7 @@ impl GraphicalReportHandler {
None => contents, None => contents,
}; };
if let Some(source_name) = primary_contents.name() { if let Some(source_name) = source.name() {
writeln!( writeln!(
f, f,
"[{}]", "[{}]",

View File

@ -159,8 +159,8 @@ impl JSONReportHandler {
) -> fmt::Result { ) -> fmt::Result {
if let Some(mut labels) = diagnostic.labels() { if let Some(mut labels) = diagnostic.labels() {
if let Some(label) = labels.next() { if let Some(label) = labels.next() {
if let Ok(span_content) = source.read_span(label.inner(), 0, 0) { if source.read_span(label.inner(), 0, 0).is_ok() {
let filename = span_content.name().unwrap_or_default(); let filename = source.name().unwrap_or_default();
return write!(f, r#""filename": "{}","#, escape(filename)); return write!(f, r#""filename": "{}","#, escape(filename));
} }
} }

View File

@ -227,7 +227,7 @@ impl NarratableReportHandler {
) -> fmt::Result { ) -> fmt::Result {
let (contents, lines) = self.get_lines(source, context.inner())?; let (contents, lines) = self.get_lines(source, context.inner())?;
write!(f, "Begin snippet")?; write!(f, "Begin snippet")?;
if let Some(filename) = contents.name() { if let Some(filename) = source.name() {
write!(f, " for {}", filename,)?; write!(f, " for {}", filename,)?;
} }
writeln!( writeln!(

View File

@ -1,6 +1,6 @@
use owo_colors::Style; use owo_colors::Style;
use crate::SpanContents; use crate::{SourceCode, SpanContents};
use super::{Highlighter, HighlighterState}; use super::{Highlighter, HighlighterState};
@ -12,7 +12,8 @@ pub struct BlankHighlighter;
impl Highlighter for BlankHighlighter { impl Highlighter for BlankHighlighter {
fn start_highlighter_state<'h>( fn start_highlighter_state<'h>(
&'h self, &'h self,
_source: &dyn SpanContents<'_>, _source: &dyn SourceCode,
_span: &dyn SpanContents<'_>,
) -> Box<dyn super::HighlighterState + 'h> { ) -> Box<dyn super::HighlighterState + 'h> {
Box::new(BlankHighlighterState) Box::new(BlankHighlighterState)
} }

View File

@ -13,7 +13,7 @@
use std::{ops::Deref, sync::Arc}; use std::{ops::Deref, sync::Arc};
use crate::SpanContents; use crate::{SourceCode, SpanContents};
use owo_colors::Styled; use owo_colors::Styled;
#[cfg(feature = "syntect-highlighter")] #[cfg(feature = "syntect-highlighter")]
@ -39,7 +39,8 @@ pub trait Highlighter {
/// responsible for the actual rendering. /// responsible for the actual rendering.
fn start_highlighter_state<'h>( fn start_highlighter_state<'h>(
&'h self, &'h self,
source: &dyn SpanContents<'_>, source: &dyn SourceCode,
span: &dyn SpanContents<'_>,
) -> Box<dyn HighlighterState + 'h>; ) -> Box<dyn HighlighterState + 'h>;
} }

View File

@ -15,7 +15,7 @@ use owo_colors::{Rgb, Style, Styled};
use crate::{ use crate::{
highlighters::{Highlighter, HighlighterState}, highlighters::{Highlighter, HighlighterState},
SpanContents, SourceCode, SpanContents,
}; };
use super::BlankHighlighterState; use super::BlankHighlighterState;
@ -42,9 +42,10 @@ impl Default for SyntectHighlighter {
impl Highlighter for SyntectHighlighter { impl Highlighter for SyntectHighlighter {
fn start_highlighter_state<'h>( fn start_highlighter_state<'h>(
&'h self, &'h self,
source: &dyn SpanContents<'_>, source: &dyn SourceCode,
span: &dyn SpanContents<'_>,
) -> Box<dyn HighlighterState + 'h> { ) -> Box<dyn HighlighterState + 'h> {
if let Some(syntax) = self.detect_syntax(source) { if let Some(syntax) = self.detect_syntax(source, span) {
let highlighter = syntect::Highlighter::new(&self.theme); let highlighter = syntect::Highlighter::new(&self.theme);
let parse_state = syntect::ParseState::new(syntax); let parse_state = syntect::ParseState::new(syntax);
let highlight_state = let highlight_state =
@ -82,13 +83,17 @@ impl SyntectHighlighter {
} }
/// Determine syntect [`SyntaxReference`] to use for given [`SpanContents`]. /// Determine syntect [`SyntaxReference`] to use for given [`SpanContents`].
fn detect_syntax(&self, contents: &dyn SpanContents<'_>) -> Option<&syntect::SyntaxReference> { fn detect_syntax(
&self,
source: &dyn SourceCode,
span: &dyn SpanContents<'_>,
) -> Option<&syntect::SyntaxReference> {
// use language if given // use language if given
if let Some(language) = contents.language() { if let Some(language) = source.language() {
return self.syntax_set.find_syntax_by_name(language); return self.syntax_set.find_syntax_by_name(language);
} }
// otherwise try to use any file extension provided in the name // otherwise try to use any file extension provided in the name
if let Some(name) = contents.name() { if let Some(name) = source.name() {
if let Some(ext) = Path::new(name).extension() { if let Some(ext) = Path::new(name).extension() {
return self return self
.syntax_set .syntax_set
@ -96,12 +101,8 @@ impl SyntectHighlighter {
} }
} }
// finally, attempt to guess syntax based on first line // finally, attempt to guess syntax based on first line
return self.syntax_set.find_syntax_by_first_line( self.syntax_set
std::str::from_utf8(contents.data()) .find_syntax_by_first_line(std::str::from_utf8(span.data()).ok()?.split('\n').next()?)
.ok()?
.split('\n')
.next()?,
);
} }
} }

View File

@ -100,7 +100,7 @@
//! //!
//! `thiserror` is a great way to define them, and plays nicely with `miette`! //! `thiserror` is a great way to define them, and plays nicely with `miette`!
//! */ //! */
//! use miette::{Diagnostic, NamedSource, SourceSpan}; //! use miette::{Diagnostic, MietteSourceCode, SourceSpan};
//! use thiserror::Error; //! use thiserror::Error;
//! //!
//! #[derive(Error, Debug, Diagnostic)] //! #[derive(Error, Debug, Diagnostic)]
@ -114,7 +114,7 @@
//! // The Source that we're gonna be printing snippets out of. //! // The Source that we're gonna be printing snippets out of.
//! // This can be a String if you don't have or care about file names. //! // This can be a String if you don't have or care about file names.
//! #[source_code] //! #[source_code]
//! src: NamedSource<String>, //! src: MietteSourceCode<String>,
//! // Snippets and highlights can be included in the diagnostic! //! // Snippets and highlights can be included in the diagnostic!
//! #[label("This bit here")] //! #[label("This bit here")]
//! bad_bit: SourceSpan, //! bad_bit: SourceSpan,
@ -134,7 +134,7 @@
//! let src = "source\n text\n here".to_string(); //! let src = "source\n text\n here".to_string();
//! //!
//! Err(MyBad { //! Err(MyBad {
//! src: NamedSource::new("bad_file.rs", src), //! src: MietteSourceCode::new(src).with_name("bad_file.rs"),
//! bad_bit: (9, 4).into(), //! bad_bit: (9, 4).into(),
//! })?; //! })?;
//! //!
@ -650,7 +650,6 @@
//! //!
//! ```rust,ignore //! ```rust,ignore
//! # use miette::{miette, LabeledSpan, Report}; //! # use miette::{miette, LabeledSpan, Report};
//!
//! let source = "2 + 2 * 2 = 8".to_string(); //! let source = "2 + 2 * 2 = 8".to_string();
//! let report = miette!( //! let report = miette!(
//! labels = vec![ //! labels = vec![
@ -666,23 +665,34 @@
//! //!
//! `miette` can be configured to highlight syntax in source code snippets. //! `miette` can be configured to highlight syntax in source code snippets.
//! //!
//! <!-- TODO: screenshot goes here once default Theme is decided --> //! <img src="https://raw.githubusercontent.com/zkat/miette/main/images/syntax_highlight.png"/>
//! //!
//! To use the built-in highlighting functionality, you must enable the //! To use the built-in highlighting functionality, you must enable the
//! `syntect-highlighter` crate feature. When this feature is enabled, `miette` will //! `syntect-highlighter` crate feature. When this feature is enabled, `miette` will
//! automatically use the [`syntect`] crate to highlight the `#[source_code]` //! automatically use the [`syntect`] crate to highlight the `#[source_code]`
//! field of your [`Diagnostic`]. //! field of your [`Diagnostic`].
//! //!
//! Syntax detection with [`syntect`] is handled by checking 2 methods on the [`SpanContents`] trait, in order: //! Syntax detection with [`syntect`] is handled by checking 2 methods on the [`SourceCode`] trait, in order:
//! * [`language()`](SpanContents::language) - Provides the name of the language //! * [`language()`](SourceCode::language) - Provides the name of the language
//! as a string. For example `"Rust"` will indicate Rust syntax highlighting. //! as a string. For example `"Rust"` will indicate Rust syntax highlighting.
//! You can set the language of the [`SpanContents`] produced by a //! You can set the language of a [`SourceCode`] by using a
//! [`NamedSource`] via the [`with_language`](NamedSource::with_language) //! [`MietteSourceCode`], via the [`with_language`](MietteSourceCode::with_language)
//! method. //! method.
//! * [`name()`](SpanContents::name) - In the absence of an explicitly set //! * [`name()`](SourceCode::name) - In the absence of an explicitly set
//! language, the name is assumed to contain a file name or file path. //! language, the name is assumed to contain a file name or file path.
//! The highlighter will check for a file extension at the end of the name and //! The highlighter will check for a file extension at the end of the name and
//! try to guess the syntax from that. //! try to guess the syntax from that. Can also be set via the
//! [`with_name`](MietteSourceCod::with_name) method.
//!
//! ```rust
//! # use miette::{miette, LabeledSpan, MietteSourceCode};
//! # use miette::Result;
//! let src = MietteSourceCode::new("fn hello(oops) -> &str { \"hello!\" }").with_language("Rust");
//! let report = miette!(
//! labels = vec![LabeledSpan::at((9, 4), "this is wrong")],
//! "invalid syntax!",
//! ).with_source_code(src);
//! ```
//! //!
//! If you want to use a custom highlighter, you can provide a custom //! If you want to use a custom highlighter, you can provide a custom
//! implementation of the [`Highlighter`](highlighters::Highlighter) //! implementation of the [`Highlighter`](highlighters::Highlighter)
@ -781,10 +791,10 @@ pub use eyreish::*;
pub use handler::*; pub use handler::*;
pub use handlers::*; pub use handlers::*;
pub use miette_diagnostic::*; pub use miette_diagnostic::*;
pub use named_source::*;
#[cfg(feature = "fancy")] #[cfg(feature = "fancy")]
pub use panic::*; pub use panic::*;
pub use protocol::*; pub use protocol::*;
pub use source_code::*;
mod chain; mod chain;
mod diagnostic_chain; mod diagnostic_chain;
@ -799,8 +809,8 @@ pub mod highlighters;
#[doc(hidden)] #[doc(hidden)]
pub mod macro_helpers; pub mod macro_helpers;
mod miette_diagnostic; mod miette_diagnostic;
mod named_source;
#[cfg(feature = "fancy")] #[cfg(feature = "fancy")]
mod panic; mod panic;
mod protocol; mod protocol;
mod source_code;
mod source_impls; mod source_impls;

View File

@ -1,78 +0,0 @@
use crate::{MietteError, MietteSpanContents, SourceCode, SpanContents};
/// Utility struct for when you have a regular [`SourceCode`] type that doesn't
/// implement `name`. For example [`String`]. Or if you want to override the
/// `name` returned by the `SourceCode`.
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct NamedSource<S: SourceCode + 'static> {
source: S,
name: String,
language: Option<String>,
}
impl<S: SourceCode> std::fmt::Debug for NamedSource<S> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("NamedSource")
.field("name", &self.name)
.field("source", &"<redacted>")
.field("language", &self.language);
Ok(())
}
}
impl<S: SourceCode + 'static> NamedSource<S> {
/// Create a new `NamedSource` using a regular [`SourceCode`] and giving
/// its returned [`SpanContents`] a name.
pub fn new(name: impl AsRef<str>, source: S) -> Self
where
S: Send + Sync,
{
Self {
source,
name: name.as_ref().to_string(),
language: None,
}
}
/// Gets the name of this `NamedSource`.
pub fn name(&self) -> &str {
&self.name
}
/// Returns a reference the inner [`SourceCode`] type for this
/// `NamedSource`.
pub fn inner(&self) -> &S {
&self.source
}
/// Sets the [`language`](SpanContents::language) for this source code.
pub fn with_language(mut self, language: impl Into<String>) -> Self {
self.language = Some(language.into());
self
}
}
impl<S: SourceCode + 'static> SourceCode for NamedSource<S> {
fn read_span<'a>(
&'a self,
span: &crate::SourceSpan,
context_lines_before: usize,
context_lines_after: usize,
) -> Result<Box<dyn SpanContents<'a> + 'a>, MietteError> {
let inner_contents =
self.inner()
.read_span(span, context_lines_before, context_lines_after)?;
let mut contents = MietteSpanContents::new_named(
self.name.clone(),
inner_contents.data(),
*inner_contents.span(),
inner_contents.line(),
inner_contents.column(),
inner_contents.line_count(),
);
if let Some(language) = &self.language {
contents = contents.with_language(language);
}
Ok(Box::new(contents))
}
}

View File

@ -253,6 +253,16 @@ pub trait SourceCode: Send + Sync {
context_lines_before: usize, context_lines_before: usize,
context_lines_after: usize, context_lines_after: usize,
) -> Result<Box<dyn SpanContents<'a> + 'a>, MietteError>; ) -> Result<Box<dyn SpanContents<'a> + 'a>, MietteError>;
/// Optional method. Get this `SourceCode`'s name.
fn name(&self) -> Option<&str> {
None
}
/// Optional method. Get this `SourceCode`'s language.
fn language(&self) -> Option<&str> {
None
}
} }
/// A labeled [`SourceSpan`]. /// A labeled [`SourceSpan`].
@ -439,10 +449,6 @@ pub trait SpanContents<'a> {
fn data(&self) -> &'a [u8]; fn data(&self) -> &'a [u8];
/// [`SourceSpan`] representing the span covered by this `SpanContents`. /// [`SourceSpan`] representing the span covered by this `SpanContents`.
fn span(&self) -> &SourceSpan; fn span(&self) -> &SourceSpan;
/// An optional (file?) name for the container of this `SpanContents`.
fn name(&self) -> Option<&str> {
None
}
/// The 0-indexed line in the associated [`SourceCode`] where the data /// The 0-indexed line in the associated [`SourceCode`] where the data
/// begins. /// begins.
fn line(&self) -> usize; fn line(&self) -> usize;
@ -451,15 +457,6 @@ pub trait SpanContents<'a> {
fn column(&self) -> usize; fn column(&self) -> usize;
/// Total number of lines covered by this `SpanContents`. /// Total number of lines covered by this `SpanContents`.
fn line_count(&self) -> usize; fn line_count(&self) -> usize;
/// Optional method. The language name for this source code, if any.
/// This is used to drive syntax highlighting.
///
/// Examples: Rust, TOML, C
///
fn language(&self) -> Option<&str> {
None
}
} }
/** /**
@ -477,10 +474,6 @@ pub struct MietteSpanContents<'a> {
column: usize, column: usize,
// Number of line in this snippet. // Number of line in this snippet.
line_count: usize, line_count: usize,
// Optional filename
name: Option<String>,
// Optional language
language: Option<String>,
} }
impl<'a> MietteSpanContents<'a> { impl<'a> MietteSpanContents<'a> {
@ -498,36 +491,8 @@ impl<'a> MietteSpanContents<'a> {
line, line,
column, column,
line_count, line_count,
name: None,
language: None,
} }
} }
/// Make a new [`MietteSpanContents`] object, with a name for its 'file'.
pub const fn new_named(
name: String,
data: &'a [u8],
span: SourceSpan,
line: usize,
column: usize,
line_count: usize,
) -> MietteSpanContents<'a> {
MietteSpanContents {
data,
span,
line,
column,
line_count,
name: Some(name),
language: None,
}
}
/// Sets the [`language`](SpanContents::language) for syntax highlighting.
pub fn with_language(mut self, language: impl Into<String>) -> Self {
self.language = Some(language.into());
self
}
} }
impl<'a> SpanContents<'a> for MietteSpanContents<'a> { impl<'a> SpanContents<'a> for MietteSpanContents<'a> {
@ -546,12 +511,6 @@ impl<'a> SpanContents<'a> for MietteSpanContents<'a> {
fn line_count(&self) -> usize { fn line_count(&self) -> usize {
self.line_count self.line_count
} }
fn name(&self) -> Option<&str> {
self.name.as_deref()
}
fn language(&self) -> Option<&str> {
self.language.as_deref()
}
} }
/// Span within a [`SourceCode`] /// Span within a [`SourceCode`]

82
src/source_code.rs Normal file
View File

@ -0,0 +1,82 @@
use crate::{MietteError, SourceCode, SourceSpan, SpanContents};
/// Utility struct for adding attributes such as `name` and `language` to a [`SourceCode`],
/// or if you want to override those attributes from another [`SourceCode`]:
///
/// ```
/// # use miette::MietteSourceCode;
/// let src = MietteSourceCode::new("fn f() {}").with_name("snippet").with_language("Rust");
/// ```
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct MietteSourceCode<S: SourceCode + 'static> {
source: S,
name: Option<String>,
language: Option<String>,
}
impl<S: SourceCode> MietteSourceCode<S> {
/// Make a new [`MietteSourceCode`] object.
pub fn new(source: S) -> Self {
Self {
source,
name: None,
language: None,
}
}
/// Set the name for this source code.
pub fn with_name(mut self, name: impl AsRef<str>) -> Self {
self.name = Some(name.as_ref().to_string());
self
}
/// Set the language name for this source code.
///
/// This is used to drive syntax highlighting when the `syntect-highlighter`
/// feature is enabled.
///
/// Examples: `"Rust"`, `"Python"`, `"C"`
///
/// The list of language names comes from the [`syntect`] crate.
/// See https://github.com/trishume/syntect/issues/168
pub fn with_language(mut self, language: impl AsRef<str>) -> Self {
self.language = Some(language.as_ref().to_string());
self
}
}
impl<S: SourceCode> std::fmt::Debug for MietteSourceCode<S> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("NamedSource")
.field("name", &self.name)
.field("language", &self.language)
.field("source", &"<redacted>");
Ok(())
}
}
impl<S: SourceCode> SourceCode for MietteSourceCode<S> {
fn read_span<'a>(
&'a self,
span: &SourceSpan,
context_lines_before: usize,
context_lines_after: usize,
) -> Result<Box<dyn SpanContents<'a> + 'a>, MietteError> {
self.source
.read_span(span, context_lines_before, context_lines_after)
}
fn name(&self) -> Option<&str> {
self.name.as_deref()
}
fn language(&self) -> Option<&str> {
self.language.as_deref()
}
}
impl<S: SourceCode> From<S> for MietteSourceCode<S> {
fn from(source: S) -> Self {
MietteSourceCode::new(source)
}
}

View File

@ -1,9 +1,10 @@
#![cfg(feature = "fancy-no-backtrace")] #![cfg(feature = "fancy-no-backtrace")]
use miette::{ use miette::{
Diagnostic, GraphicalReportHandler, GraphicalTheme, MietteError, NamedSource, Diagnostic, GraphicalReportHandler, GraphicalTheme, MietteError, MietteSourceCode,
NarratableReportHandler, Report, SourceSpan, NarratableReportHandler, Report, SourceSpan,
}; };
use std::fmt::Debug;
use thiserror::Error; use thiserror::Error;
fn fmt_report(diag: Report) -> String { fn fmt_report(diag: Report) -> String {
@ -417,14 +418,14 @@ fn empty_source() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
} }
let src = "".to_string(); let src = "".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (0, 0).into(), highlight: (0, 0).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -450,22 +451,22 @@ fn multiple_spans_multiline() {
#[diagnostic(severity(Error))] #[diagnostic(severity(Error))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<&'static str>, src: MietteSourceCode<&'static str>,
#[label("big")] #[label("big")]
big: SourceSpan, big: SourceSpan,
#[label("small")] #[label("small")]
small: SourceSpan, small: SourceSpan,
} }
let err = MyBad { let err = MyBad {
src: NamedSource::new( src: MietteSourceCode::new(
"issue",
"\ "\
if true { if true {
a a
} else { } else {
b b
}", }",
), )
.with_name("issue"),
big: (0, 32).into(), big: (0, 32).into(),
small: (14, 1).into(), small: (14, 1).into(),
}; };
@ -496,12 +497,12 @@ fn single_line_highlight_span_full_line() {
#[diagnostic(severity(Error))] #[diagnostic(severity(Error))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<&'static str>, src: MietteSourceCode<&'static str>,
#[label("This bit here")] #[label("This bit here")]
bad_bit: SourceSpan, bad_bit: SourceSpan,
} }
let err = MyBad { let err = MyBad {
src: NamedSource::new("issue", "source\ntext"), src: MietteSourceCode::new("source\ntext").with_name("issue"),
bad_bit: (7, 4).into(), bad_bit: (7, 4).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -527,14 +528,14 @@ fn single_line_with_wide_char() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
} }
let src = "source\n 👼🏼text\n here".to_string(); let src = "source\n 👼🏼text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (13, 8).into(), highlight: (13, 8).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -564,7 +565,7 @@ fn single_line_with_two_tabs() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
} }
@ -573,7 +574,7 @@ fn single_line_with_two_tabs() -> Result<(), MietteError> {
let src = "source\n\t\ttext\n here".to_string(); let src = "source\n\t\ttext\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 4).into(), highlight: (9, 4).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -603,7 +604,7 @@ fn single_line_with_tab_in_middle() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
} }
@ -612,7 +613,7 @@ fn single_line_with_tab_in_middle() -> Result<(), MietteError> {
let src = "source\ntext =\ttext\n here".to_string(); let src = "source\ntext =\ttext\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (14, 4).into(), highlight: (14, 4).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -642,14 +643,14 @@ fn single_line_highlight() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
} }
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 4).into(), highlight: (9, 4).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -686,7 +687,7 @@ fn external_source() -> Result<(), MietteError> {
let err = Report::from(MyBad { let err = Report::from(MyBad {
highlight: (9, 4).into(), highlight: (9, 4).into(),
}) })
.with_source_code(NamedSource::new("bad_file.rs", src)); .with_source_code(MietteSourceCode::new(src).with_name("bad_file.rs"));
let out = fmt_report(err); let out = fmt_report(err);
println!("Error: {}", out); println!("Error: {}", out);
let expected = r#"oops::my::bad let expected = r#"oops::my::bad
@ -714,14 +715,14 @@ fn single_line_highlight_offset_zero() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
} }
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (0, 0).into(), highlight: (0, 0).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -750,14 +751,14 @@ fn single_line_highlight_offset_end_of_line() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
} }
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (6, 0).into(), highlight: (6, 0).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -786,14 +787,14 @@ fn single_line_highlight_include_end_of_line() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
} }
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 5).into(), highlight: (9, 5).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -823,14 +824,14 @@ fn single_line_highlight_include_end_of_line_crlf() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
} }
let src = "source\r\n text\r\n here".to_string(); let src = "source\r\n text\r\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (10, 6).into(), highlight: (10, 6).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -860,14 +861,14 @@ fn single_line_highlight_with_empty_span() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
} }
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 0).into(), highlight: (9, 0).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -897,14 +898,14 @@ fn single_line_highlight_no_label() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label] #[label]
highlight: SourceSpan, highlight: SourceSpan,
} }
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 4).into(), highlight: (9, 4).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -933,14 +934,14 @@ fn single_line_highlight_at_line_start() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
} }
let src = "source\ntext\n here".to_string(); let src = "source\ntext\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (7, 4).into(), highlight: (7, 4).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -970,14 +971,14 @@ fn multiline_label() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here\nand\nthis\ntoo")] #[label("this bit here\nand\nthis\ntoo")]
highlight: SourceSpan, highlight: SourceSpan,
} }
let src = "source\ntext\n here".to_string(); let src = "source\ntext\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (7, 4).into(), highlight: (7, 4).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -1010,7 +1011,7 @@ fn multiple_multi_line_labels() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label = "x\ny"] #[label = "x\ny"]
highlight1: SourceSpan, highlight1: SourceSpan,
#[label = "z\nw"] #[label = "z\nw"]
@ -1021,7 +1022,7 @@ fn multiple_multi_line_labels() -> Result<(), MietteError> {
let src = "source\n text text text text text\n here".to_string(); let src = "source\n text text text text text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight1: (9, 4).into(), highlight1: (9, 4).into(),
highlight2: (14, 4).into(), highlight2: (14, 4).into(),
highlight3: (24, 4).into(), highlight3: (24, 4).into(),
@ -1058,7 +1059,7 @@ fn multiple_same_line_highlights() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label = "x"] #[label = "x"]
highlight1: SourceSpan, highlight1: SourceSpan,
#[label = "y"] #[label = "y"]
@ -1069,7 +1070,7 @@ fn multiple_same_line_highlights() -> Result<(), MietteError> {
let src = "source\n text text text text text\n here".to_string(); let src = "source\n text text text text text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight1: (9, 4).into(), highlight1: (9, 4).into(),
highlight2: (14, 4).into(), highlight2: (14, 4).into(),
highlight3: (24, 4).into(), highlight3: (24, 4).into(),
@ -1103,7 +1104,7 @@ fn multiple_same_line_highlights_with_tabs_in_middle() -> Result<(), MietteError
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label = "x"] #[label = "x"]
highlight1: SourceSpan, highlight1: SourceSpan,
#[label = "y"] #[label = "y"]
@ -1116,7 +1117,7 @@ fn multiple_same_line_highlights_with_tabs_in_middle() -> Result<(), MietteError
let src = "source\n text text text\ttext text\n here".to_string(); let src = "source\n text text text\ttext text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight1: (9, 4).into(), highlight1: (9, 4).into(),
highlight2: (14, 4).into(), highlight2: (14, 4).into(),
highlight3: (24, 4).into(), highlight3: (24, 4).into(),
@ -1150,14 +1151,14 @@ fn multiline_highlight_adjacent() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label = "these two lines"] #[label = "these two lines"]
highlight: SourceSpan, highlight: SourceSpan,
} }
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 11).into(), highlight: (9, 11).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -1186,14 +1187,14 @@ fn multiline_highlight_multiline_label() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label = "these two lines\nare the problem"] #[label = "these two lines\nare the problem"]
highlight: SourceSpan, highlight: SourceSpan,
} }
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 11).into(), highlight: (9, 11).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -1223,7 +1224,7 @@ fn multiline_highlight_flyby() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label = "block 1"] #[label = "block 1"]
highlight1: SourceSpan, highlight1: SourceSpan,
#[label = "block 2"] #[label = "block 2"]
@ -1239,7 +1240,7 @@ line5
.to_string(); .to_string();
let len = src.len(); let len = src.len();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight1: (0, len).into(), highlight1: (0, len).into(),
highlight2: (10, 9).into(), highlight2: (10, 9).into(),
}; };
@ -1274,7 +1275,7 @@ fn multiline_highlight_no_label() -> Result<(), MietteError> {
#[source] #[source]
source: Inner, source: Inner,
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label = "block 1"] #[label = "block 1"]
highlight1: SourceSpan, highlight1: SourceSpan,
#[label] #[label]
@ -1299,7 +1300,7 @@ line5
let len = src.len(); let len = src.len();
let err = MyBad { let err = MyBad {
source: Inner(InnerInner), source: Inner(InnerInner),
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight1: (0, len).into(), highlight1: (0, len).into(),
highlight2: (10, 9).into(), highlight2: (10, 9).into(),
}; };
@ -1338,7 +1339,7 @@ fn multiple_multiline_highlights_adjacent() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label = "this bit here"] #[label = "this bit here"]
highlight1: SourceSpan, highlight1: SourceSpan,
#[label = "also this bit"] #[label = "also this bit"]
@ -1347,7 +1348,7 @@ fn multiple_multiline_highlights_adjacent() -> Result<(), MietteError> {
let src = "source\n text\n here\nmore here".to_string(); let src = "source\n text\n here\nmore here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight1: (0, 10).into(), highlight1: (0, 10).into(),
highlight2: (20, 6).into(), highlight2: (20, 6).into(),
}; };
@ -1384,7 +1385,7 @@ fn multiple_multiline_highlights_overlapping_lines() -> Result<(), MietteError>
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label = "this bit here"] #[label = "this bit here"]
highlight1: SourceSpan, highlight1: SourceSpan,
#[label = "also this bit"] #[label = "also this bit"]
@ -1393,7 +1394,7 @@ fn multiple_multiline_highlights_overlapping_lines() -> Result<(), MietteError>
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight1: (0, 8).into(), highlight1: (0, 8).into(),
highlight2: (9, 10).into(), highlight2: (9, 10).into(),
}; };
@ -1412,7 +1413,7 @@ fn multiple_multiline_highlights_overlapping_offsets() -> Result<(), MietteError
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label = "this bit here"] #[label = "this bit here"]
highlight1: SourceSpan, highlight1: SourceSpan,
#[label = "also this bit"] #[label = "also this bit"]
@ -1421,7 +1422,7 @@ fn multiple_multiline_highlights_overlapping_offsets() -> Result<(), MietteError
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight1: (0, 8).into(), highlight1: (0, 8).into(),
highlight2: (10, 10).into(), highlight2: (10, 10).into(),
}; };
@ -1516,7 +1517,7 @@ fn related() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
#[related] #[related]
@ -1525,10 +1526,10 @@ fn related() -> Result<(), MietteError> {
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src.clone()), src: MietteSourceCode::new(src.clone()).with_name("bad_file.rs"),
highlight: (9, 4).into(), highlight: (9, 4).into(),
related: vec![MyBad { related: vec![MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (0, 6).into(), highlight: (0, 6).into(),
related: vec![], related: vec![],
}], }],
@ -1571,7 +1572,7 @@ fn related_source_code_propagation() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
#[related] #[related]
@ -1588,7 +1589,7 @@ fn related_source_code_propagation() -> Result<(), MietteError> {
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 4).into(), highlight: (9, 4).into(),
related: vec![InnerError { related: vec![InnerError {
highlight: (0, 6).into(), highlight: (0, 6).into(),
@ -1631,7 +1632,7 @@ fn related_severity() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
#[related] #[related]
@ -1648,7 +1649,7 @@ fn related_severity() -> Result<(), MietteError> {
)] )]
Error { Error {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
}, },
@ -1661,7 +1662,7 @@ fn related_severity() -> Result<(), MietteError> {
)] )]
Warning { Warning {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
}, },
@ -1674,7 +1675,7 @@ fn related_severity() -> Result<(), MietteError> {
)] )]
Advice { Advice {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
}, },
@ -1682,19 +1683,19 @@ fn related_severity() -> Result<(), MietteError> {
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src.clone()), src: MietteSourceCode::new(src.clone()).with_name("bad_file.rs"),
highlight: (9, 4).into(), highlight: (9, 4).into(),
related: vec![ related: vec![
MyRelated::Error { MyRelated::Error {
src: NamedSource::new("bad_file.rs", src.clone()), src: MietteSourceCode::new(src.clone()).with_name("bad_file.rs"),
highlight: (0, 6).into(), highlight: (0, 6).into(),
}, },
MyRelated::Warning { MyRelated::Warning {
src: NamedSource::new("bad_file.rs", src.clone()), src: MietteSourceCode::new(src.clone()).with_name("bad_file.rs"),
highlight: (0, 6).into(), highlight: (0, 6).into(),
}, },
MyRelated::Advice { MyRelated::Advice {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (0, 6).into(), highlight: (0, 6).into(),
}, },
], ],
@ -1759,12 +1760,13 @@ fn zero_length_eol_span() {
#[diagnostic(severity(Error))] #[diagnostic(severity(Error))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<&'static str>, src: MietteSourceCode<&'static str>,
#[label("This bit here")] #[label("This bit here")]
bad_bit: SourceSpan, bad_bit: SourceSpan,
} }
let err = MyBad { let err = MyBad {
src: NamedSource::new("issue", "this is the first line\nthis is the second line"), src: MietteSourceCode::new("this is the first line\nthis is the second line")
.with_name("issue"),
bad_bit: (23, 0).into(), bad_bit: (23, 0).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -1789,14 +1791,15 @@ fn primary_label() {
#[error("oops!")] #[error("oops!")]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<&'static str>, src: MietteSourceCode<&'static str>,
#[label] #[label]
first_label: SourceSpan, first_label: SourceSpan,
#[label(primary, "nope")] #[label(primary, "nope")]
second_label: SourceSpan, second_label: SourceSpan,
} }
let err = MyBad { let err = MyBad {
src: NamedSource::new("issue", "this is the first line\nthis is the second line"), src: MietteSourceCode::new("this is the first line\nthis is the second line")
.with_name("issue"),
first_label: (2, 4).into(), first_label: (2, 4).into(),
second_label: (24, 4).into(), second_label: (24, 4).into(),
}; };
@ -1825,14 +1828,14 @@ fn single_line_with_wide_char_unaligned_span_start() -> Result<(), MietteError>
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
} }
let src = "source\n 👼🏼text\n here".to_string(); let src = "source\n 👼🏼text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (10, 5).into(), highlight: (10, 5).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -1862,14 +1865,14 @@ fn single_line_with_wide_char_unaligned_span_end() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
} }
let src = "source\n text 👼🏼\n here".to_string(); let src = "source\n text 👼🏼\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 6).into(), highlight: (9, 6).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -1899,14 +1902,14 @@ fn single_line_with_wide_char_unaligned_span_empty() -> Result<(), MietteError>
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
} }
let src = "source\n 👼🏼text\n here".to_string(); let src = "source\n 👼🏼text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (10, 0).into(), highlight: (10, 0).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -1938,17 +1941,17 @@ fn syntax_highlighter() {
#[diagnostic()] #[diagnostic()]
pub struct Test { pub struct Test {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this is a label")] #[label("this is a label")]
src_span: SourceSpan, src_span: SourceSpan,
} }
let src = NamedSource::new( let name = "hello_world"; // NOTE: intentionally missing file extension
"hello_world", //NOTE: intentionally missing file extension let src =
"fn main() {\n println!(\"Hello, World!\");\n}\n".to_string(), MietteSourceCode::new("fn main() {\n println!(\"Hello, World!\");\n}\n".to_string())
) .with_language("Rust");
.with_language("Rust"); let src_with_name = src.clone().with_name(name);
let err = Test { let err = Test {
src, src: src_with_name,
src_span: (16, 26).into(), src_span: (16, 26).into(),
}; };
let mut out = String::new(); let mut out = String::new();
@ -1966,8 +1969,33 @@ fn syntax_highlighter() {
"# "#
.trim_start_matches('\n'); .trim_start_matches('\n');
assert!(out.contains("\u{1b}[38;2;180;142;173m")); let colors = "\u{1b}[38;2;180;142;173m";
assert_eq!(expected, strip_ansi_escapes::strip_str(out)) assert!(out.contains(colors));
assert_eq!(expected, strip_ansi_escapes::strip_str(out));
// test unnamed source code
let err = Test {
src,
src_span: (16, 26).into(),
};
let mut out = String::new();
GraphicalReportHandler::new_themed(GraphicalTheme::unicode())
.render_report(&mut out, &err)
.unwrap();
let expected = r#"
× This is an error
[2:5]
1 fn main() {
2 println!("Hello, World!");
·
· this is a label
3 }
"#
.trim_start_matches('\n');
assert!(out.contains(colors));
assert_eq!(expected, strip_ansi_escapes::strip_str(out));
} }
// This test reads a line from the current source file and renders it with Rust // This test reads a line from the current source file and renders it with Rust
@ -1985,7 +2013,7 @@ fn syntax_highlighter_on_real_file() {
#[diagnostic()] #[diagnostic()]
pub struct Test { pub struct Test {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this is a label")] #[label("this is a label")]
src_span: SourceSpan, src_span: SourceSpan,
} }
@ -2000,7 +2028,7 @@ fn syntax_highlighter_on_real_file() {
let file_src = std::fs::read_to_string(filename).unwrap(); let file_src = std::fs::read_to_string(filename).unwrap();
let offset = miette::SourceOffset::from_location(&file_src, line, CO); let offset = miette::SourceOffset::from_location(&file_src, line, CO);
let err = Test { let err = Test {
src: NamedSource::new(filename, file_src.clone()), src: MietteSourceCode::new(file_src.clone()).with_name(filename),
src_span: SourceSpan::new(offset, LEN), src_span: SourceSpan::new(offset, LEN),
}; };
@ -2037,7 +2065,7 @@ fn triple_adjacent_highlight() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label = "this bit here"] #[label = "this bit here"]
highlight1: SourceSpan, highlight1: SourceSpan,
#[label = "also this bit"] #[label = "also this bit"]
@ -2048,7 +2076,7 @@ fn triple_adjacent_highlight() -> Result<(), MietteError> {
let src = "source\n\n\n text\n\n\n here".to_string(); let src = "source\n\n\n text\n\n\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight1: (0, 6).into(), highlight1: (0, 6).into(),
highlight2: (11, 4).into(), highlight2: (11, 4).into(),
highlight3: (22, 4).into(), highlight3: (22, 4).into(),
@ -2086,7 +2114,7 @@ fn non_adjacent_highlight() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label = "this bit here"] #[label = "this bit here"]
highlight1: SourceSpan, highlight1: SourceSpan,
#[label = "also this bit"] #[label = "also this bit"]
@ -2095,7 +2123,7 @@ fn non_adjacent_highlight() -> Result<(), MietteError> {
let src = "source\n\n\n\n text here".to_string(); let src = "source\n\n\n\n text here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight1: (0, 6).into(), highlight1: (0, 6).into(),
highlight2: (12, 4).into(), highlight2: (12, 4).into(),
}; };
@ -2129,14 +2157,14 @@ fn invalid_span_bad_offset() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("help info"))] #[diagnostic(code(oops::my::bad), help("help info"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label = "1st"] #[label = "1st"]
highlight1: SourceSpan, highlight1: SourceSpan,
} }
let src = "blabla blibli".to_string(); let src = "blabla blibli".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight1: (50, 6).into(), highlight1: (50, 6).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -2158,14 +2186,14 @@ fn invalid_span_bad_length() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("help info"))] #[diagnostic(code(oops::my::bad), help("help info"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label = "1st"] #[label = "1st"]
highlight1: SourceSpan, highlight1: SourceSpan,
} }
let src = "blabla blibli".to_string(); let src = "blabla blibli".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight1: (0, 50).into(), highlight1: (0, 50).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -2187,14 +2215,14 @@ fn invalid_span_no_label() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("help info"))] #[diagnostic(code(oops::my::bad), help("help info"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label] #[label]
highlight1: SourceSpan, highlight1: SourceSpan,
} }
let src = "blabla blibli".to_string(); let src = "blabla blibli".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight1: (50, 6).into(), highlight1: (50, 6).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -2216,7 +2244,7 @@ fn invalid_span_2nd_label() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("help info"))] #[diagnostic(code(oops::my::bad), help("help info"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("1st")] #[label("1st")]
highlight1: SourceSpan, highlight1: SourceSpan,
#[label("2nd")] #[label("2nd")]
@ -2225,7 +2253,7 @@ fn invalid_span_2nd_label() -> Result<(), MietteError> {
let src = "blabla blibli".to_string(); let src = "blabla blibli".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight1: (0, 6).into(), highlight1: (0, 6).into(),
highlight2: (50, 6).into(), highlight2: (50, 6).into(),
}; };
@ -2248,7 +2276,7 @@ fn invalid_span_inner() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::inner), help("help info"))] #[diagnostic(code(oops::my::inner), help("help info"))]
struct MyInner { struct MyInner {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("inner label")] #[label("inner label")]
inner_label: SourceSpan, inner_label: SourceSpan,
} }
@ -2258,7 +2286,7 @@ fn invalid_span_inner() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::outer), help("help info"))] #[diagnostic(code(oops::my::outer), help("help info"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("outer label")] #[label("outer label")]
outer_label: SourceSpan, outer_label: SourceSpan,
#[source] #[source]
@ -2268,10 +2296,10 @@ fn invalid_span_inner() -> Result<(), MietteError> {
let src_outer = "outer source".to_string(); let src_outer = "outer source".to_string();
let src_inner = "inner source".to_string(); let src_inner = "inner source".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src_outer), src: MietteSourceCode::new(src_outer).with_name("bad_file.rs"),
outer_label: (0, 6).into(), outer_label: (0, 6).into(),
inner: MyInner { inner: MyInner {
src: NamedSource::new("bad_file2.rs", src_inner), src: MietteSourceCode::new(src_inner).with_name("bad_file2.rs"),
inner_label: (60, 6).into(), inner_label: (60, 6).into(),
}, },
}; };
@ -2299,7 +2327,7 @@ fn invalid_span_related() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::inner), help("help info"))] #[diagnostic(code(oops::my::inner), help("help info"))]
struct MyRelated { struct MyRelated {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("inner label")] #[label("inner label")]
inner_label: SourceSpan, inner_label: SourceSpan,
} }
@ -2309,7 +2337,7 @@ fn invalid_span_related() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::outer), help("help info"))] #[diagnostic(code(oops::my::outer), help("help info"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("outer label")] #[label("outer label")]
outer_label: SourceSpan, outer_label: SourceSpan,
#[related] #[related]
@ -2319,10 +2347,10 @@ fn invalid_span_related() -> Result<(), MietteError> {
let src_outer = "outer source".to_string(); let src_outer = "outer source".to_string();
let src_inner = "related source".to_string(); let src_inner = "related source".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src_outer), src: MietteSourceCode::new(src_outer).with_name("bad_file.rs"),
outer_label: (0, 6).into(), outer_label: (0, 6).into(),
inner: vec![MyRelated { inner: vec![MyRelated {
src: NamedSource::new("bad_file2.rs", src_inner), src: MietteSourceCode::new(src_inner).with_name("bad_file2.rs"),
inner_label: (60, 6).into(), inner_label: (60, 6).into(),
}], }],
}; };

View File

@ -1,6 +1,8 @@
#![cfg(feature = "fancy-no-backtrace")] #![cfg(feature = "fancy-no-backtrace")]
use miette::{Diagnostic, MietteError, NamedSource, NarratableReportHandler, Report, SourceSpan}; use miette::{
Diagnostic, MietteError, MietteSourceCode, NarratableReportHandler, Report, SourceSpan,
};
use miette::{GraphicalReportHandler, GraphicalTheme}; use miette::{GraphicalReportHandler, GraphicalTheme};
@ -29,14 +31,14 @@ fn single_line_with_wide_char() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
} }
let src = "source\n 👼🏼text\n here".to_string(); let src = "source\n 👼🏼text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 6).into(), highlight: (9, 6).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -65,14 +67,14 @@ fn single_line_highlight() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
} }
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 4).into(), highlight: (9, 4).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -101,14 +103,14 @@ fn single_line_highlight_offset_zero() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
} }
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (0, 0).into(), highlight: (0, 0).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -136,14 +138,14 @@ fn single_line_highlight_with_empty_span() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
} }
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 0).into(), highlight: (9, 0).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -172,14 +174,14 @@ fn single_line_highlight_no_label() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label] #[label]
highlight: SourceSpan, highlight: SourceSpan,
} }
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 4).into(), highlight: (9, 4).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -208,14 +210,14 @@ fn single_line_highlight_at_line_start() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
} }
let src = "source\ntext\n here".to_string(); let src = "source\ntext\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (7, 4).into(), highlight: (7, 4).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -244,7 +246,7 @@ fn multiple_same_line_highlights() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label = "x"] #[label = "x"]
highlight1: SourceSpan, highlight1: SourceSpan,
#[label = "y"] #[label = "y"]
@ -255,7 +257,7 @@ fn multiple_same_line_highlights() -> Result<(), MietteError> {
let src = "source\n text text text text text\n here".to_string(); let src = "source\n text text text text text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight1: (9, 4).into(), highlight1: (9, 4).into(),
highlight2: (14, 4).into(), highlight2: (14, 4).into(),
highlight3: (24, 4).into(), highlight3: (24, 4).into(),
@ -288,14 +290,14 @@ fn multiline_highlight_adjacent() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label = "these two lines"] #[label = "these two lines"]
highlight: SourceSpan, highlight: SourceSpan,
} }
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 11).into(), highlight: (9, 11).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -325,7 +327,7 @@ fn multiline_highlight_flyby() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label = "block 1"] #[label = "block 1"]
highlight1: SourceSpan, highlight1: SourceSpan,
#[label = "block 2"] #[label = "block 2"]
@ -341,7 +343,7 @@ line5
.to_string(); .to_string();
let len = src.len(); let len = src.len();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight1: (0, len).into(), highlight1: (0, len).into(),
highlight2: (10, 9).into(), highlight2: (10, 9).into(),
}; };
@ -378,7 +380,7 @@ fn multiline_highlight_no_label() -> Result<(), MietteError> {
#[source] #[source]
source: Inner, source: Inner,
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label = "block 1"] #[label = "block 1"]
highlight1: SourceSpan, highlight1: SourceSpan,
#[label] #[label]
@ -403,7 +405,7 @@ line5
let len = src.len(); let len = src.len();
let err = MyBad { let err = MyBad {
source: Inner(InnerInner), source: Inner(InnerInner),
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight1: (0, len).into(), highlight1: (0, len).into(),
highlight2: (10, 9).into(), highlight2: (10, 9).into(),
}; };
@ -444,7 +446,7 @@ fn multiple_multiline_highlights_adjacent() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label = "this bit here"] #[label = "this bit here"]
highlight1: SourceSpan, highlight1: SourceSpan,
#[label = "also this bit"] #[label = "also this bit"]
@ -453,7 +455,7 @@ fn multiple_multiline_highlights_adjacent() -> Result<(), MietteError> {
let src = "source\n text\n here\nmore here".to_string(); let src = "source\n text\n here\nmore here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight1: (0, 10).into(), highlight1: (0, 10).into(),
highlight2: (20, 6).into(), highlight2: (20, 6).into(),
}; };
@ -492,7 +494,7 @@ fn multiple_multiline_highlights_overlapping_lines() -> Result<(), MietteError>
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label = "this bit here"] #[label = "this bit here"]
highlight1: SourceSpan, highlight1: SourceSpan,
#[label = "also this bit"] #[label = "also this bit"]
@ -501,7 +503,7 @@ fn multiple_multiline_highlights_overlapping_lines() -> Result<(), MietteError>
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight1: (0, 8).into(), highlight1: (0, 8).into(),
highlight2: (9, 10).into(), highlight2: (9, 10).into(),
}; };
@ -520,7 +522,7 @@ fn multiple_multiline_highlights_overlapping_offsets() -> Result<(), MietteError
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label = "this bit here"] #[label = "this bit here"]
highlight1: SourceSpan, highlight1: SourceSpan,
#[label = "also this bit"] #[label = "also this bit"]
@ -529,7 +531,7 @@ fn multiple_multiline_highlights_overlapping_offsets() -> Result<(), MietteError
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight1: (0, 8).into(), highlight1: (0, 8).into(),
highlight2: (10, 10).into(), highlight2: (10, 10).into(),
}; };
@ -559,7 +561,7 @@ fn related() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
#[related] #[related]
@ -568,10 +570,10 @@ fn related() -> Result<(), MietteError> {
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src.clone()), src: MietteSourceCode::new(src.clone()).with_name("bad_file.rs"),
highlight: (9, 4).into(), highlight: (9, 4).into(),
related: vec![MyBad { related: vec![MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (0, 6).into(), highlight: (0, 6).into(),
related: vec![], related: vec![],
}], }],
@ -614,7 +616,7 @@ fn related_source_code_propagation() -> Result<(), MietteError> {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
#[related] #[related]
@ -631,7 +633,7 @@ fn related_source_code_propagation() -> Result<(), MietteError> {
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 4).into(), highlight: (9, 4).into(),
related: vec![InnerError { related: vec![InnerError {
highlight: (0, 6).into(), highlight: (0, 6).into(),

View File

@ -1,5 +1,5 @@
// Testing of the `diagnostic` attr used by derive(Diagnostic) // Testing of the `diagnostic` attr used by derive(Diagnostic)
use miette::{Diagnostic, LabeledSpan, NamedSource, SourceSpan}; use miette::{Diagnostic, LabeledSpan, MietteSourceCode, SourceSpan};
use thiserror::Error; use thiserror::Error;
#[test] #[test]
@ -10,7 +10,7 @@ fn enum_uses_base_attr() {
enum MyBad { enum MyBad {
Only { Only {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
}, },
@ -18,7 +18,7 @@ fn enum_uses_base_attr() {
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad::Only { let err = MyBad::Only {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 4).into(), highlight: (9, 4).into(),
}; };
assert_eq!(err.code().unwrap().to_string(), "error::on::base"); assert_eq!(err.code().unwrap().to_string(), "error::on::base");
@ -32,7 +32,7 @@ fn enum_uses_variant_attr() {
#[diagnostic(code(error::on::variant))] #[diagnostic(code(error::on::variant))]
Only { Only {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
}, },
@ -40,7 +40,7 @@ fn enum_uses_variant_attr() {
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad::Only { let err = MyBad::Only {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 4).into(), highlight: (9, 4).into(),
}; };
assert_eq!(err.code().unwrap().to_string(), "error::on::variant"); assert_eq!(err.code().unwrap().to_string(), "error::on::variant");
@ -55,7 +55,7 @@ fn multiple_attrs_allowed_on_item() {
enum MyBad { enum MyBad {
Only { Only {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
}, },
@ -63,7 +63,7 @@ fn multiple_attrs_allowed_on_item() {
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad::Only { let err = MyBad::Only {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 4).into(), highlight: (9, 4).into(),
}; };
assert_eq!(err.code().unwrap().to_string(), "error::on::base"); assert_eq!(err.code().unwrap().to_string(), "error::on::base");
@ -79,7 +79,7 @@ fn multiple_attrs_allowed_on_variant() {
#[diagnostic(help("try doing it correctly"))] #[diagnostic(help("try doing it correctly"))]
Only { Only {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
}, },
@ -87,7 +87,7 @@ fn multiple_attrs_allowed_on_variant() {
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad::Only { let err = MyBad::Only {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 4).into(), highlight: (9, 4).into(),
}; };
assert_eq!(err.code().unwrap().to_string(), "error::on::variant"); assert_eq!(err.code().unwrap().to_string(), "error::on::variant");
@ -104,7 +104,7 @@ fn attrs_can_be_split_between_item_and_variants() {
#[diagnostic(url("https://example.com/foo/bar"))] #[diagnostic(url("https://example.com/foo/bar"))]
Only { Only {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
}, },
@ -112,7 +112,7 @@ fn attrs_can_be_split_between_item_and_variants() {
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad::Only { let err = MyBad::Only {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 4).into(), highlight: (9, 4).into(),
}; };
assert_eq!(err.code().unwrap().to_string(), "error::on::base"); assert_eq!(err.code().unwrap().to_string(), "error::on::base");
@ -130,7 +130,7 @@ fn attr_not_required() {
enum MyBad { enum MyBad {
Only { Only {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
}, },
@ -138,7 +138,7 @@ fn attr_not_required() {
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad::Only { let err = MyBad::Only {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 4).into(), highlight: (9, 4).into(),
}; };
let err_span = err.labels().unwrap().next().unwrap(); let err_span = err.labels().unwrap().next().unwrap();

View File

@ -4,7 +4,7 @@ use std::{
}; };
// Testing of the `diagnostic` attr used by derive(Diagnostic) // Testing of the `diagnostic` attr used by derive(Diagnostic)
use miette::{Diagnostic, LabeledSpan, NamedSource, SourceSpan}; use miette::{Diagnostic, LabeledSpan, MietteSourceCode, SourceSpan};
use thiserror::Error; use thiserror::Error;
#[test] #[test]
@ -14,7 +14,7 @@ fn attr_collection_in_enum() {
enum MyBad { enum MyBad {
Only { Only {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
#[label(collection, "and here")] #[label(collection, "and here")]
@ -24,7 +24,7 @@ fn attr_collection_in_enum() {
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad::Only { let err = MyBad::Only {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 4).into(), highlight: (9, 4).into(),
highlight2: vec![(1, 2).into(), (3, 4).into()], highlight2: vec![(1, 2).into(), (3, 4).into()],
}; };
@ -46,7 +46,7 @@ fn attr_collection_in_struct() {
#[error("oops!")] #[error("oops!")]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
#[label(collection, "and here")] #[label(collection, "and here")]
@ -55,7 +55,7 @@ fn attr_collection_in_struct() {
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 4).into(), highlight: (9, 4).into(),
highlight2: vec![(1, 2).into(), (3, 4).into()], highlight2: vec![(1, 2).into(), (3, 4).into()],
}; };
@ -77,7 +77,7 @@ fn attr_collection_as_deque() {
#[error("oops!")] #[error("oops!")]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
#[label(collection, "and here")] #[label(collection, "and here")]
@ -86,7 +86,7 @@ fn attr_collection_as_deque() {
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 4).into(), highlight: (9, 4).into(),
highlight2: VecDeque::from([(1, 2).into(), (3, 4).into()]), highlight2: VecDeque::from([(1, 2).into(), (3, 4).into()]),
}; };
@ -108,7 +108,7 @@ fn attr_collection_as_linked_list() {
#[error("oops!")] #[error("oops!")]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
#[label(collection, "and here")] #[label(collection, "and here")]
@ -117,7 +117,7 @@ fn attr_collection_as_linked_list() {
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 4).into(), highlight: (9, 4).into(),
highlight2: LinkedList::from([(1, 2).into(), (3, 4).into()]), highlight2: LinkedList::from([(1, 2).into(), (3, 4).into()]),
}; };
@ -139,7 +139,7 @@ fn attr_collection_of_tuple() {
#[error("oops!")] #[error("oops!")]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
#[label(collection, "and here")] #[label(collection, "and here")]
@ -148,7 +148,7 @@ fn attr_collection_of_tuple() {
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 4).into(), highlight: (9, 4).into(),
highlight2: vec![(1, 2), (3, 4)], highlight2: vec![(1, 2), (3, 4)],
}; };
@ -170,7 +170,7 @@ fn attr_collection_of_range() {
#[error("oops!")] #[error("oops!")]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
#[label(collection, "and here")] #[label(collection, "and here")]
@ -179,7 +179,7 @@ fn attr_collection_of_range() {
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 4).into(), highlight: (9, 4).into(),
highlight2: vec![1..3, 3..7], highlight2: vec![1..3, 3..7],
}; };
@ -201,7 +201,7 @@ fn attr_collection_of_labeled_span_in_struct() {
#[error("oops!")] #[error("oops!")]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
#[label(collection, "then there")] #[label(collection, "then there")]
@ -210,7 +210,7 @@ fn attr_collection_of_labeled_span_in_struct() {
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 4).into(), highlight: (9, 4).into(),
highlight2: vec![ highlight2: vec![
LabeledSpan::new_with_span(Some("continuing here".to_string()), (1, 2)), LabeledSpan::new_with_span(Some("continuing here".to_string()), (1, 2)),
@ -236,7 +236,7 @@ fn attr_collection_of_labeled_span_in_enum() {
enum MyBad { enum MyBad {
Only { Only {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
#[label(collection, "then there")] #[label(collection, "then there")]
@ -246,7 +246,7 @@ fn attr_collection_of_labeled_span_in_enum() {
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad::Only { let err = MyBad::Only {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 4).into(), highlight: (9, 4).into(),
highlight2: vec![ highlight2: vec![
LabeledSpan::new_with_span(Some("continuing here".to_string()), (1, 2)), LabeledSpan::new_with_span(Some("continuing here".to_string()), (1, 2)),
@ -271,7 +271,7 @@ fn attr_collection_multi() {
#[error("oops!")] #[error("oops!")]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
#[label(collection, "and here")] #[label(collection, "and here")]
@ -282,7 +282,7 @@ fn attr_collection_multi() {
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 4).into(), highlight: (9, 4).into(),
highlight2: vec![(1, 2).into(), (3, 4).into()], highlight2: vec![(1, 2).into(), (3, 4).into()],
highlight3: vec![(5, 6).into(), (7, 8).into()], highlight3: vec![(5, 6).into(), (7, 8).into()],

View File

@ -1,5 +1,5 @@
mod json_report_handler { mod json_report_handler {
use miette::{Diagnostic, MietteError, NamedSource, Report, SourceSpan}; use miette::{Diagnostic, MietteError, MietteSourceCode, Report, SourceSpan};
use miette::JSONReportHandler; use miette::JSONReportHandler;
@ -20,14 +20,14 @@ mod json_report_handler {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
} }
let src = "source\n 👼🏼text\n here".to_string(); let src = "source\n 👼🏼text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 6).into(), highlight: (9, 6).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -65,14 +65,14 @@ mod json_report_handler {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
} }
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 4).into(), highlight: (9, 4).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -110,14 +110,14 @@ mod json_report_handler {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
} }
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (0, 0).into(), highlight: (0, 0).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -155,14 +155,14 @@ mod json_report_handler {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
} }
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 0).into(), highlight: (9, 0).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -200,14 +200,14 @@ mod json_report_handler {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label] #[label]
highlight: SourceSpan, highlight: SourceSpan,
} }
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 4).into(), highlight: (9, 4).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -244,14 +244,14 @@ mod json_report_handler {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
} }
let src = "source\ntext\n here".to_string(); let src = "source\ntext\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (7, 4).into(), highlight: (7, 4).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -289,7 +289,7 @@ mod json_report_handler {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label = "x"] #[label = "x"]
highlight1: SourceSpan, highlight1: SourceSpan,
#[label = "y"] #[label = "y"]
@ -300,7 +300,7 @@ mod json_report_handler {
let src = "source\n text text text text text\n here".to_string(); let src = "source\n text text text text text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight1: (9, 4).into(), highlight1: (9, 4).into(),
highlight2: (14, 4).into(), highlight2: (14, 4).into(),
highlight3: (24, 4).into(), highlight3: (24, 4).into(),
@ -354,14 +354,14 @@ mod json_report_handler {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label = "these two lines"] #[label = "these two lines"]
highlight: SourceSpan, highlight: SourceSpan,
} }
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 11).into(), highlight: (9, 11).into(),
}; };
let out = fmt_report(err.into()); let out = fmt_report(err.into());
@ -399,7 +399,7 @@ mod json_report_handler {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label = "block 1"] #[label = "block 1"]
highlight1: SourceSpan, highlight1: SourceSpan,
#[label = "block 2"] #[label = "block 2"]
@ -415,7 +415,7 @@ mod json_report_handler {
.to_string(); .to_string();
let len = src.len(); let len = src.len();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight1: (0, len).into(), highlight1: (0, len).into(),
highlight2: (10, 9).into(), highlight2: (10, 9).into(),
}; };
@ -463,7 +463,7 @@ mod json_report_handler {
#[source] #[source]
source: Inner, source: Inner,
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label = "block 1"] #[label = "block 1"]
highlight1: SourceSpan, highlight1: SourceSpan,
#[label] #[label]
@ -488,7 +488,7 @@ mod json_report_handler {
let len = src.len(); let len = src.len();
let err = MyBad { let err = MyBad {
source: Inner(InnerInner), source: Inner(InnerInner),
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight1: (0, len).into(), highlight1: (0, len).into(),
highlight2: (10, 9).into(), highlight2: (10, 9).into(),
}; };
@ -536,7 +536,7 @@ mod json_report_handler {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label = "this bit here"] #[label = "this bit here"]
highlight1: SourceSpan, highlight1: SourceSpan,
#[label = "also this bit"] #[label = "also this bit"]
@ -545,7 +545,7 @@ mod json_report_handler {
let src = "source\n text\n here\nmore here".to_string(); let src = "source\n text\n here\nmore here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight1: (0, 10).into(), highlight1: (0, 10).into(),
highlight2: (20, 6).into(), highlight2: (20, 6).into(),
}; };
@ -591,7 +591,7 @@ mod json_report_handler {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label = "this bit here"] #[label = "this bit here"]
highlight1: SourceSpan, highlight1: SourceSpan,
#[label = "also this bit"] #[label = "also this bit"]
@ -600,7 +600,7 @@ mod json_report_handler {
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight1: (0, 8).into(), highlight1: (0, 8).into(),
highlight2: (9, 10).into(), highlight2: (9, 10).into(),
}; };
@ -646,7 +646,7 @@ mod json_report_handler {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label = "this bit here"] #[label = "this bit here"]
highlight1: SourceSpan, highlight1: SourceSpan,
#[label = "also this bit"] #[label = "also this bit"]
@ -655,7 +655,7 @@ mod json_report_handler {
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight1: (0, 8).into(), highlight1: (0, 8).into(),
highlight2: (10, 10).into(), highlight2: (10, 10).into(),
}; };
@ -728,7 +728,7 @@ mod json_report_handler {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
#[related] #[related]
@ -737,16 +737,16 @@ mod json_report_handler {
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src.clone()), src: MietteSourceCode::new(src.clone()).with_name("bad_file.rs"),
highlight: (9, 4).into(), highlight: (9, 4).into(),
related: vec![ related: vec![
MyBad { MyBad {
src: NamedSource::new("bad_file2.rs", src.clone()), src: MietteSourceCode::new(src.clone()).with_name("bad_file2.rs"),
highlight: (0, 6).into(), highlight: (0, 6).into(),
related: vec![], related: vec![],
}, },
MyBad { MyBad {
src: NamedSource::new("bad_file3.rs", src), src: MietteSourceCode::new(src).with_name("bad_file3.rs"),
highlight: (0, 6).into(), highlight: (0, 6).into(),
related: vec![], related: vec![],
}, },
@ -821,7 +821,7 @@ mod json_report_handler {
#[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))]
struct MyBad { struct MyBad {
#[source_code] #[source_code]
src: NamedSource<String>, src: MietteSourceCode<String>,
#[label("this bit here")] #[label("this bit here")]
highlight: SourceSpan, highlight: SourceSpan,
#[related] #[related]
@ -838,7 +838,7 @@ mod json_report_handler {
let src = "source\n text\n here".to_string(); let src = "source\n text\n here".to_string();
let err = MyBad { let err = MyBad {
src: NamedSource::new("bad_file.rs", src), src: MietteSourceCode::new(src).with_name("bad_file.rs"),
highlight: (9, 4).into(), highlight: (9, 4).into(),
related: vec![ related: vec![
InnerError { InnerError {