mirror of
https://github.com/martinvonz/jj.git
synced 2025-02-08 05:30:25 +00:00
dsl_util: add basic diagnostics receiver
This object will be passed around AST processing functions. It's basically a Vec<ParseError>.
This commit is contained in:
parent
8dd3003bec
commit
6b92305102
1 changed files with 62 additions and 0 deletions
|
@ -17,11 +17,73 @@
|
||||||
use std::array;
|
use std::array;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::slice;
|
||||||
|
|
||||||
use itertools::Itertools as _;
|
use itertools::Itertools as _;
|
||||||
use pest::iterators::Pairs;
|
use pest::iterators::Pairs;
|
||||||
use pest::RuleType;
|
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<T> {
|
||||||
|
// This might be extended to [{ kind: Warning|Error, message: T }, ..].
|
||||||
|
diagnostics: Vec<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Diagnostics<T> {
|
||||||
|
/// 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<U>(&mut self, diagnostics: Diagnostics<U>, mut f: impl FnMut(U) -> T) {
|
||||||
|
self.diagnostics
|
||||||
|
.extend(diagnostics.diagnostics.into_iter().map(&mut f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Default for Diagnostics<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> IntoIterator for &'a Diagnostics<T> {
|
||||||
|
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.
|
/// AST node without type or name checking.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct ExpressionNode<'i, T> {
|
pub struct ExpressionNode<'i, T> {
|
||||||
|
|
Loading…
Reference in a new issue