feat(scanner): Track Cargo build-script inputs - #127
Conversation
Resolve literal Cargo rerun-if-changed directives through the existing Rust syntax scanner, authoritative custom-build ownership, and exact configured-file matching. Co-Authored-By: GPT-5.6 Sol <codex@openai.com>
|
Reviewed against real ground truth — built a Cargo workspace and used Two things I'd fix before landing. 1.
|
| main | this PR | |
|---|---|---|
| ast-grep matches | — | 30,000 |
| JSON payload | — | 39 MB |
codemap --deps wall |
0.31s | 0.63s |
All of it unmarshalled into []ScanMatch before filtering. The real hazard isn't the 2x — it's astGrepScanTimeout = 30s (scanner/astgrep.go:23). A println-heavy Rust monorepo pushed past that degrades the entire scan to ScanSourceTimeout, losing coverage for every language, not just this feature.
One-line fix, verified — 30,000 matches → 0 on the perf fixture, while the real fixture still yields all 4 genuine matches:
constraints:
PATH:
regex: 'cargo::?rerun-if-changed='(A files: ["**/build.rs"] glob also works but would wrongly exclude crates using build = "custom_build.rs", so the constraint is the better lever.)
2. Directive paths leak into the imports array
scanner/astgrep.go:358-360 only excludes rust-path-imports, so extracted directive strings get appended to FileAnalysis.Imports:
{"path":"app/src/lib.rs","imports":["generated","schema.proto"]}lib.rs imports nothing named schema.proto — it just contains a println! with that string in an ordinary function. Earlier fixture state also published ["../outside.proto","build.rs","missing.proto","protos"] for build.rs: unresolvable paths plus a self-reference, in the versioned codemap.analysis/v1 payload. Resolved graph edges are unaffected — only the raw array lies.
Worth noting #126 explicitly excludes its own kind (&& m.RuleID != "rust-askama-template-imports"), so #127 is the outlier here. Whoever merges second should make the two consistent rather than preserving both behaviors.
Finding 3 turned out to be a bug in main — filed as #130
Extension-less declared inputs can never resolve. cargo proves app/VERSION is an input; codemap says No files import app/VERSION. Root cause is in buildFileIndexContext: when a path has no extension, filepath.Ext returns "", so noExt == path and the same path is appended twice under the same key — meaning len(byExact[p]) == 2 forever, and the len(...) != 1 idiom rejects it permanently. Hits VERSION, Makefile, Dockerfile, LICENSE.
That's not yours to fix here — it's pre-existing, and the same three lines are also what lets #125 fabricate an edge to a nonexistent file. Filed as #130 with both halves; fixing it there makes this finding disappear without touching your PR.
Merge note
No signature changes, and rust-cargo-rerun-imports doesn't collide with #125's or #126's rule ids. I merged all four Rust PRs locally with union resolution and got a clean build and green go test ./... — no repeat of the #117/#118 break. The one hazard for whoever resolves: scanner/astgrep.go:327 must union all three rule IDs. Taking either side of that one-line conflict silently disables a feature with fully green CI.
Nits: ExplicitTarget is set at astgrep.go:354 but resolveRustBuildScriptInput reads ref.Path, so it's dead for this kind; the test file constructs two scanners and never closes the one that actually scans; and rustbuildscript_test.go:97 hard-codes forward-slash expectations that would fail on Windows (latent — CI runs tests on ubuntu+macos only).
What does this PR do?
Record file dependencies declared by literal
println!("cargo:rerun-if-changed=...")andprintln!("cargo::rerun-if-changed=...")build-script directives. Extraction reuses the existing Rust syntax and string-literal scanner; resolution requires Cargo metadata to identify the package's exact custom-build target and accepts only one exact configured, indexed file under that package.Comments, documentation strings, formatting arguments, malformed or control-containing values, globs, directories, missing files, absolute paths, escaping paths, ambiguous targets, self references, and directives outside the package build script remain unresolved.
Type of change
Checklist
go build && ./codemap .CONTRIBUTING.md; this does not add a new language.Additional notes
Focused extraction and conservative-resolution tests, the scanner suite, scanner staticcheck, and diff hygiene are GREEN.
An installed integration smoke test resolves
app/build.rsas the importer ofapp/src/generated.rs. The integration suite is GREEN under the repository's Go 1.25 minimum and with full macOS race/coverage.This branch targets and contains no generic macro, Cargo-topology, configuration, or non-Rust changes.
Developed with carefully directed, manually reviewed AI assistance.