From e2ef4f64e777f293a0408d0f60cfed9de69c7bb6 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Sun, 26 Jul 2020 17:28:43 +0200 Subject: =?UTF-8?q?Rename=20errors=20to=20problems=20and=20make=20error!?= =?UTF-8?q?=20macro=20more=20ergonomic=20=F0=9F=A7=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also adds a `warning!` macro. --- src/problem.rs | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 src/problem.rs (limited to 'src/problem.rs') diff --git a/src/problem.rs b/src/problem.rs new file mode 100644 index 00000000..3c2d3635 --- /dev/null +++ b/src/problem.rs @@ -0,0 +1,94 @@ +//! Problems (errors / warnings) in _Typst_ documents. +//! +//! There are no fatal errors in _Typst_. The document will always compile and +//! yield a layout. However, this is a best effort process and bad things will +//! still generate errors and warnings. + +use serde::Serialize; +use crate::syntax::span::SpanVec; + + +/// A list of spanned problems. +pub type Problems = SpanVec; + +/// A problem that arose in parsing or layouting. +#[derive(Debug, Clone, Eq, PartialEq, Serialize)] +pub struct Problem { + /// How severe / important the problem is. + pub severity: Severity, + /// A message describing the problem. + pub message: String, +} + +/// How severe / important a problem is. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize)] +#[serde(rename_all = "camelCase")] +pub enum Severity { + /// Something in the code is not good. + Warning, + /// Something in the code is wrong! + Error, +} + +impl Problem { + /// Create a new problem from message and severity. + pub fn new(message: impl Into, severity: Severity) -> Self { + Self { message: message.into(), severity } + } +} + +/// Construct a problem with `Error` severity. +/// +/// ``` +/// # use typstc::error; +/// # use typstc::syntax::span::Span; +/// # use typstc::Feedback; +/// # let span = Span::ZERO; +/// # let mut feedback = Feedback::new(); +/// # let name = ""; +/// // Create formatted error values. +/// let error = error!("expected {}", name); +/// +/// // Create spanned errors. +/// let spanned = error!(span, "there is an error here"); +/// +/// // Create an error and directly add it to existing feedback. +/// error!(@feedback, span, "oh no!"); +/// ``` +#[macro_export] +macro_rules! error { + ($($tts:tt)*) => { + $crate::__impl_problem!($crate::problem::Severity::Error; $($tts)*) + }; +} + +/// Construct a problem with `Warning` severity. +/// +/// This works exactly like `error!`. See its documentation for more +/// information. +#[macro_export] +macro_rules! warning { + ($($tts:tt)*) => { + $crate::__impl_problem!($crate::problem::Severity::Warning; $($tts)*) + }; +} + +/// Backs the `error!` and `warning!` macros. +#[macro_export] +#[doc(hidden)] +macro_rules! __impl_problem { + ($severity:expr; @$feedback:expr, $($tts:tt)*) => { + $feedback.problems.push($crate::__impl_problem!($severity; $($tts)*)); + }; + + ($severity:expr; $fmt:literal $($tts:tt)*) => { + $crate::problem::Problem::new(format!($fmt $($tts)*), $severity) + }; + + ($severity:expr; $span:expr, $fmt:literal $($tts:tt)*) => { + $crate::syntax::span::Spanned::new( + $crate::__impl_problem!($severity; $fmt $($tts)*), + $span, + ) + }; +} -- cgit v1.2.3