Clean up render_snippets

This commit is contained in:
Lucas Holten 2023-12-13 12:31:57 +01:00
parent 7ff4f874d6
commit d4f30ec501
1 changed files with 55 additions and 58 deletions

View File

@ -6,7 +6,7 @@ use unicode_width::UnicodeWidthChar;
use crate::diagnostic_chain::{DiagnosticChain, ErrorKind}; use crate::diagnostic_chain::{DiagnosticChain, ErrorKind};
use crate::handlers::theme::*; use crate::handlers::theme::*;
use crate::protocol::{Diagnostic, Severity}; use crate::protocol::{Diagnostic, Severity};
use crate::{LabeledSpan, MietteError, ReportHandler, SourceCode, SourceSpan, SpanContents}; use crate::{LabeledSpan, ReportHandler, SourceCode, SourceSpan, SpanContents};
/** /**
A [`ReportHandler`] that displays a given [`Report`](crate::Report) in a A [`ReportHandler`] that displays a given [`Report`](crate::Report) in a
@ -377,66 +377,63 @@ impl GraphicalReportHandler {
diagnostic: &(dyn Diagnostic), diagnostic: &(dyn Diagnostic),
opt_source: Option<&dyn SourceCode>, opt_source: Option<&dyn SourceCode>,
) -> fmt::Result { ) -> fmt::Result {
if let Some(source) = opt_source { let Some(source) = opt_source else {
if let Some(labels) = diagnostic.labels() { return Ok(());
let mut labels = labels.collect::<Vec<_>>(); };
labels.sort_unstable_by_key(|l| l.inner().offset()); let Some(labels) = diagnostic.labels() else {
if !labels.is_empty() { return Ok(());
let contents = labels };
.iter()
.map(|label| { let mut labels = labels.collect::<Vec<_>>();
source.read_span(label.inner(), self.context_lines, self.context_lines) labels.sort_unstable_by_key(|l| l.inner().offset());
})
.collect::<Result<Vec<Box<dyn SpanContents<'_>>>, MietteError>>() let mut contexts = Vec::with_capacity(labels.len());
.map_err(|_| fmt::Error)?; for right in labels.iter().cloned() {
let mut contexts = Vec::with_capacity(contents.len()); let right_conts = source
for (right, right_conts) in labels.iter().cloned().zip(contents.iter()) { .read_span(right.inner(), self.context_lines, self.context_lines)
if contexts.is_empty() { .map_err(|_| fmt::Error)?;
contexts.push((right, right_conts));
} else { if contexts.is_empty() {
let (left, left_conts) = contexts.last().unwrap().clone(); contexts.push((right, (right_conts.line(), right_conts.line_count())));
let left_end = left.offset() + left.len(); continue;
let right_end = right.offset() + right.len(); }
if left_conts.line() + left_conts.line_count() >= right_conts.line() {
// The snippets will overlap, so we create one Big Chunky Boi let (left, (left_line, left_line_count)) = contexts.last().unwrap().clone();
let new_span = LabeledSpan::new( if left_line + left_line_count >= right_conts.line() {
left.label().map(String::from), // The snippets will overlap, so we create one Big Chunky Boi
left.offset(), let left_end = left.offset() + left.len();
if right_end >= left_end { let right_end = right.offset() + right.len();
// Right end goes past left end let new_span = LabeledSpan::new(
right_end - left.offset() left.label().map(String::from),
} else { left.offset(),
// right is contained inside left if right_end >= left_end {
left.len() // Right end goes past left end
}, right_end - left.offset()
); } else {
if source // right is contained inside left
.read_span( left.len()
new_span.inner(), },
self.context_lines, );
self.context_lines, // Check that the two contexts can be combined
) if let Ok(new_conts) =
.is_ok() source.read_span(new_span.inner(), self.context_lines, self.context_lines)
{ {
contexts.pop(); contexts.pop();
contexts.push(( contexts.push((
// We'll throw this away later // We'll throw this away later
new_span, left_conts, new_span,
)); (new_conts.line(), new_conts.line_count()),
} else { ));
contexts.push((right, right_conts)); continue;
}
} else {
contexts.push((right, right_conts));
}
}
}
for (ctx, _) in contexts {
self.render_context(f, source, &ctx, &labels[..])?;
}
} }
} }
contexts.push((right, (right_conts.line(), right_conts.line_count())));
} }
for (ctx, _) in contexts {
self.render_context(f, source, &ctx, &labels[..])?;
}
Ok(()) Ok(())
} }