fix(scanner): resolve go.mod per-file, closing issue #17#24
Conversation
findModule was called once for the whole scan, from the scan root — so every file's Go import path was computed relative to whichever go.mod happened to be nearest the scan root, even for files under an independent nested submodule (a monorepo containing its own go.mod deeper in the tree). A cross-package factory call from outside the submodule into it would never resolve, since the submodule's own files' computed import paths were wrong (relative to the wrong module entirely). Fixed by searching upward from each file's own directory instead of the scan root once — a file under a submodule now correctly finds that submodule's own (nearer) go.mod before ever reaching the outer one. Added a moduleCache (memoizing the search per-directory) since this is now called once per file rather than once per scan; files sharing the same nearest go.mod (the overwhelmingly common case, one module per repo) still resolve in a single map read after the first lookup in that directory subtree. runWholeScanAnalysis no longer needs absRoot at all now that go.mod resolution is per-file — removed the now-dead parameter (and the now-dead absRoot computation in the parseFixtures test helper) rather than leave an unused one for a future unparam lint failure to catch. Verified: new fixture (testdata/fixtures/monorepo/) with a genuinely nested go.mod (a real, separate "module github.com/example/monorepo- submodule" a few directories below flaglint-go's own go.mod) proves a cross-package factory call into the submodule now resolves correctly. Full test suite green, and re-verified against weaviate (a real 4500+-file, single-module repo) — same 4 real usages, no measurable performance regression (~2s, unchanged), confirming the per-directory cache keeps the common case just as fast as the old single-lookup version. Fixes #17 Signed-off-by: Krishan Kant Sharma <krishansharma0327@gmail.com>
|
Warning Review limit reached
Next review available in: 46 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (6)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary
Closes #17.
findModulewas called once for the whole scan, from the scan root — so every file's Go import path was computed relative to whichevergo.modhappened to be nearest the scan root, even for files under an independent nested submodule (a monorepo containing its owngo.moddeeper in the tree). A cross-package factory call from outside the submodule into it would never resolve, since the submodule's own files' computed import paths were wrong (relative to the wrong module entirely).Fix
Search upward from each file's own directory instead of the scan root once — a file under a submodule now correctly finds that submodule's own (nearer)
go.modbefore ever reaching the outer one. Added amoduleCache(memoizing the search per-directory) since this is now called once per file rather than once per scan; files sharing the same nearestgo.mod(the overwhelmingly common case, one module per repo) still resolve in a single map read after the first lookup in that directory subtree.Also removed
runWholeScanAnalysis's now-deadabsRootparameter (no longer needed now that go.mod resolution is per-file) rather than leave an unused one around.Verification
testdata/fixtures/monorepo/) with a genuinely nestedgo.mod(a real, separatemodule github.com/example/monorepo-submodulea few directories below flaglint-go's owngo.mod) proves a cross-package factory call into the submodule now resolves correctly.