Skip to content

Commit

Permalink
fix(graphical): fix nested error wrapping (#358)
Browse files Browse the repository at this point in the history
Fixes: #333
  • Loading branch information
TheLostLambda committed Mar 27, 2024
1 parent ca646f3 commit 3eabbce
Show file tree
Hide file tree
Showing 5 changed files with 200 additions and 72 deletions.
41 changes: 0 additions & 41 deletions src/eyreish/wrapper.rs
Expand Up @@ -6,35 +6,9 @@ use crate::{Diagnostic, LabeledSpan, Report, SourceCode};

use crate as miette;

#[repr(transparent)]
pub(crate) struct DisplayError<M>(pub(crate) M);

#[repr(transparent)]
pub(crate) struct MessageError<M>(pub(crate) M);

pub(crate) struct NoneError;

impl<M> Debug for DisplayError<M>
where
M: Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Display::fmt(&self.0, f)
}
}

impl<M> Display for DisplayError<M>
where
M: Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Display::fmt(&self.0, f)
}
}

impl<M> StdError for DisplayError<M> where M: Display + 'static {}
impl<M> Diagnostic for DisplayError<M> where M: Display + 'static {}

impl<M> Debug for MessageError<M>
where
M: Display + Debug,
Expand All @@ -56,21 +30,6 @@ where
impl<M> StdError for MessageError<M> where M: Display + Debug + 'static {}
impl<M> Diagnostic for MessageError<M> where M: Display + Debug + 'static {}

impl Debug for NoneError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Debug::fmt("Option was None", f)
}
}

impl Display for NoneError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Display::fmt("Option was None", f)
}
}

impl StdError for NoneError {}
impl Diagnostic for NoneError {}

#[repr(transparent)]
pub(crate) struct BoxedError(pub(crate) Box<dyn Diagnostic + Send + Sync>);

Expand Down
15 changes: 9 additions & 6 deletions src/handlers/graphical.rs
@@ -1,7 +1,7 @@
use std::fmt::{self, Write};

use owo_colors::{OwoColorize, Style, StyledList};
use unicode_width::UnicodeWidthChar;
use unicode_width::{UnicodeWidthChar, UnicodeWidthStr};

use crate::diagnostic_chain::{DiagnosticChain, ErrorKind};
use crate::handlers::theme::*;
Expand Down Expand Up @@ -225,7 +225,7 @@ impl GraphicalReportHandler {
self.render_related(f, diagnostic, src)?;
if let Some(footer) = &self.footer {
writeln!(f)?;
let width = self.termwidth.saturating_sub(4);
let width = self.termwidth.saturating_sub(2);
let mut opts = textwrap::Options::new(width)
.initial_indent(" ")
.subsequent_indent(" ")
Expand Down Expand Up @@ -265,16 +265,15 @@ impl GraphicalReportHandler {
);
write!(header, "{}", link)?;
writeln!(f, "{}", header)?;
writeln!(f)?;
} else if let Some(code) = diagnostic.code() {
write!(header, "{}", code.style(severity_style),)?;
if self.links == LinkStyle::Text && diagnostic.url().is_some() {
let url = diagnostic.url().unwrap(); // safe
write!(header, " ({})", url.style(self.theme.styles.link))?;
}
writeln!(f, "{}", header)?;
writeln!(f)?;
}
writeln!(f)?;
Ok(())
}

Expand Down Expand Up @@ -354,8 +353,12 @@ impl GraphicalReportHandler {
inner_renderer.footer = None;
// Cause chains are already flattened, so don't double-print the nested error
inner_renderer.with_cause_chain = false;
// Since everything from here on is indented, shrink the virtual terminal
inner_renderer.termwidth -= rest_indent.width();
inner_renderer.render_report(&mut inner, diag)?;

// If there was no header, remove the leading newline
let inner = inner.trim_start_matches('\n');
writeln!(f, "{}", self.wrap(&inner, opts))?;
}
ErrorKind::StdError(err) => {
Expand All @@ -370,7 +373,7 @@ impl GraphicalReportHandler {

fn render_footer(&self, f: &mut impl fmt::Write, diagnostic: &(dyn Diagnostic)) -> fmt::Result {
if let Some(help) = diagnostic.help() {
let width = self.termwidth.saturating_sub(4);
let width = self.termwidth.saturating_sub(2);
let initial_indent = " help: ".style(self.theme.styles.help).to_string();
let mut opts = textwrap::Options::new(width)
.initial_indent(&initial_indent)
Expand Down Expand Up @@ -398,8 +401,8 @@ impl GraphicalReportHandler {
let mut inner_renderer = self.clone();
// Re-enable the printing of nested cause chains for related errors
inner_renderer.with_cause_chain = true;
writeln!(f)?;
for rel in related {
writeln!(f)?;
match rel.severity() {
Some(Severity::Error) | None => write!(f, "Error: ")?,
Some(Severity::Warning) => write!(f, "Warning: ")?,
Expand Down
6 changes: 6 additions & 0 deletions tests/derive.rs
Expand Up @@ -6,12 +6,14 @@ fn related() {
#[derive(Error, Debug, Diagnostic)]
#[error("welp")]
#[diagnostic(code(foo::bar::baz))]
#[allow(dead_code)]
struct Foo {
#[related]
related: Vec<Baz>,
}

#[derive(Error, Debug, Diagnostic)]
#[allow(dead_code)]
enum Bar {
#[error("variant1")]
#[diagnostic(code(foo::bar::baz))]
Expand All @@ -29,6 +31,7 @@ fn related() {

#[derive(Error, Debug, Diagnostic)]
#[error("welp2")]
#[allow(dead_code)]
struct Baz;
}

Expand All @@ -37,6 +40,7 @@ fn related_report() {
#[derive(Error, Debug, Diagnostic)]
#[error("welp")]
#[diagnostic(code(foo::bar::baz))]
#[allow(dead_code)]
struct Foo {
#[related]
related: Vec<Report>,
Expand Down Expand Up @@ -288,6 +292,7 @@ fn test_snippet_named_struct() {
#[derive(Debug, Diagnostic, Error)]
#[error("welp")]
#[diagnostic(code(foo::bar::baz))]
#[allow(dead_code)]
struct Foo<'a> {
#[source_code]
src: &'a str,
Expand All @@ -310,6 +315,7 @@ fn test_snippet_unnamed_struct() {
#[derive(Debug, Diagnostic, Error)]
#[error("welp")]
#[diagnostic(code(foo::bar::baz))]
#[allow(dead_code)]
struct Foo<'a>(
#[source_code] &'a str,
#[label("{0}")] SourceSpan,
Expand Down

0 comments on commit 3eabbce

Please sign in to comment.