Go Fan Report: golang.org/x/tools
Module Overview
golang.org/x/tools is the Go team extended tools module — the go/analysis static-analysis framework, go/ast/inspector, go/packages, the gopls language server, and assorted dev-tool packages (cover, txtar, etc). It is selected today because it is the most recently pushed direct dependency in go.mod (2026-08-18), and gh-aw builds an entire in-house static-analysis suite on top of it.
Current Usage in gh-aw
- Files: 76 non-test
.go files import it; 77 more _test.go files import it (mostly analysistest)
- Version:
v0.49.0 — this is also the latest tag of the module. Already fully up to date, no action needed there.
- Key APIs used:
analysis.Analyzer/analysis.Pass, pass.ReportRangef, analysis.TextEdit/SuggestedFix, inspector.Inspector, the modern inspector.Cursor iterator API, multichecker.Main, go/packages.Load, cover.ParseProfiles.
- Import breakdown:
go/analysis — 81 files
go/analysis/analysistest — 67 files (unit tests for every custom linter)
go/ast/inspector — 13 files
gopls — 5 references (installed as an external binary via go install, not linked as a library — see pkg/workflow/lsp_manager.go)
go/analysis/passes/inspect — 3 files
go/packages — 2 files (.github/scripts/purelock/purity_scan.go)
go/analysis/multichecker — 1 file (cmd/linters/main.go)
cover — 1 file (pkg/linters/internal/coverage/coverage.go)
The centerpiece is pkg/linters/* — roughly 65 hand-written go/analysis analyzers (e.g. largefunc, deferinloop, httprespbodyclose, sortslice...) covering everything from resource-leak patterns to idiomatic stdlib usage, all wired together by a shared pkg/linters/internal/analyzerutil helper and driven by cmd/linters via multichecker.Main.
Research Findings
- Repository: https://github.com/golang/tools — latest tag
v0.49.0, pushed 2026-08-18, matching go.mod exactly.
gopls (versioned separately) is at v0.23.0 (released 2026-07-09).
Recent Updates
Steady maintenance releases on both the module and gopls; nothing breaking for the APIs gh-aw depends on. No migration work required.
Best Practices (from module docs)
- Prefer the newer
inspector.Cursor iterator API (Root().Preorder(...), cur.Enclosing(...), cur.Parent()) over the legacy callback-style Inspector.Preorder(filter, func(ast.Node)).
- Declare shared pass dependencies via
Analyzer.Requires instead of recomputing state per analyzer.
- Test every analyzer with
analysistest.Run against testdata/src/<pkg> fixtures.
gh-aw already follows all three of these: pkg/linters/internal/analyzerutil.go builds every analyzer via a shared New/NewAtPath constructor that declares Requires: []*analysis.Analyzer{inspect.Analyzer, nolint.Analyzer, filecheck.Analyzer}, its Preorder helper uses inspector.Cursor, and all ~65 analyzers have analysistest-based tests. 👍
Improvement Opportunities
🏃 Quick Wins
- 46 of the ~65 analyzers already emit
analysis.SuggestedFix edits (import add/remove, strings.Contains rewrites, byte/string round-trip fixes, etc.), but neither the golint-custom target in Makefile nor pkg/linters/README.md mentions the -fix flag that multichecker.Main supports out of the box. Documenting make golint-custom LINTER_FLAGS=-fix (or adding a golint-custom-fix target) would let contributors auto-apply nearly half of the linter fixes with zero new code.
✨ Feature Opportunities
cmd/linters/main.go drives everything through multichecker.Main, which reloads and fully re-type-checks the target package set (./cmd/... ./pkg/...) on every run. golang.org/x/tools/go/analysis/unitchecker exposes the same analysis.Analyzer set through the standard go vet -vettool= protocol. Swapping (or adding) a unitchecker-based entry point would let go vet -vettool=/tmp/gh-aw-linters ./... — or even plain go build/go test, which invoke vet automatically — piggyback on the Go build cache and only re-analyze changed packages. That gives the custom linters the same kind of incremental speedup golint-incremental already provides for golangci-lint, without any hand-rolled changed-file diffing.
📐 Best Practice Alignment
- No gaps found — the shared
analyzerutil/astutil helpers already track the modern Cursor-based traversal API and the Requires-based dependency pattern recommended by the x/tools maintainers. Worth calling out in review guidance for new analyzers so they keep using Cursor rather than reintroducing ast.Inspect callbacks.
🔧 General Improvements
- None beyond the two items above — usage is thorough and idiomatic.
Recommendations
- Add
-fix documentation/target for golint-custom (quick win, no code changes to analyzers).
- Evaluate a
unitchecker-based driver alongside (or instead of) multichecker to unlock incremental, cache-aware analysis via go vet -vettool=.
Next Steps
- File a follow-up task to prototype a
cmd/linters-vettool (or flag-selected mode in cmd/linters) using unitchecker.Main and measure the wall-clock difference on a warm build cache vs. the current full-repo multichecker run.
Generated by Go Fan 🐹
Module summary saved to: scratchpad/mods/golang.org-x-tools.md
Generated by 🐹 Go Fan · agent · 193.2 AIC · ⌖ 5.01 AIC · ⊞ 7.8K · ◷
Go Fan Report: golang.org/x/tools
Module Overview
golang.org/x/toolsis the Go team extended tools module — thego/analysisstatic-analysis framework,go/ast/inspector,go/packages, thegoplslanguage server, and assorted dev-tool packages (cover,txtar, etc). It is selected today because it is the most recently pushed direct dependency ingo.mod(2026-08-18), and gh-aw builds an entire in-house static-analysis suite on top of it.Current Usage in gh-aw
.gofiles import it; 77 more_test.gofiles import it (mostlyanalysistest)v0.49.0— this is also the latest tag of the module. Already fully up to date, no action needed there.analysis.Analyzer/analysis.Pass,pass.ReportRangef,analysis.TextEdit/SuggestedFix,inspector.Inspector, the moderninspector.Cursoriterator API,multichecker.Main,go/packages.Load,cover.ParseProfiles.go/analysis— 81 filesgo/analysis/analysistest— 67 files (unit tests for every custom linter)go/ast/inspector— 13 filesgopls— 5 references (installed as an external binary viago install, not linked as a library — seepkg/workflow/lsp_manager.go)go/analysis/passes/inspect— 3 filesgo/packages— 2 files (.github/scripts/purelock/purity_scan.go)go/analysis/multichecker— 1 file (cmd/linters/main.go)cover— 1 file (pkg/linters/internal/coverage/coverage.go)The centerpiece is
pkg/linters/*— roughly 65 hand-writtengo/analysisanalyzers (e.g.largefunc,deferinloop,httprespbodyclose,sortslice...) covering everything from resource-leak patterns to idiomatic stdlib usage, all wired together by a sharedpkg/linters/internal/analyzerutilhelper and driven bycmd/lintersviamultichecker.Main.Research Findings
v0.49.0, pushed 2026-08-18, matching go.mod exactly.gopls(versioned separately) is atv0.23.0(released 2026-07-09).Recent Updates
Steady maintenance releases on both the module and gopls; nothing breaking for the APIs gh-aw depends on. No migration work required.
Best Practices (from module docs)
inspector.Cursoriterator API (Root().Preorder(...),cur.Enclosing(...),cur.Parent()) over the legacy callback-styleInspector.Preorder(filter, func(ast.Node)).Analyzer.Requiresinstead of recomputing state per analyzer.analysistest.Runagainsttestdata/src/<pkg>fixtures.gh-aw already follows all three of these:
pkg/linters/internal/analyzerutil.gobuilds every analyzer via a sharedNew/NewAtPathconstructor that declaresRequires: []*analysis.Analyzer{inspect.Analyzer, nolint.Analyzer, filecheck.Analyzer}, itsPreorderhelper usesinspector.Cursor, and all ~65 analyzers haveanalysistest-based tests. 👍Improvement Opportunities
🏃 Quick Wins
analysis.SuggestedFixedits (import add/remove,strings.Containsrewrites, byte/string round-trip fixes, etc.), but neither thegolint-customtarget inMakefilenorpkg/linters/README.mdmentions the-fixflag thatmultichecker.Mainsupports out of the box. Documentingmake golint-custom LINTER_FLAGS=-fix(or adding agolint-custom-fixtarget) would let contributors auto-apply nearly half of the linter fixes with zero new code.✨ Feature Opportunities
cmd/linters/main.godrives everything throughmultichecker.Main, which reloads and fully re-type-checks the target package set (./cmd/... ./pkg/...) on every run.golang.org/x/tools/go/analysis/unitcheckerexposes the sameanalysis.Analyzerset through the standardgo vet -vettool=protocol. Swapping (or adding) aunitchecker-based entry point would letgo vet -vettool=/tmp/gh-aw-linters ./...— or even plaingo build/go test, which invoke vet automatically — piggyback on the Go build cache and only re-analyze changed packages. That gives the custom linters the same kind of incremental speedupgolint-incrementalalready provides for golangci-lint, without any hand-rolled changed-file diffing.📐 Best Practice Alignment
analyzerutil/astutilhelpers already track the modernCursor-based traversal API and theRequires-based dependency pattern recommended by the x/tools maintainers. Worth calling out in review guidance for new analyzers so they keep usingCursorrather than reintroducingast.Inspectcallbacks.🔧 General Improvements
Recommendations
-fixdocumentation/target forgolint-custom(quick win, no code changes to analyzers).unitchecker-based driver alongside (or instead of)multicheckerto unlock incremental, cache-aware analysis viago vet -vettool=.Next Steps
cmd/linters-vettool(or flag-selected mode incmd/linters) usingunitchecker.Mainand measure the wall-clock difference on a warm build cache vs. the current full-repomulticheckerrun.Generated by Go Fan 🐹
Module summary saved to:
scratchpad/mods/golang.org-x-tools.md