use sealed::sealed;
use crate::{ColorPalette, Diagnostic, DiagnosticCode, code};
pub trait Lenient {}
pub trait Diagnose<S, D = code::DefaultDiscriminant> {
fn diagnose(self, colors: &ColorPalette) -> Diagnostic<S, D>;
}
impl<T, S, D> Diagnose<S, D> for (S, T)
where
T: DiagnosticGroup<D> + PartialDiagnose<S, D> + Sized,
{
fn diagnose(self, colors: &ColorPalette) -> Diagnostic<S, D> {
let (span, group_member) = self;
let diagnostic = group_member.make_diagnostic(span);
group_member.partial_diagnose(diagnostic, colors)
}
}
pub trait PartialDiagnose<S, D = code::DefaultDiscriminant> {
fn partial_diagnose(
self,
diagnostic: Diagnostic<S, D>,
colors: &ColorPalette,
) -> Diagnostic<S, D>;
}
pub trait DiagnosticGroup<D = code::DefaultDiscriminant> {
fn message(&self) -> Box<dyn FnOnce() -> String>;
fn diagnostic_code(&self) -> DiagnosticCode<D>;
}
#[sealed]
pub trait DiagnosticGroupExt<D = code::DefaultDiscriminant>: DiagnosticGroup<D> {
fn make_diagnostic<S>(&self, span: S) -> Diagnostic<S, D> {
Diagnostic::new::<Self>(self, span)
}
fn into_diagnostic<S>(self, span: S, colors: &ColorPalette) -> Diagnostic<S, D>
where
Self: PartialDiagnose<S, D> + Sized,
{
(span, self).diagnose(colors)
}
}
#[sealed]
impl<T, D> DiagnosticGroupExt<D> for T where T: DiagnosticGroup<D> {}