use proc_macro_error::emit_call_site_warning;
use syn::{FnArg, Pat, Type};
use super::extractor_types::ExtractorType;
#[derive(Clone)]
pub struct ParamInfo {
pub pat: Pat,
pub ty: Type,
pub extractor_type: ExtractorType,
}
pub fn analyze_params(
sig: &syn::Signature,
extractor_map: &std::collections::HashMap<String, ExtractorType>,
) -> Vec<ParamInfo> {
let mut params = Vec::new();
let mut seen_params = std::collections::HashSet::new();
for input in &sig.inputs {
if let FnArg::Typed(pat_type) = input {
let pat = (*pat_type.pat).clone();
let ty = (*pat_type.ty).clone();
let param_name = if let Pat::Ident(pat_ident) = &pat {
pat_ident.ident.to_string()
} else {
emit_call_site_warning!(
"Complex pattern in function parameter. Extractor mapping may not work correctly"
);
"unknown".to_string()
};
if !seen_params.insert(param_name.clone()) {
emit_call_site_warning!(
"Duplicate parameter name '{}' found in function signature",
param_name
);
}
let extractor_type = extractor_map
.get(¶m_name)
.cloned()
.unwrap_or_else(|| {
if param_name != "unknown" {
emit_call_site_warning!(
"Parameter '{}' has no extractor specified. It will not receive any data from the request",
param_name
);
}
ExtractorType::None
});
params.push(ParamInfo {
pat,
ty,
extractor_type,
});
}
}
for (extractor_name, extractor_type) in extractor_map {
if !seen_params.contains(extractor_name) {
emit_call_site_warning!(
"Extractor specified for parameter '{}' ({:?}) but no parameter with that name exists in the function signature",
extractor_name,
extractor_type
);
}
}
params
}