summaryrefslogtreecommitdiff
path: root/src/diag.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2021-08-13 12:21:14 +0200
committerLaurenz <laurmaedje@gmail.com>2021-08-13 14:33:58 +0200
commit144f20882136ef81b79d77bd8a68f42b76c66676 (patch)
tree7a452ab2a092f674d93cd994d80b88cc6808e540 /src/diag.rs
parentd002cdf451e1c6efbf7cd7f2303264526b6f8a92 (diff)
Add file information to spans
Diffstat (limited to 'src/diag.rs')
-rw-r--r--src/diag.rs104
1 files changed, 57 insertions, 47 deletions
diff --git a/src/diag.rs b/src/diag.rs
index 1905d480..154de24b 100644
--- a/src/diag.rs
+++ b/src/diag.rs
@@ -2,8 +2,18 @@
use serde::{Deserialize, Serialize};
-use crate::source::SourceId;
-use crate::syntax::Span;
+use crate::syntax::{Span, Spanned};
+
+/// Early-return with a vec-boxed [`Error`].
+macro_rules! bail {
+ ($span:expr, $message:expr $(,)?) => {
+ return Err($crate::diag::Error::boxed($span, $message,));
+ };
+
+ ($span:expr, $fmt:expr, $($arg:expr),+ $(,)?) => {
+ bail!($span, format!($fmt, $($arg),+));
+ };
+}
/// The result type for typesetting and all its subpasses.
pub type TypResult<T> = Result<T, Box<Vec<Error>>>;
@@ -14,35 +24,19 @@ pub type StrResult<T> = Result<T, String>;
/// An error in a source file.
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
pub struct Error {
- /// The id of the source file that contains the error.
- pub source: SourceId,
/// The erroneous location in the source code.
pub span: Span,
/// A diagnostic message describing the problem.
pub message: String,
/// The trace of function calls leading to the error.
- pub trace: Vec<(SourceId, Span, Tracepoint)>,
-}
-
-/// A part of an error's [trace](Error::trace).
-#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
-pub enum Tracepoint {
- /// A function call.
- Call(Option<String>),
- /// A module import.
- Import,
+ pub trace: Vec<Spanned<Tracepoint>>,
}
impl Error {
/// Create a new, bare error.
- pub fn new(
- source: SourceId,
- span: impl Into<Span>,
- message: impl Into<String>,
- ) -> Self {
+ pub fn new(span: Span, message: impl Into<String>) -> Self {
Self {
- source,
- span: span.into(),
+ span,
trace: vec![],
message: message.into(),
}
@@ -50,36 +44,52 @@ impl Error {
/// Create a boxed vector containing one error. The return value is suitable
/// as the `Err` variant of a [`TypResult`].
- pub fn boxed(
- source: SourceId,
- span: impl Into<Span>,
- message: impl Into<String>,
- ) -> Box<Vec<Self>> {
- Box::new(vec![Self::new(source, span, message)])
+ pub fn boxed(span: Span, message: impl Into<String>) -> Box<Vec<Self>> {
+ Box::new(vec![Self::new(span, message)])
}
+}
- /// Create a closure that contains the positional information for an error
- /// and just needs the message to yield a vec-boxed error.
- ///
- /// This is useful in to convert from [`StrResult`] to a [`TypResult`] using
- /// [`map_err`](Result::map_err).
- pub fn at<S: Into<String>>(
- source: SourceId,
- span: impl Into<Span>,
- ) -> impl FnOnce(S) -> Box<Vec<Self>> {
- move |message| Self::boxed(source, span, message)
+/// A part of an error's [trace](Error::trace).
+#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
+pub enum Tracepoint {
+ /// A function call.
+ Call(Option<String>),
+ /// A module import.
+ Import,
+}
+
+/// Convert a [`StrResult`] to a [`TypResult`] by adding span information.
+pub trait At<T> {
+ /// Add the span information.
+ fn at(self, span: Span) -> TypResult<T>;
+}
+
+impl<T> At<T> for StrResult<T> {
+ fn at(self, span: Span) -> TypResult<T> {
+ self.map_err(|message| Error::boxed(span, message))
}
}
-/// Early-return with a vec-boxed [`Error`].
-macro_rules! bail {
- ($source:expr, $span:expr, $message:expr $(,)?) => {
- return Err(Box::new(vec![$crate::diag::Error::new(
- $source, $span, $message,
- )]));
- };
+/// Enrich a [`TypResult`] with a tracepoint.
+pub trait Trace<T> {
+ /// Add the tracepoint to all errors that lie outside the `span`.
+ fn trace<F>(self, make_point: F, span: Span) -> Self
+ where
+ F: Fn() -> Tracepoint;
+}
- ($source:expr, $span:expr, $fmt:expr, $($arg:expr),+ $(,)?) => {
- bail!($source, $span, format!($fmt, $($arg),+));
- };
+impl<T> Trace<T> for TypResult<T> {
+ fn trace<F>(self, make_point: F, span: Span) -> Self
+ where
+ F: Fn() -> Tracepoint,
+ {
+ self.map_err(|mut errors| {
+ for error in errors.iter_mut() {
+ if !span.contains(error.span) {
+ error.trace.push(Spanned::new(make_point(), span));
+ }
+ }
+ errors
+ })
+ }
}