use proc_macro::TokenStream;
use quote::{format_ident, quote};
use syn::parse_macro_input;
use convert_case::{Case, Casing};
type ColumnList = syn::punctuated::Punctuated<syn::ExprPath, syn::Token![,]>;
struct MakeIndexParams {
unique: Option<syn::Token![!]>,
name: syn::Ident,
#[allow(dead_code)]
comma: syn::Token![,],
columns: ColumnList,
}
impl syn::parse::Parse for MakeIndexParams {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
Ok(Self {
unique: input.parse()?,
name: input.parse()?,
comma: input.parse()?,
columns: ColumnList::parse_separated_nonempty(input)?,
})
}
}
pub(crate) fn do_make_index(
tokens: TokenStream,
microrm_ref: proc_macro2::TokenStream,
) -> TokenStream {
let input = parse_macro_input!(tokens as MakeIndexParams);
let index_struct_name = input.name;
let index_sql_name = format!("{}", index_struct_name).to_case(Case::Snake);
let columns = input.columns.clone().into_iter();
let unique = input.unique.is_some();
let first_column = columns.clone().next().unwrap();
let columns_array_name = format_ident!(
"INDEX_COLUMN_NAMES_{}",
index_struct_name.to_string().to_case(Case::ScreamingSnake)
);
let column_count = columns.len();
quote! {
pub struct #index_struct_name ();
#microrm_ref::re_export::lazy_static::lazy_static!{
static ref #columns_array_name : [&'static str; #column_count] = {
use #microrm_ref::entity::EntityColumn;
[
#( #columns . name() ),*
]
};
}
impl #microrm_ref::entity::Index for #index_struct_name {
fn index_name() -> &'static str {
#index_sql_name
}
fn table_name() -> &'static str {
use #microrm_ref::entity::EntityColumn;
#first_column.table_name()
}
fn column_names() -> &'static [&'static str] {
#columns_array_name.as_ref()
}
fn unique() -> bool where Self: Sized {
#unique
}
}
}
.into()
}