Repository navigation
Description
Environment
codegraph 1.6.2 from npm, and current main (f72c9d2) built from source and run on Node 22.23.4. Linux, rustc 1.99.1, fresh codegraph init. The repro crate passes cargo check.
Problem
A call written inside a macro invocation gets no edge. The same call outside a macro links fine. In our crate (42 files) this is 18 missed call edges, all confirmed by rust-analyzer: format!, assert_eq!, vec!, serde_json::json!, tokio::select!. write! misses the same way. Same on 1.6.2 and on current main.
A matches! pattern with | gives no reference either: Code::is_known has no edge to Code. With a single variant (matches!(c, Code::Bad) in variant_in_macro) the reference is there.
Minimal repro
Cargo.toml:
[package]
name = "repro_macro"
version = "0.1.0"
edition = "2021"
[dependencies]
serde_json = "1"src/main.rs:
use serde_json::json;
use std::fmt;
pub enum Code {
Bad,
Good,
}
impl Code {
pub fn is_known(self) -> bool {
matches!(self, Code::Bad | Code::Good)
}
pub fn as_str(&self) -> &'static str {
match self {
Code::Bad => "bad",
Code::Good => "good",
}
}
}
pub struct Error {
code: Code,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "error {}", self.code.as_str())
}
}
fn label() -> String {
"x".to_string()
}
fn count() -> usize {
3
}
fn size() -> usize {
2
}
fn in_format() -> String {
format!("label {}", label())
}
fn in_assert() {
assert_eq!(count(), 3);
}
fn in_vec() -> Vec<bool> {
vec![false; size()]
}
fn in_json() -> serde_json::Value {
json!({"label": label(), "count": count()})
}
fn variant_in_macro(c: &Code) -> bool {
matches!(c, Code::Bad)
}
fn plain() -> String {
label()
}
fn main() {
let e = Error { code: Code::Good };
println!("{e} {} {} {:?}", in_format(), plain(), in_vec());
in_assert();
let _ = in_json();
let _ = variant_in_macro(&Code::Bad);
let _ = Code::Good.is_known();
}Actual
Edges in .codegraph/codegraph.db for these functions (1.6.2 and main give the same):
plain -> label resolvedBy exact-match, confidence 0.9, refName label (ok, calls, no macro)
variant_in_macro -> Code resolvedBy exact-match, confidence 0.9, refName Code (ok, references)
No edge at all from in_format, in_assert, in_vec, in_json, Error::fmt and Code::is_known.
Expected
- in_format -> label, in_assert -> count, in_vec -> size, in_json -> label and count, Error::fmt -> Code::as_str (calls).
- Code::is_known -> Code (references), same as variant_in_macro.
Notes
I think the macro arguments stay a token_tree in tree-sitter-rust and nothing walks it. For these std macros the arguments are plain expressions (comma separated, key: value in json!), so reading the token tree as expressions would cover most of them. rust-analyzer resolves all of these calls.
Related, I checked before posting, not duplicates: #2328 / #2354 (a variant path references its enum — works outside macros and in matches! without |), #1838 (C++, a macro invocation taken as a call — other language and other direction).
Activity