use crate::adapters::analyzers::architecture::{MatchLocation, ViolationKind};
use syn::spanned::Spanned;
use syn::visit::{self, Visit};
pub fn find_macro_calls(file: &str, ast: &syn::File, names: &[String]) -> Vec<MatchLocation> {
let mut visitor = MacroCallVisitor {
file,
names,
hits: Vec::new(),
};
visitor.visit_file(ast);
visitor.hits
}
struct MacroCallVisitor<'a> {
file: &'a str,
names: &'a [String],
hits: Vec<MatchLocation>,
}
impl<'ast> Visit<'ast> for MacroCallVisitor<'_> {
fn visit_macro(&mut self, node: &'ast syn::Macro) {
if let Some(last) = node.path.segments.last() {
let name = last.ident.to_string();
if self.names.iter().any(|n| n == &name) {
let start = last.ident.span().start();
self.hits.push(MatchLocation {
file: self.file.to_string(),
line: start.line,
column: start.column,
kind: ViolationKind::MacroCall { name },
});
}
}
use syn::punctuated::Punctuated;
if let Ok(args) = syn::parse::Parser::parse2(
Punctuated::<syn::Expr, syn::Token![,]>::parse_terminated,
node.tokens.clone(),
) {
args.iter().for_each(|expr| visit::visit_expr(self, expr));
}
visit::visit_macro(self, node);
}
}