summaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorSébastien d'Herbais de Thun <sebastien.d.herbais@gmail.com>2023-11-27 11:17:47 +0100
committerGitHub <noreply@github.com>2023-11-27 11:17:47 +0100
commit2c85161a277a8b754eea529bd71fb0e67f39ac33 (patch)
treeb20fa60eea042242bfecc2415cea4bcd564f0e0d /crates
parent219c1c9ed0f4d5755becd9f679b4cf7cfa670b5a (diff)
Added `hint` to `bail!`, `warning!`, and `error!` (#2756)
Diffstat (limited to 'crates')
-rw-r--r--crates/typst/src/diag.rs80
-rw-r--r--crates/typst/src/eval/markup.rs18
-rw-r--r--crates/typst/src/foundations/version.rs4
-rw-r--r--crates/typst/src/layout/mod.rs8
-rw-r--r--crates/typst/src/lib.rs8
-rw-r--r--crates/typst/src/model/footnote.rs9
-rw-r--r--crates/typst/src/model/outline.rs10
-rw-r--r--crates/typst/src/realize/mod.rs12
-rw-r--r--crates/typst/src/text/mod.rs10
-rw-r--r--crates/typst/src/visualize/color.rs14
-rw-r--r--crates/typst/src/visualize/gradient.rs58
-rw-r--r--crates/typst/src/visualize/pattern.rs8
12 files changed, 149 insertions, 90 deletions
diff --git a/crates/typst/src/diag.rs b/crates/typst/src/diag.rs
index 4634f41e..41339dff 100644
--- a/crates/typst/src/diag.rs
+++ b/crates/typst/src/diag.rs
@@ -18,69 +18,105 @@ use crate::{World, WorldExt};
/// `StrResult`. If called with a span, a string and format args, returns
/// a `SourceResult`.
///
+/// You can also emit hints with the `; hint: "..."` syntax.
+///
/// ```
/// bail!("bailing with a {}", "string result");
/// bail!(span, "bailing with a {}", "source result");
+/// bail!(
+/// span, "bailing with a {}", "source result";
+/// hint: "hint 1"
+/// );
+/// bail!(
+/// span, "bailing with a {}", "source result";
+/// hint: "hint 1";
+/// hint: "hint 2";
+/// );
/// ```
#[macro_export]
#[doc(hidden)]
macro_rules! __bail {
+ // For bail!("just a {}", "string")
($fmt:literal $(, $arg:expr)* $(,)?) => {
- return Err($crate::diag::eco_format!($fmt, $($arg),*))
+ return Err($crate::diag::error!(
+ $fmt, $($arg),*
+ ))
};
+ // For bail!(error!(..))
($error:expr) => {
return Err(::ecow::eco_vec![$error])
};
- ($span:expr, $fmt:literal $(, $arg:expr)* $(,)?) => {
- return Err(::ecow::eco_vec![$crate::diag::SourceDiagnostic::error(
- $span,
- $crate::diag::eco_format!($fmt, $($arg),*),
- )])
+ // For bail(span, ...)
+ ($($tts:tt)*) => {
+ return Err(::ecow::eco_vec![$crate::diag::error!($($tts)*)])
};
}
-#[doc(inline)]
-pub use crate::__bail as bail;
-#[doc(inline)]
-pub use crate::__error as error;
-#[doc(inline)]
-pub use crate::__warning as warning;
-
-#[doc(hidden)]
-pub use ecow::eco_format;
-#[doc(hidden)]
-pub use ecow::EcoString;
-
/// Construct an [`EcoString`] or [`SourceDiagnostic`] with severity `Error`.
#[macro_export]
#[doc(hidden)]
macro_rules! __error {
+ // For bail!("just a {}", "string").
($fmt:literal $(, $arg:expr)* $(,)?) => {
$crate::diag::eco_format!($fmt, $($arg),*)
};
- ($span:expr, $fmt:literal $(, $arg:expr)* $(,)?) => {
+ // For bail!(span, ...)
+ (
+ $span:expr, $fmt:literal $(, $arg:expr)*
+ $(; hint: $hint:literal $(, $hint_arg:expr)*)*
+ $(,)?
+ ) => {
$crate::diag::SourceDiagnostic::error(
$span,
$crate::diag::eco_format!($fmt, $($arg),*),
- )
+ ) $(.with_hint($crate::diag::eco_format!($hint, $($hint_arg),*)))*
};
}
/// Construct a [`SourceDiagnostic`] with severity `Warning`.
+///
+/// You can also emit hints with the `; hint: "..."` syntax.
+///
+/// ```
+/// warning!(span, "warning with a {}", "source result");
+/// warning!(
+/// span, "warning with a {}", "source result";
+/// hint: "hint 1"
+/// );
+/// warning!(
+/// span, "warning with a {}", "source result";
+/// hint: "hint 1";
+/// hint: "hint 2";
+/// );
+/// ```
#[macro_export]
#[doc(hidden)]
macro_rules! __warning {
- ($span:expr, $fmt:literal $(, $arg:expr)* $(,)?) => {
+ (
+ $span:expr,
+ $fmt:literal $(, $arg:expr)*
+ $(; hint: $hint:literal $(, $hint_arg:expr)*)*
+ $(,)?
+ ) => {
$crate::diag::SourceDiagnostic::warning(
$span,
$crate::diag::eco_format!($fmt, $($arg),*),
- )
+ ) $(.with_hint($crate::diag::eco_format!($hint, $($hint_arg),*)))*
};
}
+#[rustfmt::skip]
+#[doc(inline)]
+pub use {
+ crate::__bail as bail,
+ crate::__error as error,
+ crate::__warning as warning,
+ ecow::{eco_format, EcoString},
+};
+
/// A result that can carry multiple source errors.
pub type SourceResult<T> = Result<T, EcoVec<SourceDiagnostic>>;
diff --git a/crates/typst/src/eval/markup.rs b/crates/typst/src/eval/markup.rs
index a40b978e..ad9cd9c1 100644
--- a/crates/typst/src/eval/markup.rs
+++ b/crates/typst/src/eval/markup.rs
@@ -139,11 +139,12 @@ impl Eval for ast::Strong<'_> {
fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let body = self.body();
if body.exprs().next().is_none() {
- vm.engine.tracer.warn(
- warning!(self.span(), "no text within stars").with_hint(
- "using multiple consecutive stars (e.g. **) has no additional effect",
- ),
- );
+ vm.engine
+ .tracer
+ .warn(warning!(
+ self.span(), "no text within stars";
+ hint: "using multiple consecutive stars (e.g. **) has no additional effect",
+ ));
}
Ok(StrongElem::new(body.eval(vm)?).pack())
@@ -159,9 +160,10 @@ impl Eval for ast::Emph<'_> {
if body.exprs().next().is_none() {
vm.engine
.tracer
- .warn(warning!(self.span(), "no text within underscores").with_hint(
- "using multiple consecutive underscores (e.g. __) has no additional effect"
- ));
+ .warn(warning!(
+ self.span(), "no text within underscores";
+ hint: "using multiple consecutive underscores (e.g. __) has no additional effect"
+ ));
}
Ok(EmphElem::new(body.eval(vm)?).pack())
diff --git a/crates/typst/src/foundations/version.rs b/crates/typst/src/foundations/version.rs
index 80a39fe4..98ad598b 100644
--- a/crates/typst/src/foundations/version.rs
+++ b/crates/typst/src/foundations/version.rs
@@ -5,7 +5,7 @@ use std::iter::repeat;
use ecow::{eco_format, EcoString, EcoVec};
-use crate::diag::{bail, error, StrResult};
+use crate::diag::{bail, StrResult};
use crate::foundations::{cast, func, repr, scope, ty, Repr};
/// A version with an arbitrary number of components.
@@ -43,7 +43,7 @@ impl Version {
.iter()
.zip(Self::COMPONENTS)
.find_map(|(&i, s)| (s == name).then_some(i as i64))
- .ok_or_else(|| error!("unknown version component"))
+ .ok_or_else(|| "unknown version component".into())
}
/// Push a component to the end of this version.
diff --git a/crates/typst/src/layout/mod.rs b/crates/typst/src/layout/mod.rs
index 1e1bcf9b..dbdadbde 100644
--- a/crates/typst/src/layout/mod.rs
+++ b/crates/typst/src/layout/mod.rs
@@ -71,7 +71,7 @@ pub(crate) use self::inline::*;
use comemo::{Tracked, TrackedMut};
-use crate::diag::{bail, error, SourceResult};
+use crate::diag::{bail, SourceResult};
use crate::engine::{Engine, Route};
use crate::eval::Tracer;
use crate::foundations::{category, Category, Content, Scope, StyleChain};
@@ -238,8 +238,10 @@ impl Layout for Content {
};
if engine.route.exceeding() {
- bail!(error!(content.span(), "maximum layout depth exceeded")
- .with_hint("try to reduce the amount of nesting in your layout"));
+ bail!(
+ content.span(), "maximum layout depth exceeded";
+ hint: "try to reduce the amount of nesting in your layout",
+ );
}
let scratch = Scratch::default();
diff --git a/crates/typst/src/lib.rs b/crates/typst/src/lib.rs
index 52634d45..1109b906 100644
--- a/crates/typst/src/lib.rs
+++ b/crates/typst/src/lib.rs
@@ -143,10 +143,10 @@ fn typeset(
}
if iter >= 5 {
- tracer.warn(
- warning!(Span::detached(), "layout did not converge within 5 attempts",)
- .with_hint("check if any states or queries are updating themselves"),
- );
+ tracer.warn(warning!(
+ Span::detached(), "layout did not converge within 5 attempts";
+ hint: "check if any states or queries are updating themselves"
+ ));
break;
}
}
diff --git a/crates/typst/src/model/footnote.rs b/crates/typst/src/model/footnote.rs
index df88b58c..a6e1e2de 100644
--- a/crates/typst/src/model/footnote.rs
+++ b/crates/typst/src/model/footnote.rs
@@ -3,7 +3,7 @@ use std::str::FromStr;
use comemo::Prehashed;
-use crate::diag::{bail, error, At, SourceResult, StrResult};
+use crate::diag::{bail, At, SourceResult, StrResult};
use crate::engine::Engine;
use crate::foundations::{
cast, elem, scope, Content, Finalize, Label, NativeElement, Show, Smart, StyleChain,
@@ -280,9 +280,10 @@ impl Show for FootnoteEntry {
let numbering = note.numbering(default);
let counter = Counter::of(FootnoteElem::elem());
let Some(loc) = note.location() else {
- bail!(error!(self.span(), "footnote entry must have a location").with_hint(
- "try using a query or a show rule to customize the footnote instead"
- ))
+ bail!(
+ self.span(), "footnote entry must have a location";
+ hint: "try using a query or a show rule to customize the footnote instead"
+ );
};
let num = counter.at(engine, loc)?.display(engine, numbering)?;
diff --git a/crates/typst/src/model/outline.rs b/crates/typst/src/model/outline.rs
index 91526a9c..06b032fa 100644
--- a/crates/typst/src/model/outline.rs
+++ b/crates/typst/src/model/outline.rs
@@ -1,7 +1,7 @@
use std::num::NonZeroUsize;
use std::str::FromStr;
-use crate::diag::{bail, error, At, SourceResult};
+use crate::diag::{bail, At, SourceResult};
use crate::engine::Engine;
use crate::foundations::{
cast, elem, scope, select_where, Content, Finalize, Func, LocatableSelector,
@@ -492,10 +492,10 @@ impl Show for OutlineEntry {
// In case a user constructs an outline entry with an arbitrary element.
let Some(location) = elem.location() else {
if elem.can::<dyn Locatable>() && elem.can::<dyn Outlinable>() {
- bail!(error!(self.span(), "{} must have a location", elem.func().name())
- .with_hint(
- "try using a query or a show rule to customize the outline.entry instead",
- ))
+ bail!(
+ self.span(), "{} must have a location", elem.func().name();
+ hint: "try using a query or a show rule to customize the outline.entry instead",
+ )
} else {
bail!(self.span(), "cannot outline {}", elem.func().name())
}
diff --git a/crates/typst/src/realize/mod.rs b/crates/typst/src/realize/mod.rs
index c2f19303..81dbdb66 100644
--- a/crates/typst/src/realize/mod.rs
+++ b/crates/typst/src/realize/mod.rs
@@ -10,7 +10,7 @@ use std::mem;
use smallvec::smallvec;
use typed_arena::Arena;
-use crate::diag::{bail, error, SourceResult};
+use crate::diag::{bail, SourceResult};
use crate::engine::Engine;
use crate::foundations::{
Content, Finalize, Guard, NativeElement, Recipe, Selector, Show, StyleChain,
@@ -308,11 +308,11 @@ impl<'a, 'v, 't> Builder<'a, 'v, 't> {
if let Some(realized) = realize(self.engine, content, styles)? {
self.engine.route.increase();
if self.engine.route.exceeding() {
- bail!(error!(content.span(), "maximum show rule depth exceeded")
- .with_hint("check whether the show rule matches its own output")
- .with_hint(
- "this is a current compiler limitation that will be resolved in the future"
- ));
+ bail!(
+ content.span(), "maximum show rule depth exceeded";
+ hint: "check whether the show rule matches its own output";
+ hint: "this is a current compiler limitation that will be resolved in the future",
+ );
}
let stored = self.scratch.content.alloc(realized);
let v = self.accept(stored, styles);
diff --git a/crates/typst/src/text/mod.rs b/crates/typst/src/text/mod.rs
index da3580a5..dfbf328f 100644
--- a/crates/typst/src/text/mod.rs
+++ b/crates/typst/src/text/mod.rs
@@ -34,7 +34,7 @@ use ecow::{eco_format, EcoString};
use rustybuzz::{Feature, Tag};
use ttf_parser::Rect;
-use crate::diag::{bail, error, SourceResult, StrResult};
+use crate::diag::{bail, SourceResult, StrResult};
use crate::engine::Engine;
use crate::foundations::{
cast, category, elem, Args, Array, Cast, Category, Construct, Content, Dict, Fold,
@@ -228,11 +228,9 @@ pub struct TextElem {
if let Some(paint) = &paint {
if paint.v.relative() == Smart::Custom(RelativeTo::Self_) {
bail!(
- error!(
- paint.span,
- "gradients and patterns on text must be relative to the parent"
- )
- .with_hint("make sure to set `relative: auto` on your text fill")
+ paint.span,
+ "gradients and patterns on text must be relative to the parent";
+ hint: "make sure to set `relative: auto` on your text fill"
);
}
}
diff --git a/crates/typst/src/visualize/color.rs b/crates/typst/src/visualize/color.rs
index e3c858ff..b327e92d 100644
--- a/crates/typst/src/visualize/color.rs
+++ b/crates/typst/src/visualize/color.rs
@@ -10,7 +10,7 @@ use palette::{
Darken, Desaturate, FromColor, Lighten, Okhsva, OklabHue, RgbHue, Saturate, ShiftHue,
};
-use crate::diag::{bail, error, At, SourceResult, StrResult};
+use crate::diag::{bail, At, SourceResult, StrResult};
use crate::foundations::{
array, cast, func, repr, scope, ty, Args, Array, IntoValue, Module, Repr, Scope, Str,
Value,
@@ -922,8 +922,10 @@ impl Color {
) -> SourceResult<Color> {
Ok(match self {
Self::Luma(_) => {
- bail!(error!(span, "cannot saturate grayscale color")
- .with_hint("try converting your color to RGB first"));
+ bail!(
+ span, "cannot saturate grayscale color";
+ hint: "try converting your color to RGB first"
+ );
}
Self::Oklab(_) => self.to_hsv().saturate(span, factor)?.to_oklab(),
Self::Oklch(_) => self.to_hsv().saturate(span, factor)?.to_oklch(),
@@ -946,8 +948,10 @@ impl Color {
) -> SourceResult<Color> {
Ok(match self {
Self::Luma(_) => {
- bail!(error!(span, "cannot desaturate grayscale color")
- .with_hint("try converting your color to RGB first"));
+ bail!(
+ span, "cannot desaturate grayscale color";
+ hint: "try converting your color to RGB first"
+ );
}
Self::Oklab(_) => self.to_hsv().desaturate(span, factor)?.to_oklab(),
Self::Oklch(_) => self.to_hsv().desaturate(span, factor)?.to_oklch(),
diff --git a/crates/typst/src/visualize/gradient.rs b/crates/typst/src/visualize/gradient.rs
index 4e804d9a..bd08254c 100644
--- a/crates/typst/src/visualize/gradient.rs
+++ b/crates/typst/src/visualize/gradient.rs
@@ -6,7 +6,7 @@ use std::sync::Arc;
use ecow::EcoString;
use kurbo::Vec2;
-use crate::diag::{bail, error, SourceResult};
+use crate::diag::{bail, SourceResult};
use crate::foundations::{
array, cast, func, scope, ty, Args, Array, Cast, Func, IntoValue, Repr, Smart,
};
@@ -231,8 +231,10 @@ impl Gradient {
};
if stops.len() < 2 {
- bail!(error!(span, "a gradient must have at least two stops")
- .with_hint("try filling the shape with a single color instead"));
+ bail!(
+ span, "a gradient must have at least two stops";
+ hint: "try filling the shape with a single color instead"
+ );
}
Ok(Self::Linear(Arc::new(LinearGradient {
@@ -332,24 +334,29 @@ impl Gradient {
focal_radius: Spanned<Ratio>,
) -> SourceResult<Gradient> {
if stops.len() < 2 {
- bail!(error!(span, "a gradient must have at least two stops")
- .with_hint("try filling the shape with a single color instead"));
+ bail!(
+ span, "a gradient must have at least two stops";
+ hint: "try filling the shape with a single color instead"
+ );
}
if focal_radius.v > radius.v {
- bail!(error!(
+ bail!(
focal_radius.span,
- "the focal radius must be smaller than the end radius"
- )
- .with_hint("try using a focal radius of `0%` instead"));
+ "the focal radius must be smaller than the end radius";
+ hint: "try using a focal radius of `0%` instead"
+ );
}
let focal_center = focal_center.unwrap_or(center);
let d_center_sqr = (focal_center.x - center.x).get().powi(2)
+ (focal_center.y - center.y).get().powi(2);
if d_center_sqr.sqrt() >= (radius.v - focal_radius.v).get() {
- bail!(error!(span, "the focal circle must be inside of the end circle")
- .with_hint("try using a focal center of `auto` instead"));
+ bail!(
+ span,
+ "the focal circle must be inside of the end circle";
+ hint: "try using a focal center of `auto` instead"
+ );
}
Ok(Gradient::Radial(Arc::new(RadialGradient {
@@ -419,8 +426,10 @@ impl Gradient {
center: Axes<Ratio>,
) -> SourceResult<Gradient> {
if stops.len() < 2 {
- bail!(error!(span, "a gradient must have at least two stops")
- .with_hint("try filling the shape with a single color instead"));
+ bail!(
+ span, "a gradient must have at least two stops";
+ hint: "try filling the shape with a single color instead"
+ );
}
Ok(Gradient::Conic(Arc::new(ConicGradient {
@@ -1154,11 +1163,10 @@ fn process_stops(stops: &[Spanned<GradientStop>]) -> SourceResult<Vec<(Color, Ra
let mut last_stop = f64::NEG_INFINITY;
for Spanned { v: stop, span } in stops.iter() {
let Some(stop) = stop.offset else {
- bail!(error!(
- *span,
- "either all stops must have an offset or none of them can"
- )
- .with_hint("try adding an offset to all stops"));
+ bail!(
+ *span, "either all stops must have an offset or none of them can";
+ hint: "try adding an offset to all stops"
+ );
};
if stop.get() < last_stop {
@@ -1179,13 +1187,19 @@ fn process_stops(stops: &[Spanned<GradientStop>]) -> SourceResult<Vec<(Color, Ra
.collect::<SourceResult<Vec<_>>>()?;
if out[0].1 != Ratio::zero() {
- bail!(error!(stops[0].span, "first stop must have an offset of 0%")
- .with_hint("try setting this stop to `0%`"));
+ bail!(
+ stops[0].span,
+ "first stop must have an offset of 0";
+ hint: "try setting this stop to `0%`"
+ );
}
if out[out.len() - 1].1 != Ratio::one() {
- bail!(error!(stops[0].span, "last stop must have an offset of 100%")
- .with_hint("try setting this stop to `100%`"));
+ bail!(
+ stops[out.len() - 1].span,
+ "last stop must have an offset of 100%";
+ hint: "try setting this stop to `100%`"
+ );
}
return Ok(out);
diff --git a/crates/typst/src/visualize/pattern.rs b/crates/typst/src/visualize/pattern.rs
index 3014a8e0..87cae4e5 100644
--- a/crates/typst/src/visualize/pattern.rs
+++ b/crates/typst/src/visualize/pattern.rs
@@ -4,7 +4,7 @@ use std::sync::Arc;
use comemo::Prehashed;
use ecow::{eco_format, EcoString};
-use crate::diag::{bail, error, SourceResult};
+use crate::diag::{bail, SourceResult};
use crate::engine::Engine;
use crate::foundations::{func, scope, ty, Content, Repr, Smart, StyleChain};
use crate::layout::{Abs, Axes, Em, Frame, Layout, Length, Regions, Size};
@@ -181,8 +181,10 @@ impl Pattern {
// Check that the frame is non-zero.
if size.is_auto() && frame.size().is_zero() {
- bail!(error!(span, "pattern tile size must be non-zero")
- .with_hint("try setting the size manually"));
+ bail!(
+ span, "pattern tile size must be non-zero";
+ hint: "try setting the size manually"
+ );
}
// Set the size of the frame if the size is enforced.