use crate::location::SourceCoords;
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum DiagKind {
Error,
Warning,
Note,
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Subsystem {
Unspecified,
Lexer,
Parser,
}
#[derive(Copy, Clone, Debug)]
pub struct OutputOptions {
pub show_colors: bool,
pub preferred_max_error_width: Option<usize>,
}
impl OutputOptions {
pub const TAB_STOP: usize = 8;
pub const MINIMUM_SOURCE_CONTEXT: usize = 16;
}
impl Default for OutputOptions {
fn default() -> Self {
OutputOptions {
show_colors: true,
preferred_max_error_width: None,
}
}
}
#[derive(Clone, Debug)]
pub struct ResolvedDiagnostic {
pub kind: DiagKind,
pub file_name: String,
pub line: u32,
pub col: u32,
pub message: String,
pub source_line: Option<String>,
pub range_cols: Option<(u32, u32)>,
}
pub trait DiagHandler {
fn handle(&mut self, diag: &ResolvedDiagnostic);
fn as_any(&self) -> &dyn std::any::Any;
}
pub trait CoordTranslator {
fn translate(&self, coords: &mut SourceCoords);
}
pub struct CollectingHandler {
messages: Vec<ResolvedDiagnostic>,
}
impl CollectingHandler {
pub fn new() -> CollectingHandler {
CollectingHandler {
messages: Vec::new(),
}
}
pub fn messages(&self) -> &[ResolvedDiagnostic] {
&self.messages
}
}
impl Default for CollectingHandler {
fn default() -> Self {
Self::new()
}
}
impl DiagHandler for CollectingHandler {
fn handle(&mut self, diag: &ResolvedDiagnostic) {
self.messages.push(diag.clone());
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Warning {
NoWarning,
UndefinedVariable,
DirectEval,
EvalDisabled,
UnresolvedStaticRequire,
Misc,
}
impl Warning {
pub const COUNT: usize = 6;
pub fn index(self) -> usize {
self as usize
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn collecting_handler_records() {
let mut h = CollectingHandler::new();
h.handle(&ResolvedDiagnostic {
kind: DiagKind::Error,
line: 3,
col: 5,
file_name: "a.js".into(),
message: "boom".into(),
source_line: Some(" let x".into()),
range_cols: None,
});
assert_eq!(h.messages().len(), 1);
assert_eq!(h.messages()[0].kind, DiagKind::Error);
assert_eq!((h.messages()[0].line, h.messages()[0].col), (3, 5));
}
#[test]
fn output_options_defaults() {
let o = OutputOptions::default();
assert!(o.show_colors);
assert_eq!(OutputOptions::TAB_STOP, 8);
}
#[test]
fn warning_index_within_count() {
assert_eq!(Warning::NoWarning.index(), 0);
assert!(Warning::Misc.index() < Warning::COUNT);
assert_eq!(Warning::COUNT, 6);
}
}