From bbcdeb128cce04cd95714b7bc7af5a23a7e38bd2 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Wed, 29 Jul 2020 18:09:51 +0200 Subject: =?UTF-8?q?Move,=20rename=20and=20switch=20some=20things=20(boring?= =?UTF-8?q?)=20=F0=9F=9A=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Problems -> Diagnostics - Position -> Pos - offset_spans -> Offset trait - Size -> Length (and some more size types renamed) - Paper into its own module - scope::Parser -> parsing::CallParser - Create `Decorations` alias - Remove lots of double newlines - Switch from f32 to f64 --- src/diagnostic.rs | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 src/diagnostic.rs (limited to 'src/diagnostic.rs') diff --git a/src/diagnostic.rs b/src/diagnostic.rs new file mode 100644 index 00000000..a5c5d0b8 --- /dev/null +++ b/src/diagnostic.rs @@ -0,0 +1,91 @@ +//! Diagnostics (errors / warnings) in source code. +//! +//! There are no fatal errors. 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 diagnostics. +pub type Diagnostics = SpanVec; + +/// A diagnostic that arose in parsing or layouting. +#[derive(Debug, Clone, Eq, PartialEq, Serialize)] +pub struct Diagnostic { + /// How severe / important the diagnostic is. + pub level: Level, + /// A message describing the diagnostic. + pub message: String, +} + +/// How severe / important a diagnostic is. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize)] +#[serde(rename_all = "camelCase")] +pub enum Level { + Warning, + Error, +} + +impl Diagnostic { + /// Create a new diagnostic from message and level. + pub fn new(message: impl Into, level: Level) -> Self { + Self { message: message.into(), level } + } +} + +/// Construct a diagnostic with `Error` level. +/// +/// ``` +/// # 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_diagnostic!($crate::diagnostic::Level::Error; $($tts)*) + }; +} + +/// Construct a diagnostic with `Warning` level. +/// +/// This works exactly like `error!`. See its documentation for more +/// information. +#[macro_export] +macro_rules! warning { + ($($tts:tt)*) => { + $crate::__impl_diagnostic!($crate::diagnostic::Level::Warning; $($tts)*) + }; +} + +/// Backs the `error!` and `warning!` macros. +#[macro_export] +#[doc(hidden)] +macro_rules! __impl_diagnostic { + ($level:expr; @$feedback:expr, $($tts:tt)*) => { + $feedback.diagnostics.push($crate::__impl_diagnostic!($level; $($tts)*)); + }; + + ($level:expr; $fmt:literal $($tts:tt)*) => { + $crate::diagnostic::Diagnostic::new(format!($fmt $($tts)*), $level) + }; + + ($level:expr; $span:expr, $fmt:literal $($tts:tt)*) => { + $crate::syntax::span::Spanned::new( + $crate::__impl_diagnostic!($level; $fmt $($tts)*), + $span, + ) + }; +} -- cgit v1.2.3