mirror of https://github.com/zkat/miette.git
feat(protocol): improvements to snippets API
This commit is contained in:
parent
80e7dabbe4
commit
3584dc600c
|
|
@ -4,7 +4,7 @@ that you can implement to get access to miette's (and related library's) full
|
|||
reporting and such features.
|
||||
*/
|
||||
|
||||
use std::fmt::Display;
|
||||
use std::{fmt::Display, sync::Arc};
|
||||
|
||||
use crate::MietteError;
|
||||
|
||||
|
|
@ -36,14 +36,16 @@ pub trait Diagnostic: std::error::Error {
|
|||
|
||||
/// Additional contextual snippets. This is typically used for adding
|
||||
/// marked-up source file output the way compilers often do.
|
||||
fn snippets(&self) -> Option<&[DiagnosticSnippet]> {
|
||||
fn snippets(&self) -> Option<Box<dyn Iterator<Item = DiagnosticSnippet>>> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for Box<dyn Diagnostic> {}
|
||||
|
||||
impl<T: Diagnostic + Send + Sync + 'static> From<T> for Box<dyn Diagnostic + Send + Sync + 'static> {
|
||||
impl<T: Diagnostic + Send + Sync + 'static> From<T>
|
||||
for Box<dyn Diagnostic + Send + Sync + 'static>
|
||||
{
|
||||
fn from(diag: T) -> Self {
|
||||
Box::new(diag)
|
||||
}
|
||||
|
|
@ -112,8 +114,10 @@ support Sources which are gigabytes or larger in size.
|
|||
*/
|
||||
pub trait Source: std::fmt::Debug + Send + Sync + 'static {
|
||||
/// Read the bytes for a specific span from this Source.
|
||||
fn read_span<'a>(&'a self, span: &SourceSpan)
|
||||
-> Result<Box<dyn SpanContents + 'a>, MietteError>;
|
||||
fn read_span<'a>(
|
||||
&'a self,
|
||||
span: &SourceSpan,
|
||||
) -> Result<Box<dyn SpanContents + 'a>, MietteError>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -166,14 +170,14 @@ impl<'a> SpanContents for MietteSpanContents<'a> {
|
|||
/**
|
||||
A snippet from a [Source] to be displayed with a message and possibly some highlights.
|
||||
*/
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct DiagnosticSnippet {
|
||||
/// Explanation of this specific diagnostic snippet.
|
||||
pub message: Option<String>,
|
||||
/// The "filename" for this snippet.
|
||||
pub source_name: String,
|
||||
/// A [Source] that can be used to read the actual text of a source.
|
||||
pub source: Box<dyn Source>,
|
||||
pub source: Arc<dyn Source>,
|
||||
/// The primary [SourceSpan] where this diagnostic is located.
|
||||
pub context: SourceSpan,
|
||||
/// Additional [SourceSpan]s that mark specific sections of the span, for
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use std::fmt;
|
|||
use indenter::indented;
|
||||
|
||||
use crate::chain::Chain;
|
||||
use crate::protocol::{Diagnostic, DiagnosticSnippet, DiagnosticReporter, Severity};
|
||||
use crate::protocol::{Diagnostic, DiagnosticReporter, DiagnosticSnippet, Severity};
|
||||
|
||||
/**
|
||||
Reference implementation of the [DiagnosticReporter] trait. This is generally
|
||||
|
|
@ -17,7 +17,11 @@ you want custom reporting for your tool or app.
|
|||
pub struct MietteReporter;
|
||||
|
||||
impl MietteReporter {
|
||||
fn render_snippet(&self, f: &mut fmt::Formatter<'_>, snippet: &DiagnosticSnippet) -> fmt::Result {
|
||||
fn render_snippet(
|
||||
&self,
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
snippet: &DiagnosticSnippet,
|
||||
) -> fmt::Result {
|
||||
use fmt::Write as _;
|
||||
write!(f, "\n[{}]", snippet.source_name)?;
|
||||
if let Some(msg) = &snippet.message {
|
||||
|
|
@ -126,7 +130,7 @@ impl DiagnosticReporter for MietteReporter {
|
|||
if let Some(snippets) = diagnostic.snippets() {
|
||||
writeln!(f)?;
|
||||
for snippet in snippets {
|
||||
self.render_snippet(f, snippet)?;
|
||||
self.render_snippet(f, &snippet)?;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -166,7 +170,7 @@ impl DiagnosticReporter for JokeReporter {
|
|||
"miette, her eyes enormous: you {} miette? you {}? oh! oh! jail for mother! jail for mother for One Thousand Years!!!!",
|
||||
diagnostic.code(),
|
||||
diagnostic.snippets().map(|snippets| {
|
||||
snippets.iter().map(|snippet| snippet.message.clone()).collect::<Option<Vec<String>>>()
|
||||
snippets.map(|snippet| snippet.message).collect::<Option<Vec<String>>>()
|
||||
}).flatten().map(|x| x.join(", ")).unwrap_or_else(||"try and cause miette to panic".into())
|
||||
)?;
|
||||
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ impl Diagnostic for MyBad {
|
|||
Some(&"try doing it better next time?")
|
||||
}
|
||||
|
||||
fn snippets(&self) -> Option<&[DiagnosticSnippet]> {
|
||||
Some(&self.snippets)
|
||||
fn snippets(&self) -> Option<Box<dyn Iterator<Item = DiagnosticSnippet>>> {
|
||||
Some(Box::new(self.snippets.clone().into_iter()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -48,20 +48,22 @@ fn basic() -> Result<(), MietteError> {
|
|||
#[test]
|
||||
fn fancy() -> Result<(), MietteError> {
|
||||
let src = "source\n text\n here".to_string();
|
||||
let len = src.len();
|
||||
let err = MyBad {
|
||||
snippets: vec![DiagnosticSnippet {
|
||||
message: Some("This is the part that broke".into()),
|
||||
source_name: "bad_file.rs".into(),
|
||||
source: Box::new(src.clone()),
|
||||
highlights: Some(vec![
|
||||
("this bit here".into(), SourceSpan {
|
||||
source: Arc::new(src),
|
||||
highlights: Some(vec![(
|
||||
"this bit here".into(),
|
||||
SourceSpan {
|
||||
start: 9.into(),
|
||||
end: 12.into(),
|
||||
})
|
||||
]),
|
||||
},
|
||||
)]),
|
||||
context: SourceSpan {
|
||||
start: 0.into(),
|
||||
end: (src.len() - 1).into(),
|
||||
end: (len - 1).into(),
|
||||
},
|
||||
}],
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue