From 3584dc600c2b8b0f84a2a0c59856da9a9dc7fbab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Sat, 7 Aug 2021 22:59:20 -0400 Subject: [PATCH] feat(protocol): improvements to snippets API --- src/protocol.rs | 18 +++++++++++------- src/reporter.rs | 12 ++++++++---- tests/reporter.rs | 18 ++++++++++-------- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/protocol.rs b/src/protocol.rs index 2c192f1..ceebf6d 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -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>> { None } } impl std::error::Error for Box {} -impl From for Box { +impl From + for Box +{ 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, MietteError>; + fn read_span<'a>( + &'a self, + span: &SourceSpan, + ) -> Result, 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, /// 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, + pub source: Arc, /// The primary [SourceSpan] where this diagnostic is located. pub context: SourceSpan, /// Additional [SourceSpan]s that mark specific sections of the span, for diff --git a/src/reporter.rs b/src/reporter.rs index bcebf9e..6fb4e0e 100644 --- a/src/reporter.rs +++ b/src/reporter.rs @@ -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::>>() + snippets.map(|snippet| snippet.message).collect::>>() }).flatten().map(|x| x.join(", ")).unwrap_or_else(||"try and cause miette to panic".into()) )?; diff --git a/tests/reporter.rs b/tests/reporter.rs index 7fa2653..56dd539 100644 --- a/tests/reporter.rs +++ b/tests/reporter.rs @@ -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>> { + 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(), }, }], };