use heck::ToSnakeCase;
use itertools::Itertools;
use proc_macro2::{Ident, Span, TokenStream};
use quote::quote;
use std::convert::AsRef;
pub fn quote_ident(value: impl AsRef<str>) -> TokenStream {
let ident = Ident::new(value.as_ref(), Span::call_site());
quote!(#ident)
}
pub fn quote_escaped_ident(value: impl AsRef<str>) -> TokenStream {
quote_ident(escape_identifier(value))
}
pub fn make_ignored_ident(value: impl AsRef<str>) -> String {
format!("_{}", value.as_ref())
}
pub fn to_module_path<'a, I: IntoIterator<Item = &'a str>>(path: I) -> String {
path.into_iter().join(".")
}
pub fn to_rust_identifier(value: impl AsRef<str>) -> String {
escape_identifier(value.as_ref().to_snake_case())
}
pub fn normalize_generic_param(param: &str) -> &str {
match param.split('_').next() {
Some(s) => s,
None => param,
}
}
fn escape_identifier(value: impl AsRef<str>) -> String {
let mut sanitized_ident = value.as_ref().replace('-', "_").replace('$', "_").replace('.', "_");
escape_keyword(&mut sanitized_ident);
sanitized_ident
}
fn escape_keyword(ident: &mut String) -> &mut String {
match ident.as_str() {
"as" | "break" | "const" | "continue" | "else" | "enum" | "false" | "fn" | "for" | "if" | "impl" | "in"
| "let" | "loop" | "match" | "mod" | "move" | "mut" | "pub" | "ref" | "return" | "static" | "struct"
| "trait" | "true" | "type" | "unsafe" | "use" | "where" | "while" | "dyn" | "abstract" | "become" | "box"
| "do" | "final" | "macro" | "override" | "priv" | "typeof" | "unsized" | "virtual" | "yield" | "async"
| "await" | "try" | "self" | "super" | "extern" | "crate" => *ident += "_",
_ => (),
}
ident
}