Summary
A macro_rules! macro is not extracted: it never becomes a node, and a name!(...) invocation of a locally-defined macro resolves to nothing.
Repro
macro_rules! my_vec {
($($x:expr),*) => { vec![$($x),*] };
}
fn build() -> Vec<i32> {
my_vec!(1, 2, 3)
}
No my_vec node, no build -> my_vec edge.
Cause
The macro_definition node type has no branch in the walker, so the macro is dropped. Invocations are macro_invocation nodes (never call_expression), which walk_calls doesn't handle, so even if the definition existed there would be nothing linking to it.
Expected
Emit a node per macro_definition and resolve a bare name! invocation to it with a calls edge. A macro and a function can share a name (vec! vs vec), so macros should be tracked separately / id-qualified to avoid cross-binding. A scoped invocation (log::info!) is cross-crate and should stay unresolved (fail-closed).
Fix + regression tests ready.
Summary
A
macro_rules!macro is not extracted: it never becomes a node, and aname!(...)invocation of a locally-defined macro resolves to nothing.Repro
No
my_vecnode, nobuild -> my_vecedge.Cause
The
macro_definitionnode type has no branch in the walker, so the macro is dropped. Invocations aremacro_invocationnodes (nevercall_expression), whichwalk_callsdoesn't handle, so even if the definition existed there would be nothing linking to it.Expected
Emit a node per
macro_definitionand resolve a barename!invocation to it with acallsedge. A macro and a function can share a name (vec!vsvec), so macros should be tracked separately / id-qualified to avoid cross-binding. A scoped invocation (log::info!) is cross-crate and should stay unresolved (fail-closed).Fix + regression tests ready.