Skip to content

Commit

Permalink
feat(source-code): Don't override provided source code (#300)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: Source code is no longer overridden if it was provided by the diagnostic's own `source_code()` impl.
  • Loading branch information
gavrilikhin-d authored Feb 4, 2024
1 parent c0a298e commit 0d5c2ce
Showing 1 changed file with 87 additions and 2 deletions.
89 changes: 87 additions & 2 deletions src/eyreish/wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ impl<E: Diagnostic, C: SourceCode> Diagnostic for WithSourceCode<E, C> {
}

fn source_code(&self) -> Option<&dyn miette::SourceCode> {
Some(&self.source_code)
self.error.source_code().or(Some(&self.source_code))
}

fn related<'a>(&'a self) -> Option<Box<dyn Iterator<Item = &'a dyn Diagnostic> + 'a>> {
Expand Down Expand Up @@ -197,7 +197,7 @@ impl<C: SourceCode> Diagnostic for WithSourceCode<Report, C> {
}

fn source_code(&self) -> Option<&dyn miette::SourceCode> {
Some(&self.source_code)
self.error.source_code().or(Some(&self.source_code))
}

fn related<'a>(&'a self) -> Option<Box<dyn Iterator<Item = &'a dyn Diagnostic> + 'a>> {
Expand Down Expand Up @@ -232,3 +232,88 @@ impl<C> StdError for WithSourceCode<Report, C> {
self.error.source()
}
}

#[cfg(test)]
mod tests {
use thiserror::Error;

use crate::{Diagnostic, LabeledSpan, Report, SourceCode, SourceSpan};

#[derive(Error, Debug)]
#[error("inner")]
struct Inner {
pub(crate) at: SourceSpan,
pub(crate) source_code: Option<String>,
}

impl Diagnostic for Inner {
fn labels(&self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + '_>> {
Some(Box::new(std::iter::once(LabeledSpan::underline(self.at))))
}

fn source_code(&self) -> Option<&dyn SourceCode> {
self.source_code.as_ref().map(|s| s as _)
}
}

#[derive(Error, Debug)]
#[error("outer")]
struct Outer {
pub(crate) errors: Vec<Inner>,
}

impl Diagnostic for Outer {
fn related<'a>(&'a self) -> Option<Box<dyn Iterator<Item = &'a dyn Diagnostic> + 'a>> {
Some(Box::new(self.errors.iter().map(|e| e as _)))
}
}

#[test]
fn no_override() {
let inner_source = "hello world";
let outer_source = "abc";

let report = Report::from(Inner {
at: (0..5).into(),
source_code: Some(inner_source.to_string()),
})
.with_source_code(outer_source.to_string());

let underlined = String::from_utf8(
report
.source_code()
.unwrap()
.read_span(&(0..5).into(), 0, 0)
.unwrap()
.data()
.to_vec(),
)
.unwrap();
assert_eq!(underlined, "hello");
}

#[test]
#[cfg(feature = "fancy")]
fn two_source_codes() {
let inner_source = "hello world";
let outer_source = "abc";

let report = Report::from(Outer {
errors: vec![
Inner {
at: (0..5).into(),
source_code: Some(inner_source.to_string()),
},
Inner {
at: (1..2).into(),
source_code: None,
},
],
})
.with_source_code(outer_source.to_string());

let message = format!("{:?}", report);
assert!(message.contains(inner_source));
assert!(message.contains(outer_source));
}
}

0 comments on commit 0d5c2ce

Please sign in to comment.