use waddling_errors::prelude::*;
use waddling_errors::{ComponentIdDocumented, PrimaryIdDocumented};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
enum Component {
Parser,
Semantic,
}
impl ComponentId for Component {
fn as_str(&self) -> &'static str {
match self {
Component::Parser => "PARSER",
Component::Semantic => "SEMANTIC",
}
}
}
impl ComponentIdDocumented for Component {
fn description(&self) -> Option<&'static str> {
Some(match self {
Component::Parser => "Syntax parsing and tokenization errors",
Component::Semantic => "Type checking and semantic analysis errors",
})
}
fn examples(&self) -> &'static [&'static str] {
match self {
Component::Parser => &[
"E.PARSER.SYNTAX.001: Missing semicolon",
"E.PARSER.SYNTAX.002: Unexpected token",
],
Component::Semantic => &[
"E.SEMANTIC.TYPE.001: Type mismatch",
"E.SEMANTIC.TYPE.002: Undefined variable",
],
}
}
fn tags(&self) -> &'static [&'static str] {
match self {
Component::Parser => &["frontend", "syntax"],
Component::Semantic => &["frontend", "types", "analysis"],
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
enum Primary {
Syntax,
Type,
}
impl PrimaryId for Primary {
fn as_str(&self) -> &'static str {
match self {
Primary::Syntax => "SYNTAX",
Primary::Type => "TYPE",
}
}
}
impl PrimaryIdDocumented for Primary {
fn description(&self) -> Option<&'static str> {
Some(match self {
Primary::Syntax => "Syntax-level parsing errors and token issues",
Primary::Type => "Type system violations and inference failures",
})
}
fn related(&self) -> &'static [&'static str] {
match self {
Primary::Syntax => &["PARSE", "TOKEN"],
Primary::Type => &["INFER", "CHECK"],
}
}
}
const ERR_PARSER_SYNTAX: Code<Component, Primary> =
Code::error(Component::Parser, Primary::Syntax, 3);
const ERR_SEMANTIC_TYPE: Code<Component, Primary> =
Code::error(Component::Semantic, Primary::Type, 3);
fn main() {
println!("🦆 Documented Trait-Based Error Codes\n");
println!("======================================\n");
print_code_with_docs(ERR_PARSER_SYNTAX);
println!();
print_code_with_docs(ERR_SEMANTIC_TYPE);
}
fn print_code_with_docs(code: Code<Component, Primary>) {
println!("Code: {}", code.code());
println!("Severity: {}", code.severity().as_str());
println!();
let component = code.component();
println!("Component: {}", component.as_str());
if let Some(desc) = component.description() {
println!(" Description: {}", desc);
}
println!(" Tags: {:?}", component.tags());
println!(" Examples:");
for example in component.examples() {
println!(" - {}", example);
}
println!();
let primary = code.primary();
println!("Primary: {}", primary.as_str());
if let Some(desc) = primary.description() {
println!(" Description: {}", desc);
}
if !primary.related().is_empty() {
println!(" Related: {:?}", primary.related());
}
}