From 6b923051026c5819568958028fd5872a86efa5e7 Mon Sep 17 00:00:00 2001 From: Yuya Nishihara Date: Thu, 19 Sep 2024 15:02:10 +0900 Subject: [PATCH] dsl_util: add basic diagnostics receiver This object will be passed around AST processing functions. It's basically a Vec. --- lib/src/dsl_util.rs | 62 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/lib/src/dsl_util.rs b/lib/src/dsl_util.rs index 183ec4675..4ceb00dcc 100644 --- a/lib/src/dsl_util.rs +++ b/lib/src/dsl_util.rs @@ -17,11 +17,73 @@ use std::array; use std::collections::HashMap; use std::fmt; +use std::slice; use itertools::Itertools as _; use pest::iterators::Pairs; use pest::RuleType; +/// Manages diagnostic messages emitted during parsing. +/// +/// `T` is usually a parse error type of the language, which contains a message +/// and source span of 'static lifetime. +#[derive(Debug)] +pub struct Diagnostics { + // This might be extended to [{ kind: Warning|Error, message: T }, ..]. + diagnostics: Vec, +} + +impl Diagnostics { + /// Creates new empty diagnostics collector. + pub fn new() -> Self { + Diagnostics { + diagnostics: Vec::new(), + } + } + + /// Returns `true` if there are no diagnostic messages. + pub fn is_empty(&self) -> bool { + self.diagnostics.is_empty() + } + + /// Returns the number of diagnostic messages. + pub fn len(&self) -> usize { + self.diagnostics.len() + } + + /// Returns iterator over diagnostic messages. + pub fn iter(&self) -> slice::Iter<'_, T> { + self.diagnostics.iter() + } + + /// Adds a diagnostic message of warning level. + pub fn add_warning(&mut self, diag: T) { + self.diagnostics.push(diag); + } + + /// Moves diagnostic messages of different type (such as fileset warnings + /// emitted within `file()` revset.) + pub fn extend_with(&mut self, diagnostics: Diagnostics, mut f: impl FnMut(U) -> T) { + self.diagnostics + .extend(diagnostics.diagnostics.into_iter().map(&mut f)); + } +} + +impl Default for Diagnostics { + fn default() -> Self { + Self::new() + } +} + +impl<'a, T> IntoIterator for &'a Diagnostics { + type Item = &'a T; + type IntoIter = slice::Iter<'a, T>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + /// AST node without type or name checking. #[derive(Clone, Debug, Eq, PartialEq)] pub struct ExpressionNode<'i, T> {