Skip to content

[go-fan] Go Module Review: golang.org/x/toolsΒ #42699

Description

@github-actions

🐹 Go Fan Report: golang.org/x/tools

Module Overview

golang.org/x/tools is the Go team's static-analysis toolkit. In gh-aw it's the backbone of the custom linter suite β€” the go/analysis framework, the passes/inspect result, the go/ast/inspector traversal engine, multichecker for the CLI, and analysistest for tests. This is one of the most deeply-integrated dependencies in the repo. πŸŽ‰

Current Usage in gh-aw

  • Files: ~38 analyzer packages under pkg/linters/* (+ shared internal/astutil), wired into cmd/linters/main.go via multichecker.Main(...).
  • Key APIs Used: analysis.Analyzer / Pass.ReportRangef, passes/inspect.Analyzer (every analyzer's Requires), go/ast/inspector (Preorder, Root().Preorder, Cursor.Enclosing), multichecker.Main, analysistest.
  • Version: v0.47.0 β€” the latest release (repo pushed 2026-06-30). No upgrade needed. βœ…

Research Findings

The go/ast/inspector docs now explicitly state: "We recommend using methods of Cursor in preference to Inspector where possible." The Cursor API (added v0.34.0, well below the pinned v0.47.0) is immutable positional navigation over the AST β€” Enclosing, Parent, Children, Contains, FindByPos, Preorder, Inspect β€” letting you start a traversal at any node, nest traversals, and navigate in all four directions.

Recent Updates

  • Cursor + Inspector.Root()/At() (v0.34.0), Valid()/ParentEdgeKind()/ParentEdgeIndex() (v0.42.0), generic All[N]/PreorderSeq iterators (v0.26.0). Active maintenance through v0.47.0.

Best Practices

  • Prefer Cursor methods over the callback-based Inspector.Preorder/Nodes/WithStack.
  • Use Cursor.Enclosing(types...) for ancestor/context checks instead of manual stack tracking.

Improvement Opportunities

πŸƒ Quick Wins

  • Add an astutil.Root(pass) (inspector.Cursor, error) helper next to the existing astutil.Inspector(pass) so Cursor-style linters share one error path and drop insp.Root() boilerplate.

✨ Feature Opportunities

  • The Cursor-based linters (e.g. timeafterleak) that re-walk subtrees for containment could use Cursor.Contains / Cursor.FindByPos.

πŸ“ Best Practice Alignment (primary finding)

The suite is split between two traversal styles:

  • Modern Cursor API (insp.Root().Preorder(...) + cur.Enclosing(...)): 9 linters β€” ctxbackground, deferinloop, execcommandwithoutcontext, hardcodedfilepath, httpnoctx, panic-in-library-code, regexpcompileinfunction, timeafterleak, timesleepnocontext (exactly the ones needing enclosing-context navigation).
  • Legacy callback API (insp.Preorder(filter, func(n ast.Node){...})): 29 linters β€” e.g. sortslice, errormessage, httpstatuscode, jsonmarshalignoredeerror, lenstringzero.
  • No linter uses the superseded WithStack (good).

Migrating the 29 legacy linters to for cur := range insp.Root().Preorder(nodeType) { ... } aligns the whole suite with the maintainers' recommendation, drops the []ast.Node filter boilerplate, and makes any future enclosing-context need a one-line cur.Enclosing(...) instead of a rewrite.

πŸ”§ General Improvements

  • A tiny shared traversal helper would keep all linters on one style and prevent drift between the two.

Recommendations (prioritized)

  1. Incrementally migrate legacy linters to the Cursor API. Mechanical, low-risk (both share the same inspector), guarded by existing analysistest coverage. Start with linters most likely to grow context checks.
  2. Add the astutil.Root(pass) helper to standardize Cursor acquisition.
  3. Keep tracking x/tools releases for further Cursor conveniences β€” already on latest v0.47.0.

Next Steps

  • Add astutil.Root(pass) helper.
  • Convert 2–3 legacy linters (e.g. sortslice, httpstatuscode) to Cursor as a pattern reference.
  • Track remaining conversions as follow-ups.

Generated by Go Fan
Module summary saved to: scratchpad/mods/golang-x-tools.md

Generated by 🐹 Go Fan Β· 118.9 AIC Β· βŒ– 12.7 AIC Β· ⊞ 7.4K Β· β—·

  • expires on Jul 2, 2026, 1:10 AM UTC-08:00

Metadata

Metadata

Labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions