This commit is contained in:
RandomScientist 2026-06-03 13:58:11 +09:00 committed by GitHub
commit 5dd6186538
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 64 additions and 34 deletions

View File

@ -1303,7 +1303,7 @@ impl GraphicalReportHandler {
&'a self, &'a self,
source: &'a dyn SourceCode, source: &'a dyn SourceCode,
context_span: &'a SourceSpan, context_span: &'a SourceSpan,
) -> Result<(Box<dyn SpanContents<'a> + 'a>, Vec<Line>), fmt::Error> { ) -> Result<(Box<dyn SpanContents + 'a>, Vec<Line>), fmt::Error> {
let context_data = source let context_data = source
.read_span(context_span, self.context_lines, self.context_lines) .read_span(context_span, self.context_lines, self.context_lines)
.map_err(|_| fmt::Error)?; .map_err(|_| fmt::Error)?;

View File

@ -165,7 +165,7 @@ impl NarratableReportHandler {
.map(|label| { .map(|label| {
source.read_span(label.inner(), self.context_lines, self.context_lines) source.read_span(label.inner(), self.context_lines, self.context_lines)
}) })
.collect::<Result<Vec<Box<dyn SpanContents<'_>>>, MietteError>>() .collect::<Result<Vec<Box<dyn SpanContents>>, MietteError>>()
.map_err(|_| fmt::Error)?; .map_err(|_| fmt::Error)?;
let mut contexts = Vec::new(); let mut contexts = Vec::new();
for (right, right_conts) in labels.iter().cloned().zip(contents.iter()) { for (right, right_conts) in labels.iter().cloned().zip(contents.iter()) {
@ -286,7 +286,7 @@ impl NarratableReportHandler {
&'a self, &'a self,
source: &'a dyn SourceCode, source: &'a dyn SourceCode,
context_span: &'a SourceSpan, context_span: &'a SourceSpan,
) -> Result<(Box<dyn SpanContents<'a> + 'a>, Vec<Line>), fmt::Error> { ) -> Result<(Box<dyn SpanContents + 'a>, Vec<Line>), fmt::Error> {
let context_data = source let context_data = source
.read_span(context_span, self.context_lines, self.context_lines) .read_span(context_span, self.context_lines, self.context_lines)
.map_err(|_| fmt::Error)?; .map_err(|_| fmt::Error)?;

View File

@ -12,7 +12,7 @@ pub struct BlankHighlighter;
impl Highlighter for BlankHighlighter { impl Highlighter for BlankHighlighter {
fn start_highlighter_state<'h>( fn start_highlighter_state<'h>(
&'h self, &'h self,
_source: &dyn SpanContents<'_>, _source: &(dyn SpanContents + 'h),
) -> Box<dyn super::HighlighterState + 'h> { ) -> Box<dyn super::HighlighterState + 'h> {
Box::new(BlankHighlighterState) Box::new(BlankHighlighterState)
} }

View File

@ -39,7 +39,7 @@ pub trait Highlighter {
/// responsible for the actual rendering. /// responsible for the actual rendering.
fn start_highlighter_state<'h>( fn start_highlighter_state<'h>(
&'h self, &'h self,
source: &dyn SpanContents<'_>, source: &(dyn SpanContents + 'h),
) -> Box<dyn HighlighterState + 'h>; ) -> Box<dyn HighlighterState + 'h>;
} }

View File

@ -42,7 +42,7 @@ impl Default for SyntectHighlighter {
impl Highlighter for SyntectHighlighter { impl Highlighter for SyntectHighlighter {
fn start_highlighter_state<'h>( fn start_highlighter_state<'h>(
&'h self, &'h self,
source: &dyn SpanContents<'_>, source: &(dyn SpanContents + 'h),
) -> Box<dyn HighlighterState + 'h> { ) -> Box<dyn HighlighterState + 'h> {
if let Some(syntax) = self.detect_syntax(source) { if let Some(syntax) = self.detect_syntax(source) {
let highlighter = syntect::Highlighter::new(&self.theme); let highlighter = syntect::Highlighter::new(&self.theme);
@ -82,7 +82,7 @@ impl SyntectHighlighter {
} }
/// Determine syntect [`SyntaxReference`] to use for given [`SpanContents`]. /// Determine syntect [`SyntaxReference`] to use for given [`SpanContents`].
fn detect_syntax(&self, contents: &dyn SpanContents<'_>) -> Option<&syntect::SyntaxReference> { fn detect_syntax(&self, contents: &dyn SpanContents) -> Option<&syntect::SyntaxReference> {
// use language if given // use language if given
if let Some(language) = contents.language() { if let Some(language) = contents.language() {
return self.syntax_set.find_syntax_by_name(language); return self.syntax_set.find_syntax_by_name(language);

View File

@ -1,4 +1,4 @@
use crate::{MietteError, MietteSpanContents, SourceCode, SpanContents}; use crate::{MietteError, SourceCode, SpanContents};
/// Utility struct for when you have a regular [`SourceCode`] type that doesn't /// Utility struct for when you have a regular [`SourceCode`] type that doesn't
/// implement `name`. For example [`String`]. Or if you want to override the /// implement `name`. For example [`String`]. Or if you want to override the
@ -51,6 +51,43 @@ impl<S: SourceCode + 'static> NamedSource<S> {
self self
} }
} }
/// Utility struct used by [`NamedSource`] to attach a file name to an inner [`SpanContents`] value
#[derive(Debug)]
pub struct NamedSpanContents<T: ?Sized> {
inner: Box<T>,
name: Box<str>,
language: Option<Box<str>>,
}
impl<T: SpanContents + ?Sized> SpanContents for NamedSpanContents<T> {
#[inline]
fn data(&self) -> &[u8] {
self.inner.data()
}
#[inline]
fn span(&self) -> &crate::SourceSpan {
self.inner.span()
}
#[inline]
fn line(&self) -> usize {
self.inner.line()
}
#[inline]
fn column(&self) -> usize {
self.inner.column()
}
#[inline]
fn line_count(&self) -> usize {
self.inner.line_count()
}
#[inline]
fn name(&self) -> Option<&str> {
Some(&self.name)
}
#[inline]
fn language(&self) -> Option<&str> {
self.language.as_deref()
}
}
impl<S: SourceCode + 'static> SourceCode for NamedSource<S> { impl<S: SourceCode + 'static> SourceCode for NamedSource<S> {
fn read_span<'a>( fn read_span<'a>(
@ -58,21 +95,14 @@ impl<S: SourceCode + 'static> SourceCode for NamedSource<S> {
span: &crate::SourceSpan, span: &crate::SourceSpan,
context_lines_before: usize, context_lines_before: usize,
context_lines_after: usize, context_lines_after: usize,
) -> Result<Box<dyn SpanContents<'a> + 'a>, MietteError> { ) -> Result<Box<dyn SpanContents + 'a>, MietteError> {
let inner_contents = let inner_contents =
self.inner() self.inner()
.read_span(span, context_lines_before, context_lines_after)?; .read_span(span, context_lines_before, context_lines_after)?;
let mut contents = MietteSpanContents::new_named( Ok(Box::new(NamedSpanContents {
self.name.clone(), inner: inner_contents,
inner_contents.data(), name: self.name.clone().into_boxed_str(),
*inner_contents.span(), language: self.language.as_ref().map(|v| v.clone().into_boxed_str()),
inner_contents.line(), }))
inner_contents.column(),
inner_contents.line_count(),
);
if let Some(language) = &self.language {
contents = contents.with_language(language);
}
Ok(Box::new(contents))
} }
} }

View File

@ -241,7 +241,7 @@ pub trait SourceCode: Send + Sync {
span: &SourceSpan, span: &SourceSpan,
context_lines_before: usize, context_lines_before: usize,
context_lines_after: usize, context_lines_after: usize,
) -> Result<Box<dyn SpanContents<'a> + 'a>, MietteError>; ) -> Result<Box<dyn SpanContents + 'a>, MietteError>;
} }
/// A labeled [`SourceSpan`]. /// A labeled [`SourceSpan`].
@ -423,9 +423,9 @@ Contents of a [`SourceCode`] covered by [`SourceSpan`].
Includes line and column information to optimize highlight calculations. Includes line and column information to optimize highlight calculations.
*/ */
pub trait SpanContents<'a> { pub trait SpanContents {
/// Reference to the data inside the associated span, in bytes. /// Reference to the data inside the associated span, in bytes.
fn data(&self) -> &'a [u8]; fn data(&self) -> &[u8];
/// [`SourceSpan`] representing the span covered by this `SpanContents`. /// [`SourceSpan`] representing the span covered by this `SpanContents`.
fn span(&self) -> &SourceSpan; fn span(&self) -> &SourceSpan;
/// An optional (file?) name for the container of this `SpanContents`. /// An optional (file?) name for the container of this `SpanContents`.
@ -519,8 +519,8 @@ impl<'a> MietteSpanContents<'a> {
} }
} }
impl<'a> SpanContents<'a> for MietteSpanContents<'a> { impl<'a> SpanContents for MietteSpanContents<'a> {
fn data(&self) -> &'a [u8] { fn data(&self) -> &[u8] {
self.data self.data
} }
fn span(&self) -> &SourceSpan { fn span(&self) -> &SourceSpan {

View File

@ -98,7 +98,7 @@ impl SourceCode for [u8] {
span: &SourceSpan, span: &SourceSpan,
context_lines_before: usize, context_lines_before: usize,
context_lines_after: usize, context_lines_after: usize,
) -> Result<Box<dyn SpanContents<'a> + 'a>, MietteError> { ) -> Result<Box<dyn SpanContents + 'a>, MietteError> {
let contents = context_info(self, span, context_lines_before, context_lines_after)?; let contents = context_info(self, span, context_lines_before, context_lines_after)?;
Ok(Box::new(contents)) Ok(Box::new(contents))
} }
@ -110,7 +110,7 @@ impl SourceCode for &[u8] {
span: &SourceSpan, span: &SourceSpan,
context_lines_before: usize, context_lines_before: usize,
context_lines_after: usize, context_lines_after: usize,
) -> Result<Box<dyn SpanContents<'a> + 'a>, MietteError> { ) -> Result<Box<dyn SpanContents + 'a>, MietteError> {
<[u8] as SourceCode>::read_span(self, span, context_lines_before, context_lines_after) <[u8] as SourceCode>::read_span(self, span, context_lines_before, context_lines_after)
} }
} }
@ -121,7 +121,7 @@ impl SourceCode for Vec<u8> {
span: &SourceSpan, span: &SourceSpan,
context_lines_before: usize, context_lines_before: usize,
context_lines_after: usize, context_lines_after: usize,
) -> Result<Box<dyn SpanContents<'a> + 'a>, MietteError> { ) -> Result<Box<dyn SpanContents + 'a>, MietteError> {
<[u8] as SourceCode>::read_span(self, span, context_lines_before, context_lines_after) <[u8] as SourceCode>::read_span(self, span, context_lines_before, context_lines_after)
} }
} }
@ -132,7 +132,7 @@ impl SourceCode for str {
span: &SourceSpan, span: &SourceSpan,
context_lines_before: usize, context_lines_before: usize,
context_lines_after: usize, context_lines_after: usize,
) -> Result<Box<dyn SpanContents<'a> + 'a>, MietteError> { ) -> Result<Box<dyn SpanContents + 'a>, MietteError> {
<[u8] as SourceCode>::read_span( <[u8] as SourceCode>::read_span(
self.as_bytes(), self.as_bytes(),
span, span,
@ -149,7 +149,7 @@ impl SourceCode for &str {
span: &SourceSpan, span: &SourceSpan,
context_lines_before: usize, context_lines_before: usize,
context_lines_after: usize, context_lines_after: usize,
) -> Result<Box<dyn SpanContents<'a> + 'a>, MietteError> { ) -> Result<Box<dyn SpanContents + 'a>, MietteError> {
<str as SourceCode>::read_span(self, span, context_lines_before, context_lines_after) <str as SourceCode>::read_span(self, span, context_lines_before, context_lines_after)
} }
} }
@ -160,7 +160,7 @@ impl SourceCode for String {
span: &SourceSpan, span: &SourceSpan,
context_lines_before: usize, context_lines_before: usize,
context_lines_after: usize, context_lines_after: usize,
) -> Result<Box<dyn SpanContents<'a> + 'a>, MietteError> { ) -> Result<Box<dyn SpanContents + 'a>, MietteError> {
<str as SourceCode>::read_span(self, span, context_lines_before, context_lines_after) <str as SourceCode>::read_span(self, span, context_lines_before, context_lines_after)
} }
} }
@ -171,7 +171,7 @@ impl<T: ?Sized + SourceCode> SourceCode for Arc<T> {
span: &SourceSpan, span: &SourceSpan,
context_lines_before: usize, context_lines_before: usize,
context_lines_after: usize, context_lines_after: usize,
) -> Result<Box<dyn SpanContents<'a> + 'a>, MietteError> { ) -> Result<Box<dyn SpanContents + 'a>, MietteError> {
self.as_ref() self.as_ref()
.read_span(span, context_lines_before, context_lines_after) .read_span(span, context_lines_before, context_lines_after)
} }
@ -191,7 +191,7 @@ where
span: &SourceSpan, span: &SourceSpan,
context_lines_before: usize, context_lines_before: usize,
context_lines_after: usize, context_lines_after: usize,
) -> Result<Box<dyn SpanContents<'a> + 'a>, MietteError> { ) -> Result<Box<dyn SpanContents + 'a>, MietteError> {
self.as_ref() self.as_ref()
.read_span(span, context_lines_before, context_lines_after) .read_span(span, context_lines_before, context_lines_after)
} }