diman_unit_system 0.3.0

Internal procedural macros for diman.
Documentation
use proc_macro::{Diagnostic, Level};
use syn::Ident;

pub enum Error {
    Unresolvable(Vec<Ident>),
    Undefined(Vec<Ident>),
    Multiple(Vec<Vec<Ident>>),
}

pub type Result<T> = std::result::Result<T, Error>;

impl Error {
    pub fn emit(self) {
        match self {
            Error::Unresolvable(idents) => emit_unresolvable(idents),
            Error::Undefined(idents) => emit_undefined(idents),
            Error::Multiple(idents) => emit_multiple(idents),
        }
    }
}

fn emit_undefined(idents: Vec<Ident>) {
    for ident in idents {
        ident
            .span()
            .unwrap()
            .error(format!("Undefined identifier \"{}\".", ident))
            .emit();
    }
}

fn emit_unresolvable(idents: Vec<Ident>) {
    for ident in idents {
        ident
            .span()
            .unwrap()
            .error(format!("Unresolvable definition \"{}\".", ident))
            .help("Remove recursive definitions.")
            .emit();
    }
}

fn emit_multiple(idents: Vec<Vec<Ident>>) {
    for idents in idents {
        let name = &idents[0];
        Diagnostic::spanned(
            idents
                .iter()
                .map(|ident| ident.span().unwrap())
                .collect::<Vec<_>>(),
            Level::Error,
            format!("Identifier \"{}\" defined multiple times.", name),
        )
        .emit();
    }
}