diff options
| author | Laurenz <laurmaedje@gmail.com> | 2023-06-12 15:40:43 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2023-06-12 15:42:01 +0200 |
| commit | 378ebe5f5601f11c3f428c17bed492012feb251e (patch) | |
| tree | 4530bf009844faca40ca4fd6d0b9251fd51ef587 /library/src | |
| parent | 19bf1f58944a42f17903869c162a33aba22b80b0 (diff) | |
Delayed errors
Fixes #785. Thanks to @Dherse for the idea!
Diffstat (limited to 'library/src')
| -rw-r--r-- | library/src/layout/mod.rs | 44 | ||||
| -rw-r--r-- | library/src/layout/par.rs | 19 | ||||
| -rw-r--r-- | library/src/meta/bibliography.rs | 88 | ||||
| -rw-r--r-- | library/src/meta/context.rs | 10 | ||||
| -rw-r--r-- | library/src/meta/counter.rs | 76 | ||||
| -rw-r--r-- | library/src/meta/link.rs | 23 | ||||
| -rw-r--r-- | library/src/meta/reference.rs | 92 | ||||
| -rw-r--r-- | library/src/meta/state.rs | 37 |
8 files changed, 212 insertions, 177 deletions
diff --git a/library/src/layout/mod.rs b/library/src/layout/mod.rs index d934c458..41490eb8 100644 --- a/library/src/layout/mod.rs +++ b/library/src/layout/mod.rs @@ -50,6 +50,7 @@ use std::mem; use typed_arena::Arena; use typst::diag::SourceResult; use typst::eval::Tracer; +use typst::model::DelayedErrors; use typst::model::{applicable, realize, StyleVecBuilder}; use crate::math::{EquationElem, LayoutMath}; @@ -116,13 +117,20 @@ impl LayoutRoot for Content { fn cached( content: &Content, world: Tracked<dyn World + '_>, - tracer: TrackedMut<Tracer>, - locator: Tracked<Locator>, introspector: Tracked<Introspector>, + locator: Tracked<Locator>, + delayed: TrackedMut<DelayedErrors>, + tracer: TrackedMut<Tracer>, styles: StyleChain, ) -> SourceResult<Document> { let mut locator = Locator::chained(locator); - let mut vt = Vt { world, tracer, locator: &mut locator, introspector }; + let mut vt = Vt { + world, + introspector, + locator: &mut locator, + delayed, + tracer, + }; let scratch = Scratch::default(); let (realized, styles) = realize_root(&mut vt, &scratch, content, styles)?; realized @@ -132,13 +140,13 @@ impl LayoutRoot for Content { } tracing::info!("Starting layout"); - cached( self, vt.world, - TrackedMut::reborrow_mut(&mut vt.tracer), - vt.locator.track(), vt.introspector, + vt.locator.track(), + TrackedMut::reborrow_mut(&mut vt.delayed), + TrackedMut::reborrow_mut(&mut vt.tracer), styles, ) } @@ -168,9 +176,10 @@ pub trait Layout { let mut locator = Locator::chained(vt.locator.track()); let mut vt = Vt { world: vt.world, - tracer: TrackedMut::reborrow_mut(&mut vt.tracer), - locator: &mut locator, introspector: vt.introspector, + locator: &mut locator, + tracer: TrackedMut::reborrow_mut(&mut vt.tracer), + delayed: TrackedMut::reborrow_mut(&mut vt.delayed), }; self.layout(&mut vt, styles, regions) } @@ -184,18 +193,26 @@ impl Layout for Content { styles: StyleChain, regions: Regions, ) -> SourceResult<Fragment> { + #[allow(clippy::too_many_arguments)] #[comemo::memoize] fn cached( content: &Content, world: Tracked<dyn World + '_>, - tracer: TrackedMut<Tracer>, - locator: Tracked<Locator>, introspector: Tracked<Introspector>, + locator: Tracked<Locator>, + delayed: TrackedMut<DelayedErrors>, + tracer: TrackedMut<Tracer>, styles: StyleChain, regions: Regions, ) -> SourceResult<Fragment> { let mut locator = Locator::chained(locator); - let mut vt = Vt { world, tracer, locator: &mut locator, introspector }; + let mut vt = Vt { + world, + introspector, + locator: &mut locator, + delayed, + tracer, + }; let scratch = Scratch::default(); let (realized, styles) = realize_block(&mut vt, &scratch, content, styles)?; realized @@ -209,9 +226,10 @@ impl Layout for Content { let fragment = cached( self, vt.world, - TrackedMut::reborrow_mut(&mut vt.tracer), - vt.locator.track(), vt.introspector, + vt.locator.track(), + TrackedMut::reborrow_mut(&mut vt.delayed), + TrackedMut::reborrow_mut(&mut vt.tracer), styles, regions, )?; diff --git a/library/src/layout/par.rs b/library/src/layout/par.rs index fa53f031..2d0944ce 100644 --- a/library/src/layout/par.rs +++ b/library/src/layout/par.rs @@ -5,6 +5,7 @@ use icu_provider_blob::BlobDataProvider; use icu_segmenter::{LineBreakIteratorUtf8, LineSegmenter}; use once_cell::sync::Lazy; use typst::eval::Tracer; +use typst::model::DelayedErrors; use unicode_bidi::{BidiInfo, Level as BidiLevel}; use unicode_script::{Script, UnicodeScript}; @@ -148,16 +149,23 @@ impl ParElem { fn cached( par: &ParElem, world: Tracked<dyn World + '_>, - tracer: TrackedMut<Tracer>, - locator: Tracked<Locator>, introspector: Tracked<Introspector>, + locator: Tracked<Locator>, + delayed: TrackedMut<DelayedErrors>, + tracer: TrackedMut<Tracer>, styles: StyleChain, consecutive: bool, region: Size, expand: bool, ) -> SourceResult<Fragment> { let mut locator = Locator::chained(locator); - let mut vt = Vt { world, tracer, locator: &mut locator, introspector }; + let mut vt = Vt { + world, + introspector, + locator: &mut locator, + delayed, + tracer, + }; let children = par.children(); // Collect all text into one string for BiDi analysis. @@ -178,9 +186,10 @@ impl ParElem { let fragment = cached( self, vt.world, - TrackedMut::reborrow_mut(&mut vt.tracer), - vt.locator.track(), vt.introspector, + vt.locator.track(), + TrackedMut::reborrow_mut(&mut vt.delayed), + TrackedMut::reborrow_mut(&mut vt.tracer), styles, consecutive, region, diff --git a/library/src/meta/bibliography.rs b/library/src/meta/bibliography.rs index 737530b8..f020f730 100644 --- a/library/src/meta/bibliography.rs +++ b/library/src/meta/bibliography.rs @@ -96,11 +96,11 @@ impl BibliographyElem { pub fn find(introspector: Tracked<Introspector>) -> StrResult<Self> { let mut iter = introspector.query(&Self::func().select()).into_iter(); let Some(elem) = iter.next() else { - return Err("the document does not contain a bibliography".into()); + bail!("the document does not contain a bibliography"); }; if iter.next().is_some() { - Err("multiple bibliographies are not supported")?; + bail!("multiple bibliographies are not supported"); } Ok(elem.to::<Self>().unwrap().clone()) @@ -162,42 +162,40 @@ impl Show for BibliographyElem { seq.push(HeadingElem::new(title).with_level(NonZeroUsize::ONE).pack()); } - if !vt.introspector.init() { - return Ok(Content::sequence(seq)); - } + Ok(vt.delayed(|vt| { + let works = Works::new(vt).at(self.span())?; - let works = Works::new(vt).at(self.span())?; + let row_gutter = BlockElem::below_in(styles).amount(); + if works.references.iter().any(|(prefix, _)| prefix.is_some()) { + let mut cells = vec![]; + for (prefix, reference) in &works.references { + cells.push(prefix.clone().unwrap_or_default()); + cells.push(reference.clone()); + } - let row_gutter = BlockElem::below_in(styles).amount(); - if works.references.iter().any(|(prefix, _)| prefix.is_some()) { - let mut cells = vec![]; - for (prefix, reference) in &works.references { - cells.push(prefix.clone().unwrap_or_default()); - cells.push(reference.clone()); - } + seq.push(VElem::new(row_gutter).with_weakness(3).pack()); + seq.push( + GridElem::new(cells) + .with_columns(TrackSizings(vec![Sizing::Auto; 2])) + .with_column_gutter(TrackSizings(vec![COLUMN_GUTTER.into()])) + .with_row_gutter(TrackSizings(vec![row_gutter.into()])) + .pack(), + ); + } else { + let mut entries = vec![]; + for (_, reference) in &works.references { + entries.push(VElem::new(row_gutter).with_weakness(3).pack()); + entries.push(reference.clone()); + } - seq.push(VElem::new(row_gutter).with_weakness(3).pack()); - seq.push( - GridElem::new(cells) - .with_columns(TrackSizings(vec![Sizing::Auto; 2])) - .with_column_gutter(TrackSizings(vec![COLUMN_GUTTER.into()])) - .with_row_gutter(TrackSizings(vec![row_gutter.into()])) - .pack(), - ); - } else { - let mut entries = vec![]; - for (_, reference) in &works.references { - entries.push(VElem::new(row_gutter).with_weakness(3).pack()); - entries.push(reference.clone()); + seq.push( + Content::sequence(entries) + .styled(ParElem::set_hanging_indent(INDENT.into())), + ); } - seq.push( - Content::sequence(entries) - .styled(ParElem::set_hanging_indent(INDENT.into())), - ); - } - - Ok(Content::sequence(seq)) + Ok(Content::sequence(seq)) + })) } } @@ -357,19 +355,17 @@ impl Synthesize for CiteElem { impl Show for CiteElem { #[tracing::instrument(name = "CiteElem::show", skip(self, vt))] fn show(&self, vt: &mut Vt, _: StyleChain) -> SourceResult<Content> { - if !vt.introspector.init() { - return Ok(Content::empty()); - } - - let works = Works::new(vt).at(self.span())?; - let location = self.0.location().unwrap(); - works - .citations - .get(&location) - .cloned() - .flatten() - .ok_or("bibliography does not contain this key") - .at(self.span()) + Ok(vt.delayed(|vt| { + let works = Works::new(vt).at(self.span())?; + let location = self.0.location().unwrap(); + works + .citations + .get(&location) + .cloned() + .flatten() + .ok_or("bibliography does not contain this key") + .at(self.span()) + })) } } diff --git a/library/src/meta/context.rs b/library/src/meta/context.rs index d599c63e..2ed359ee 100644 --- a/library/src/meta/context.rs +++ b/library/src/meta/context.rs @@ -73,12 +73,10 @@ struct LocateElem { impl Show for LocateElem { #[tracing::instrument(name = "LocateElem::show", skip(self, vt))] fn show(&self, vt: &mut Vt, _: StyleChain) -> SourceResult<Content> { - if !vt.introspector.init() { - return Ok(Content::empty()); - } - - let location = self.0.location().unwrap(); - Ok(self.func().call_vt(vt, [location])?.display()) + Ok(vt.delayed(|vt| { + let location = self.0.location().unwrap(); + Ok(self.func().call_vt(vt, [location])?.display()) + })) } } diff --git a/library/src/meta/counter.rs b/library/src/meta/counter.rs index ef4646ab..65522c40 100644 --- a/library/src/meta/counter.rs +++ b/library/src/meta/counter.rs @@ -4,6 +4,7 @@ use std::str::FromStr; use ecow::{eco_vec, EcoVec}; use smallvec::{smallvec, SmallVec}; use typst::eval::Tracer; +use typst::model::DelayedErrors; use super::{FigureElem, HeadingElem, Numbering, NumberingPattern}; use crate::layout::PageElem; @@ -397,9 +398,10 @@ impl Counter { ) -> SourceResult<EcoVec<(CounterState, NonZeroUsize)>> { self.sequence_impl( vt.world, - TrackedMut::reborrow_mut(&mut vt.tracer), - vt.locator.track(), vt.introspector, + vt.locator.track(), + TrackedMut::reborrow_mut(&mut vt.delayed), + TrackedMut::reborrow_mut(&mut vt.tracer), ) } @@ -408,12 +410,19 @@ impl Counter { fn sequence_impl( &self, world: Tracked<dyn World + '_>, - tracer: TrackedMut<Tracer>, - locator: Tracked<Locator>, introspector: Tracked<Introspector>, + locator: Tracked<Locator>, + delayed: TrackedMut<DelayedErrors>, + tracer: TrackedMut<Tracer>, ) -> SourceResult<EcoVec<(CounterState, NonZeroUsize)>> { let mut locator = Locator::chained(locator); - let mut vt = Vt { world, tracer, locator: &mut locator, introspector }; + let mut vt = Vt { + world, + introspector, + locator: &mut locator, + delayed, + tracer, + }; let mut state = CounterState(match &self.0 { // special case, because pages always start at one. CounterKey::Page => smallvec![1], @@ -618,37 +627,36 @@ struct DisplayElem { impl Show for DisplayElem { #[tracing::instrument(name = "DisplayElem::show", skip_all)] fn show(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Content> { - if !vt.introspector.init() { - return Ok(Content::empty()); - } - - let location = self.0.location().unwrap(); - let counter = self.counter(); - let numbering = self - .numbering() - .or_else(|| { - let CounterKey::Selector(Selector::Elem(func, _)) = counter.0 else { - return None; + Ok(vt.delayed(|vt| { + let location = self.0.location().unwrap(); + let counter = self.counter(); + let numbering = self + .numbering() + .or_else(|| { + let CounterKey::Selector(Selector::Elem(func, _)) = counter.0 else { + return None; + }; + + if func == HeadingElem::func() { + HeadingElem::numbering_in(styles) + } else if func == FigureElem::func() { + FigureElem::numbering_in(styles) + } else if func == EquationElem::func() { + EquationElem::numbering_in(styles) + } else { + None + } + }) + .unwrap_or_else(|| NumberingPattern::from_str("1.1").unwrap().into()); + + let state = if self.both() { + counter.both(vt, location)? + } else { + counter.at(vt, location)? }; - if func == HeadingElem::func() { - HeadingElem::numbering_in(styles) - } else if func == FigureElem::func() { - FigureElem::numbering_in(styles) - } else if func == EquationElem::func() { - EquationElem::numbering_in(styles) - } else { - None - } - }) - .unwrap_or_else(|| NumberingPattern::from_str("1.1").unwrap().into()); - - let state = if self.both() { - counter.both(vt, location)? - } else { - counter.at(vt, location)? - }; - state.display(vt, &numbering) + state.display(vt, &numbering) + })) } } diff --git a/library/src/meta/link.rs b/library/src/meta/link.rs index 43f6a34d..c3d8718c 100644 --- a/library/src/meta/link.rs +++ b/library/src/meta/link.rs @@ -91,21 +91,18 @@ impl Show for LinkElem { #[tracing::instrument(name = "LinkElem::show", skip(self, vt))] fn show(&self, vt: &mut Vt, _: StyleChain) -> SourceResult<Content> { let body = self.body(); - let dest = match self.dest() { - LinkTarget::Dest(dest) => dest, - LinkTarget::Label(label) => { - if !vt.introspector.init() { - return Ok(body); - } - - let elem = vt.introspector.query_label(&label).at(self.span())?; - Destination::Location(elem.location().unwrap()) - } + let linked = match self.dest() { + LinkTarget::Dest(dest) => body.linked(dest), + LinkTarget::Label(label) => vt + .delayed(|vt| { + let elem = vt.introspector.query_label(&label).at(self.span())?; + let dest = Destination::Location(elem.location().unwrap()); + Ok(Some(body.clone().linked(dest))) + }) + .unwrap_or(body), }; - Ok(body - .linked(dest) - .styled(TextElem::set_hyphenate(Hyphenate(Smart::Custom(false))))) + Ok(linked.styled(TextElem::set_hyphenate(Hyphenate(Smart::Custom(false))))) } } diff --git a/library/src/meta/reference.rs b/library/src/meta/reference.rs index 5a295e33..96358ffa 100644 --- a/library/src/meta/reference.rs +++ b/library/src/meta/reference.rs @@ -132,7 +132,7 @@ impl Synthesize for RefElem { self.push_element(None); let target = self.target(); - if vt.introspector.init() && !BibliographyElem::has(vt, &target.0) { + if !BibliographyElem::has(vt, &target.0) { if let Ok(elem) = vt.introspector.query_label(&target) { self.push_element(Some(elem.into_inner())); return Ok(()); @@ -146,63 +146,65 @@ impl Synthesize for RefElem { impl Show for RefElem { #[tracing::instrument(name = "RefElem::show", skip_all)] fn show(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Content> { - if !vt.introspector.init() { - return Ok(Content::empty()); - } + Ok(vt.delayed(|vt| { + let target = self.target(); + let elem = vt.introspector.query_label(&self.target()); + let span = self.span(); - let target = self.target(); - let elem = vt.introspector.query_label(&self.target()); - let span = self.span(); + if BibliographyElem::has(vt, &target.0) { + if elem.is_ok() { + bail!(span, "label occurs in the document and its bibliography"); + } - if BibliographyElem::has(vt, &target.0) { - if elem.is_ok() { - bail!(span, "label occurs in the document and its bibliography"); + return Ok(self.to_citation(vt, styles)?.pack().spanned(span)); } - return Ok(self.to_citation(vt, styles)?.pack().spanned(span)); - } + let elem = elem.at(span)?; + let refable = elem + .with::<dyn Refable>() + .ok_or_else(|| { + if elem.can::<dyn Figurable>() { + eco_format!( + "cannot reference {} directly, try putting it into a figure", + elem.func().name() + ) + } else { + eco_format!("cannot reference {}", elem.func().name()) + } + }) + .at(span)?; - let elem = elem.at(span)?; - let refable = elem - .with::<dyn Refable>() - .ok_or_else(|| { - if elem.can::<dyn Figurable>() { + let numbering = refable + .numbering() + .ok_or_else(|| { eco_format!( - "cannot reference {} directly, try putting it into a figure", + "cannot reference {0} without numbering \ + - did you mean to use `#set {0}(numbering: \"1.\")`?", elem.func().name() ) - } else { - eco_format!("cannot reference {}", elem.func().name()) - } - }) - .at(span)?; + }) + .at(span)?; - let numbering = refable - .numbering() - .ok_or_else(|| { - eco_format!("cannot reference {0} without numbering - did you mean to use `#set {0}(numbering: \"1.\")`?", elem.func().name()) - }) - .at(span)?; + let numbers = refable + .counter() + .at(vt, elem.location().unwrap())? + .display(vt, &numbering.trimmed())?; - let numbers = refable - .counter() - .at(vt, elem.location().unwrap())? - .display(vt, &numbering.trimmed())?; + let supplement = match self.supplement(styles) { + Smart::Auto => refable.supplement(), + Smart::Custom(None) => Content::empty(), + Smart::Custom(Some(supplement)) => { + supplement.resolve(vt, [(*elem).clone()])? + } + }; - let supplement = match self.supplement(styles) { - Smart::Auto => refable.supplement(), - Smart::Custom(None) => Content::empty(), - Smart::Custom(Some(supplement)) => { - supplement.resolve(vt, [(*elem).clone()])? + let mut content = numbers; + if !supplement.is_empty() { + content = supplement + TextElem::packed("\u{a0}") + content; } - }; - - let mut content = numbers; - if !supplement.is_empty() { - content = supplement + TextElem::packed("\u{a0}") + content; - } - Ok(content.linked(Destination::Location(elem.location().unwrap()))) + Ok(content.linked(Destination::Location(elem.location().unwrap()))) + })) } } diff --git a/library/src/meta/state.rs b/library/src/meta/state.rs index 231852e3..a8e37901 100644 --- a/library/src/meta/state.rs +++ b/library/src/meta/state.rs @@ -2,6 +2,7 @@ use std::fmt::{self, Debug, Formatter, Write}; use ecow::{eco_vec, EcoVec}; use typst::eval::Tracer; +use typst::model::DelayedErrors; use crate::prelude::*; @@ -306,9 +307,10 @@ impl State { fn sequence(&self, vt: &mut Vt) -> SourceResult<EcoVec<Value>> { self.sequence_impl( vt.world, - TrackedMut::reborrow_mut(&mut vt.tracer), - vt.locator.track(), vt.introspector, + vt.locator.track(), + TrackedMut::reborrow_mut(&mut vt.delayed), + TrackedMut::reborrow_mut(&mut vt.tracer), ) } @@ -317,12 +319,19 @@ impl State { fn sequence_impl( &self, world: Tracked<dyn World + '_>, - tracer: TrackedMut<Tracer>, - locator: Tracked<Locator>, introspector: Tracked<Introspector>, + locator: Tracked<Locator>, + delayed: TrackedMut<DelayedErrors>, + tracer: TrackedMut<Tracer>, ) -> SourceResult<EcoVec<Value>> { let mut locator = Locator::chained(locator); - let mut vt = Vt { world, tracer, locator: &mut locator, introspector }; + let mut vt = Vt { + world, + introspector, + locator: &mut locator, + delayed, + tracer, + }; let mut state = self.init.clone(); let mut stops = eco_vec![state.clone()]; @@ -397,16 +406,14 @@ struct DisplayElem { impl Show for DisplayElem { #[tracing::instrument(name = "DisplayElem::show", skip(self, vt))] fn show(&self, vt: &mut Vt, _: StyleChain) -> SourceResult<Content> { - if !vt.introspector.init() { - return Ok(Content::empty()); - } - - let location = self.0.location().unwrap(); - let value = self.state().at(vt, location)?; - Ok(match self.func() { - Some(func) => func.call_vt(vt, [value])?.display(), - None => value.display(), - }) + Ok(vt.delayed(|vt| { + let location = self.0.location().unwrap(); + let value = self.state().at(vt, location)?; + Ok(match self.func() { + Some(func) => func.call_vt(vt, [value])?.display(), + None => value.display(), + }) + })) } } |
