mirror of
https://github.com/typst/typst
synced 2025-05-15 01:25:28 +08:00
initial attempt at a local sink on call
This commit is contained in:
parent
e196e45c31
commit
3823f560c5
@ -325,36 +325,48 @@ impl Display for Tracepoint {
|
||||
}
|
||||
}
|
||||
|
||||
/// Enrich a [`SourceResult`] with a tracepoint.
|
||||
pub trait Trace<T> {
|
||||
/// Add the tracepoint to all errors that lie outside the `span`.
|
||||
/// Enrich diagnostics with a tracepoint.
|
||||
pub trait Trace {
|
||||
/// Add the tracepoint to all diagnostics that lie outside the `span`.
|
||||
fn trace<F>(self, world: Tracked<dyn World + '_>, make_point: F, span: Span) -> Self
|
||||
where
|
||||
F: Fn() -> Tracepoint;
|
||||
}
|
||||
|
||||
impl<T> Trace<T> for SourceResult<T> {
|
||||
impl Trace for EcoVec<SourceDiagnostic> {
|
||||
fn trace<F>(
|
||||
mut self,
|
||||
world: Tracked<dyn World + '_>,
|
||||
make_point: F,
|
||||
span: Span,
|
||||
) -> Self
|
||||
where
|
||||
F: Fn() -> Tracepoint,
|
||||
{
|
||||
let Some(trace_range) = world.range(span) else { return self };
|
||||
for error in self.make_mut().iter_mut() {
|
||||
// Skip traces that surround the error.
|
||||
if let Some(error_range) = world.range(error.span) {
|
||||
if error.span.id() == span.id()
|
||||
&& trace_range.start <= error_range.start
|
||||
&& trace_range.end >= error_range.end
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
error.trace.push(Spanned::new(make_point(), span));
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Trace for SourceResult<T> {
|
||||
fn trace<F>(self, world: Tracked<dyn World + '_>, make_point: F, span: Span) -> Self
|
||||
where
|
||||
F: Fn() -> Tracepoint,
|
||||
{
|
||||
self.map_err(|mut errors| {
|
||||
let Some(trace_range) = world.range(span) else { return errors };
|
||||
for error in errors.make_mut().iter_mut() {
|
||||
// Skip traces that surround the error.
|
||||
if let Some(error_range) = world.range(error.span) {
|
||||
if error.span.id() == span.id()
|
||||
&& trace_range.start <= error_range.start
|
||||
&& trace_range.end >= error_range.end
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
error.trace.push(Spanned::new(make_point(), span));
|
||||
}
|
||||
errors
|
||||
})
|
||||
self.map_err(|errors| errors.trace(world, make_point, span))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@ use comemo::{Track, Tracked, TrackedMut, Validate};
|
||||
use ecow::EcoVec;
|
||||
use rayon::iter::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator};
|
||||
|
||||
use crate::diag::{self, Severity, SourceDiagnostic, SourceResult};
|
||||
use crate::diag::{self, Severity, SourceDiagnostic, SourceResult, Trace, Tracepoint};
|
||||
use crate::foundations::{Styles, Value};
|
||||
use crate::introspection::Introspector;
|
||||
use crate::syntax::{ast, FileId, Span};
|
||||
@ -161,6 +161,30 @@ impl Sink {
|
||||
self.values
|
||||
}
|
||||
|
||||
/// Takes and returns all fields from this sink:
|
||||
/// delayed errors, warnings and traced values.
|
||||
pub fn take(
|
||||
self,
|
||||
) -> (
|
||||
EcoVec<SourceDiagnostic>,
|
||||
EcoVec<SourceDiagnostic>,
|
||||
EcoVec<(Value, Option<Styles>)>,
|
||||
) {
|
||||
(self.delayed, self.warnings, self.values)
|
||||
}
|
||||
|
||||
/// Adds a tracepoint to all warnings outside the given span.
|
||||
pub fn trace_warnings<F>(
|
||||
&mut self,
|
||||
world: Tracked<dyn World + '_>,
|
||||
make_point: F,
|
||||
span: Span,
|
||||
) where
|
||||
F: Fn() -> Tracepoint,
|
||||
{
|
||||
self.warnings = std::mem::take(&mut self.warnings).trace(world, make_point, span);
|
||||
}
|
||||
|
||||
/// Apply warning suppression.
|
||||
pub fn suppress_warnings(&mut self, world: &dyn World) {
|
||||
self.warnings.retain(|diag| {
|
||||
@ -204,7 +228,7 @@ impl Sink {
|
||||
}
|
||||
|
||||
/// Extend from another sink.
|
||||
fn extend(
|
||||
pub fn extend(
|
||||
&mut self,
|
||||
delayed: EcoVec<SourceDiagnostic>,
|
||||
warnings: EcoVec<SourceDiagnostic>,
|
||||
|
@ -1,4 +1,4 @@
|
||||
use comemo::{Tracked, TrackedMut};
|
||||
use comemo::{Track, Tracked, TrackedMut};
|
||||
use ecow::{eco_format, EcoVec};
|
||||
|
||||
use crate::diag::{bail, error, At, HintedStrResult, SourceResult, Trace, Tracepoint};
|
||||
@ -165,8 +165,31 @@ impl Eval for ast::FuncCall<'_> {
|
||||
|
||||
let point = || Tracepoint::Call(func.name().map(Into::into));
|
||||
let f = || {
|
||||
func.call(&mut vm.engine, vm.context, args)
|
||||
.trace(vm.world(), point, span)
|
||||
// Create a temporary sink to accumulate all warnings produced by
|
||||
// this call (either directly or due to a nested call). Later, we
|
||||
// add a tracepoint to those warnings, indicating this call was
|
||||
// part of the call stack that led to the warning being raised,
|
||||
// thus allowing suppression of the warning through this call.
|
||||
let mut local_sink = Sink::new();
|
||||
let previous_sink =
|
||||
std::mem::replace(&mut vm.engine.sink, local_sink.track_mut());
|
||||
|
||||
let call_result = func.call(&mut vm.engine, vm.context, args).trace(
|
||||
vm.world(),
|
||||
point,
|
||||
span,
|
||||
);
|
||||
|
||||
std::mem::replace(&mut vm.engine.sink, previous_sink);
|
||||
local_sink.trace_warnings(vm.world(), point, span);
|
||||
|
||||
// Push the accumulated warnings and other fields back to the
|
||||
// original sink after we have modified them. This is needed so the
|
||||
// warnings are properly returned by compilation later.
|
||||
let (delayed, warnings, values) = local_sink.take();
|
||||
vm.engine.sink.extend(delayed, warnings, values);
|
||||
|
||||
call_result
|
||||
};
|
||||
|
||||
// Stacker is broken on WASM.
|
||||
|
Loading…
x
Reference in New Issue
Block a user