use crate::utils;
use proc_macro::{TokenStream, TokenTree};
use quote::quote;
use regex::Regex;
use std::fs;
use syn::{parse_file, parse_macro_input, parse_str, File, Item, ItemFn, Stmt};
pub(crate) fn scope_impl(args: TokenStream, input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as ItemFn);
let ItemFn {
sig,
vis,
block,
attrs,
} = input;
let statements = block.stmts;
let mut is_file = false;
let mut file = String::new();
for arg in args.into_iter() {
if matches!(&arg, TokenTree::Ident(_)) && "file".eq(&arg.to_string()) {
is_file = true;
}
if is_file && matches!(&arg, TokenTree::Literal(_)) {
let temp = arg.to_string();
file = temp.clone().replace("\"", "");
}
}
let mut fn_name_list: Vec<String> = vec![];
let mut scope_var_name = String::new();
let patterns =
r"(\#\s*\[\s*post)|(\#\s*\[\s*macros\s*::\s*post)|(\#\s*\[\s*get)|(\#\s*\[\s*macros\s*::\s*get)|(\#\s*\[\s*put)|(\#\s*\[\s*macros\s*::\s*put)|(\#\s*\[\s*delete)|(\#\s*\[\s*macros\s*::\s*delete)|(\#\s*\[\s*head)|(\#\s*\[\s*macros\s*::\s*head)";
let re = Regex::new(patterns).unwrap();
let content = fs::read_to_string(file).expect("Should have been able to read the file");
let syntax: File = parse_file(&content).expect("Not valid Rust code");
for item in syntax.items {
if let Item::Fn(ItemFn { sig, attrs, .. }) = item {
let fn_name = &sig.ident;
if fn_name.eq("routes") {
let args_map = utils::parse_group_extract_args(quote! {#sig});
let cfg = args_map.values().next().unwrap();
for statement in &statements {
let mut is_cfg_ident = false;
let statement_tokens = quote! {#statement};
for statement_token in statement_tokens {
match statement_token {
proc_macro2::TokenTree::Ident(ref ident) => {
if !cfg.eq(&ident.to_string()) && !is_cfg_ident {
continue;
}
is_cfg_ident = true;
}
proc_macro2::TokenTree::Group(ref group) => {
if is_cfg_ident {
let group_tokens = group.stream();
for group_token in group_tokens {
match group_token {
proc_macro2::TokenTree::Ident(ref ident) => {
scope_var_name = ident.to_string();
}
_ => (),
}
}
}
}
_ => (),
}
}
}
} else {
for attr in &attrs {
if re.is_match(quote! {#attr}.to_string().as_str()) {
fn_name_list.push(fn_name.to_string());
break;
}
}
}
}
}
let mut new_statements: Vec<Stmt> = vec![];
let mut i = 0;
let statements_len = &statements.len();
let scope_var_name = scope_var_name.replace("\"", "");
for statement in &statements {
new_statements.push(statement.clone());
if i == statements_len - 2 {
for fn_name in fn_name_list.clone() {
let fn_name = fn_name.replace("\"", "");
let stmt = parse_str::<Stmt>(format!(
"let {} = {}.service({});",
scope_var_name, scope_var_name, fn_name
).as_str())
.unwrap();
new_statements.push(stmt.clone());
}
}
i += 1;
}
quote!(
#(#attrs)*
#vis #sig {
#(#new_statements)*
}
)
.into()
}