Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!(render): render_report can accept more types #371

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/handlers/debug.rs
@@ -1,6 +1,6 @@
use std::fmt;

use crate::{protocol::Diagnostic, ReportHandler};
use crate::{protocol::Diagnostic, AsDiagnostic, ReportHandler};

/**
[`ReportHandler`] that renders plain text and avoids extraneous graphics.
Expand Down Expand Up @@ -31,8 +31,9 @@ impl DebugReportHandler {
pub fn render_report(
&self,
f: &mut fmt::Formatter<'_>,
diagnostic: &(dyn Diagnostic),
diagnostic: impl AsDiagnostic,
) -> fmt::Result {
let diagnostic = diagnostic.as_dyn();
let mut diag = f.debug_struct("Diagnostic");
diag.field("message", &format!("{}", diagnostic));
if let Some(code) = diagnostic.code() {
Expand Down
5 changes: 3 additions & 2 deletions src/handlers/graphical.rs
Expand Up @@ -7,7 +7,7 @@ use crate::diagnostic_chain::{DiagnosticChain, ErrorKind};
use crate::handlers::theme::*;
use crate::highlighters::{Highlighter, MietteHighlighter};
use crate::protocol::{Diagnostic, Severity};
use crate::{LabeledSpan, ReportHandler, SourceCode, SourceSpan, SpanContents};
use crate::{AsDiagnostic, LabeledSpan, ReportHandler, SourceCode, SourceSpan, SpanContents};

/**
A [`ReportHandler`] that displays a given [`Report`](crate::Report) in a
Expand Down Expand Up @@ -215,8 +215,9 @@ impl GraphicalReportHandler {
pub fn render_report(
&self,
f: &mut impl fmt::Write,
diagnostic: &(dyn Diagnostic),
diagnostic: impl AsDiagnostic,
) -> fmt::Result {
let diagnostic = diagnostic.as_dyn();
self.render_header(f, diagnostic)?;
self.render_causes(f, diagnostic)?;
let src = diagnostic.source_code();
Expand Down
6 changes: 4 additions & 2 deletions src/handlers/json.rs
@@ -1,7 +1,8 @@
use std::fmt::{self, Write};

use crate::{
diagnostic_chain::DiagnosticChain, protocol::Diagnostic, ReportHandler, Severity, SourceCode,
diagnostic_chain::DiagnosticChain, protocol::Diagnostic, AsDiagnostic, ReportHandler, Severity,
SourceCode,
};

/**
Expand Down Expand Up @@ -60,8 +61,9 @@ impl JSONReportHandler {
pub fn render_report(
&self,
f: &mut impl fmt::Write,
diagnostic: &(dyn Diagnostic),
diagnostic: impl AsDiagnostic,
) -> fmt::Result {
let diagnostic = diagnostic.as_dyn();
self._render_report(f, diagnostic, None)
}

Expand Down
7 changes: 5 additions & 2 deletions src/handlers/narratable.rs
Expand Up @@ -4,7 +4,9 @@ use unicode_width::{UnicodeWidthChar, UnicodeWidthStr};

use crate::diagnostic_chain::DiagnosticChain;
use crate::protocol::{Diagnostic, Severity};
use crate::{LabeledSpan, MietteError, ReportHandler, SourceCode, SourceSpan, SpanContents};
use crate::{
AsDiagnostic, LabeledSpan, MietteError, ReportHandler, SourceCode, SourceSpan, SpanContents,
};

/**
[`ReportHandler`] that renders plain text and avoids extraneous graphics.
Expand Down Expand Up @@ -69,8 +71,9 @@ impl NarratableReportHandler {
pub fn render_report(
&self,
f: &mut impl fmt::Write,
diagnostic: &(dyn Diagnostic),
diagnostic: impl AsDiagnostic,
) -> fmt::Result {
let diagnostic = diagnostic.as_dyn();
self.render_header(f, diagnostic)?;
if self.with_cause_chain {
self.render_causes(f, diagnostic)?;
Expand Down
82 changes: 81 additions & 1 deletion src/protocol.rs
Expand Up @@ -12,7 +12,7 @@ use std::{
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

use crate::MietteError;
use crate::{MietteError, Report};

/// Adds rich metadata to your Error that can be used by
/// [`Report`](crate::Report) to print really nice and human-friendly error
Expand Down Expand Up @@ -69,6 +69,48 @@ pub trait Diagnostic: std::error::Error {
}
}

macro_rules! blanket_ref_impls {
($($ref_type:ty),+ $(,)?) => {
$(
impl<T: Diagnostic> Diagnostic for $ref_type {
fn code<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
(**self).code()
}

fn severity(&self) -> Option<Severity> {
(**self).severity()
}

fn help<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
(**self).help()
}

fn url<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
(**self).url()
}

fn source_code(&self) -> Option<&dyn SourceCode> {
(**self).source_code()
}

fn labels(&self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + '_>> {
(**self).labels()
}

fn related<'a>(&'a self) -> Option<Box<dyn Iterator<Item = &'a dyn Diagnostic> + 'a>> {
(**self).related()
}

fn diagnostic_source(&self) -> Option<&dyn Diagnostic> {
(**self).diagnostic_source()
}
}
)+
};
}

blanket_ref_impls!(&T, Box<T>);

macro_rules! box_error_impls {
($($box_type:ty),*) => {
$(
Expand Down Expand Up @@ -189,6 +231,44 @@ impl From<Box<dyn std::error::Error + Send + Sync>> for Box<dyn Diagnostic + Sen
}
}

/// WOOF
pub trait AsDiagnostic {
/// BARK
fn as_dyn(&self) -> &dyn Diagnostic;
}

impl AsDiagnostic for &dyn Diagnostic {
fn as_dyn(&self) -> &dyn Diagnostic {
*self
}
}

impl AsDiagnostic for Report {
fn as_dyn(&self) -> &dyn Diagnostic {
self.as_ref()
}
}

macro_rules! blanket_ref_impls {
($($ref_type:ty),+ $(,)?) => {
$(
impl AsDiagnostic for $ref_type {
fn as_dyn(&self) -> &dyn Diagnostic {
(**self).as_dyn()
}
}
)+
};
}

blanket_ref_impls!(&Report, &mut Report, Box<Report>);

impl<T: Diagnostic> AsDiagnostic for T {
fn as_dyn(&self) -> &dyn Diagnostic {
self
}
}

/**
[`Diagnostic`] severity. Intended to be used by
[`ReportHandler`](crate::ReportHandler)s to change the way different
Expand Down
10 changes: 5 additions & 5 deletions tests/graphical.rs
Expand Up @@ -13,24 +13,24 @@ fn fmt_report(diag: Report) -> String {
GraphicalReportHandler::new_themed(GraphicalTheme::unicode())
.with_width(80)
.with_footer("this is a footer".into())
.render_report(&mut out, diag.as_ref())
.render_report(&mut out, &diag)
.unwrap();
} else if std::env::var("NARRATED").is_ok() {
NarratableReportHandler::new()
.render_report(&mut out, diag.as_ref())
.render_report(&mut out, diag)
.unwrap();
} else if let Ok(w) = std::env::var("REPLACE_TABS") {
GraphicalReportHandler::new_themed(GraphicalTheme::unicode_nocolor())
.without_syntax_highlighting()
.with_width(80)
.tab_width(w.parse().expect("Invalid tab width."))
.render_report(&mut out, diag.as_ref())
.render_report(&mut out, &diag)
.unwrap();
} else {
GraphicalReportHandler::new_themed(GraphicalTheme::unicode_nocolor())
.without_syntax_highlighting()
.with_width(80)
.render_report(&mut out, diag.as_ref())
.render_report(&mut out, &diag)
.unwrap();
};
out
Expand All @@ -46,7 +46,7 @@ fn fmt_report_with_settings(
GraphicalTheme::unicode_nocolor(),
));

handler.render_report(&mut out, diag.as_ref()).unwrap();
handler.render_report(&mut out, diag).unwrap();

println!("Error:\n```\n{}\n```", out);

Expand Down
4 changes: 2 additions & 2 deletions tests/narrated.rs
Expand Up @@ -12,11 +12,11 @@ fn fmt_report(diag: Report) -> String {
if cfg!(feature = "fancy-no-backtrace") && std::env::var("STYLE").is_ok() {
#[cfg(feature = "fancy-no-backtrace")]
GraphicalReportHandler::new_themed(GraphicalTheme::unicode())
.render_report(&mut out, diag.as_ref())
.render_report(&mut out, diag)
.unwrap();
} else {
NarratableReportHandler::new()
.render_report(&mut out, diag.as_ref())
.render_report(&mut out, diag)
.unwrap();
};
out
Expand Down
13 changes: 13 additions & 0 deletions tests/test_blanket.rs
@@ -0,0 +1,13 @@
use miette::{Diagnostic, MietteDiagnostic};

fn assert_diagnostic<T: Diagnostic>() {}

#[test]
fn test_ref() {
assert_diagnostic::<&MietteDiagnostic>()
}

#[test]
fn test_box() {
assert_diagnostic::<Box<MietteDiagnostic>>()
}
2 changes: 1 addition & 1 deletion tests/test_json.rs
Expand Up @@ -8,7 +8,7 @@ mod json_report_handler {
fn fmt_report(diag: Report) -> String {
let mut out = String::new();
JSONReportHandler::new()
.render_report(&mut out, diag.as_ref())
.render_report(&mut out, diag)
.unwrap();
out
}
Expand Down