use super::diagnostic::Severity;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum RecoveryStrategy {
#[default]
SkipOnError,
SkipOnFatal,
AbortOnAny,
}
impl RecoveryStrategy {
pub fn decide(self, severity: Severity) -> RecoveryAction {
match (self, severity) {
(_, Severity::Info) | (_, Severity::Warning) => RecoveryAction::Continue,
(RecoveryStrategy::SkipOnError, Severity::Error) => RecoveryAction::SkipExpression,
(RecoveryStrategy::SkipOnError, Severity::Fatal) => RecoveryAction::SkipExpression,
(RecoveryStrategy::SkipOnFatal, Severity::Error) => RecoveryAction::SkipExpression,
(RecoveryStrategy::SkipOnFatal, Severity::Fatal) => RecoveryAction::AbortProgram,
(RecoveryStrategy::AbortOnAny, Severity::Error) => RecoveryAction::AbortProgram,
(RecoveryStrategy::AbortOnAny, Severity::Fatal) => RecoveryAction::AbortProgram,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum RecoveryAction {
Continue,
SkipExpression,
AbortProgram,
}
impl RecoveryAction {
pub fn is_abort(self) -> bool {
matches!(self, RecoveryAction::AbortProgram)
}
pub fn drops_expression(self) -> bool {
matches!(
self,
RecoveryAction::SkipExpression | RecoveryAction::AbortProgram
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_is_skip_on_error() {
assert_eq!(RecoveryStrategy::default(), RecoveryStrategy::SkipOnError);
}
#[test]
fn skip_on_error_never_aborts() {
let s = RecoveryStrategy::SkipOnError;
assert_eq!(s.decide(Severity::Info), RecoveryAction::Continue);
assert_eq!(s.decide(Severity::Warning), RecoveryAction::Continue);
assert_eq!(s.decide(Severity::Error), RecoveryAction::SkipExpression);
assert_eq!(s.decide(Severity::Fatal), RecoveryAction::SkipExpression);
}
#[test]
fn skip_on_fatal_aborts_only_on_fatal() {
let s = RecoveryStrategy::SkipOnFatal;
assert_eq!(s.decide(Severity::Warning), RecoveryAction::Continue);
assert_eq!(s.decide(Severity::Error), RecoveryAction::SkipExpression);
assert_eq!(s.decide(Severity::Fatal), RecoveryAction::AbortProgram);
}
#[test]
fn abort_on_any_aborts_on_both_error_and_fatal() {
let s = RecoveryStrategy::AbortOnAny;
assert_eq!(s.decide(Severity::Info), RecoveryAction::Continue);
assert_eq!(s.decide(Severity::Warning), RecoveryAction::Continue);
assert_eq!(s.decide(Severity::Error), RecoveryAction::AbortProgram);
assert_eq!(s.decide(Severity::Fatal), RecoveryAction::AbortProgram);
}
#[test]
fn action_classifiers() {
assert!(RecoveryAction::AbortProgram.is_abort());
assert!(!RecoveryAction::SkipExpression.is_abort());
assert!(!RecoveryAction::Continue.is_abort());
assert!(!RecoveryAction::Continue.drops_expression());
assert!(RecoveryAction::SkipExpression.drops_expression());
assert!(RecoveryAction::AbortProgram.drops_expression());
}
}