l10n_impl 0.1.3

Proc macros for l10n.
Documentation
use crate::ast::{MessageArgs, MessageKey};
use crate::instance::L10N;
use l10n_core::l10n::TranslateError;
use proc_macro2::Span;
use quote::ToTokens;
use std::collections::HashSet;
use syn::{Error, LitStr, Result};

pub fn validate_l10n(
    resource: &LitStr,
    key: &MessageKey,
    arguments: &MessageArgs,
    span_missing_arguments: Span,
) -> Result<()> {
    let required_arguments = L10N
        .as_ref()
        .map_err(|err| Error::new(Span::call_site(), err))?
        .required_variables(&resource.value(), &key.value())
        .map_err(|err| match err {
            TranslateError::ResourceNotExists(_) => Error::new_spanned(resource, err),
            TranslateError::MessageIdNotExists { .. } => Error::new(key.id_span(), err),
            _ => Error::new_spanned(key, err),
        })?;

    if arguments.is_complete() {
        let actual_arguments: HashSet<_> = arguments.iter().map(|arg| arg.name().value()).collect();
        let mut missing_arguments: Vec<_> = required_arguments
            .into_iter()
            .filter(|name| !actual_arguments.contains(*name))
            .collect();

        if !missing_arguments.is_empty() {
            missing_arguments.sort();
            return Err(Error::new(
                span_missing_arguments,
                format!(
                    r#"missing arguments: "{}" for resource: {} and key: {}"#,
                    missing_arguments.join("\", \""),
                    resource.to_token_stream(),
                    key.to_token_stream()
                ),
            ));
        }
    }

    Ok(())
}