// Diagnostic system // // Copyright (C) 2014-2021 Ryan Specialty Group, LLC. // // This file is part of TAME. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . //! Diagnostic system for error reporting. //! //! This system is heavily motivated by Rust's. //! While the data structures and organization may differ, //! the diagnostic output is visually similar. mod report; mod resolver; pub use report::{Reporter, VisualReporter}; pub use resolver::FsSpanResolver; use core::fmt; use std::{borrow::Cow, error::Error, fmt::Display}; use crate::span::Span; /// Diagnostic report. /// /// This describes an error condition or other special event using a series /// of [`Span`]s to describe the source, cause, and circumstances around /// an event. pub trait Diagnostic: Error + Sized { /// Produce a series of [`AnnotatedSpan`]s describing the source and /// circumstances of the diagnostic event. fn describe(&self) -> Vec; } /// Diagnostic severity level. /// /// Levels are used both for entire reports and for styling of individual /// [`AnnotatedSpan`]s. /// /// Lower levels are more severe /// (e.g. levelĀ 1 is the worst). #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)] #[repr(u8)] pub enum Level { /// An error internal to TAMER that the user cannot resolve, /// but may be able to work around. InternalError = 1, /// A user-resolvable error. /// /// These represent errors resulting from the user's input. Error, /// Useful information that supplements other messages. /// /// This is most often used when multiple spans are in play for a given /// diagnostic report. Note, /// Additional advice to the user that may help in debugging or fixing a /// problem. /// /// These messages may suggest concrete fixes and are intended to /// hopefully replace having to request advice from a human. /// Unlike other severity levels which provide concrete factual /// information, /// help messages may be more speculative. #[default] Help, } impl Display for Level { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Level::InternalError => write!(f, "internal error"), Level::Error => write!(f, "error"), Level::Note => write!(f, "note"), Level::Help => write!(f, "help"), } } } /// A label associated with a report or [`Span`]. /// /// See [`AnnotatedSpan`]. #[derive(Debug, PartialEq, Eq, Clone)] pub struct Label<'a>(Cow<'a, str>); impl<'a> Display for Label<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { Display::fmt(&self.0, f) } } impl<'a> From for Label<'a> { fn from(s: String) -> Self { Self(Cow::Owned(s)) } } impl<'a> From<&'a str> for Label<'a> { fn from(s: &'a str) -> Self { Self(Cow::Borrowed(s)) } } /// A span with an associated severity level and optional label. /// /// Annotated spans are intended to guide users through debugging a /// diagnostic message by describing important source locations that /// contribute to a given diagnostic event. #[derive(Debug, PartialEq, Eq, Clone)] pub struct AnnotatedSpan<'l>(Span, Level, Option>); impl<'l> AnnotatedSpan<'l> { pub fn with_help>>( self, label: L, ) -> [AnnotatedSpan<'l>; 2] { let span = self.0; [self, span.help(label)] } } impl<'l> From> for Vec> { fn from(x: AnnotatedSpan<'l>) -> Self { vec![x] } } pub trait Annotate: Sized { /// Annotate a [`Span`] with a severity [`Level`] and an optional /// [`Label`] to display alongside of it. /// /// You may wish to use one of the more specific methods that provide a /// more pleasent interface. fn annotate(self, level: Level, label: Option