x/tools/go/analysis/vet: export cmd/vet and cmd/fix's \\[]\\*Analyzer suites
要約
概要
cmd/vet および cmd/fix が内部で使用しているアナライザ一覧([]*analysis.Analyzer)を、golang.org/x/tools/go/analysis/suite/vet および golang.org/x/tools/go/analysis/suite/fix という新規パッケージに公開するproposalです。これにより、ユーザーが独自の静的解析ツールを構築する際に、既存のvetおよびfixのアナライザセットを再利用しやすくなります。
ステータス変更
likely_accept → accepted
2026年5月21日の週次Proposalレビューミーティングにおいて、@aclements が前週の likely_accept から合意に変更がないと判断し、正式に accepted と決定しました。実装CLとして go.dev/cl/780780(x/toolsサイドの新パッケージ作成)と go.dev/cl/780900(cmd/vet・cmd/fix側での利用)がすでに提出されており、実装フェーズに移行しています。
技術的背景
現状の問題点
cmd/vet/main.go に定義されているアナライザリストはパッケージ内部のプライベートな定義であり、外部から参照できません。そのため、go vet と同じアナライザセットを含む独自のマルチチェッカーを作りたい開発者は、ソースコードを参照して手動でリストをコピーするしかありませんでした。
// cmd/vet/main.go の内部定義(現状・公開されていない)
var analyzers = []*analysis.Analyzer{
appends.Analyzer,
asmdecl.Analyzer,
assign.Analyzer,
atomic.Analyzer,
// ... 多数のアナライザ
}
このリストはGoのバージョンアップに伴い変化するため、コピーしたリストは陳腐化するリスクがあります。
提案された解決策
golang.org/x/tools/go/analysis/suite/vet および golang.org/x/tools/go/analysis/suite/fix という2つのパッケージを新規作成し、それぞれ var Suite = []*analysis.Analyzer{ ... } を公開します。
// golang.org/x/tools/go/analysis/suite/vet
package vet
import "golang.org/x/tools/go/analysis"
// Suite は cmd/vet が実行するアナライザのセットです。
var Suite = []*analysis.Analyzer{ ... }
// golang.org/x/tools/go/analysis/suite/fix
package fix
import "golang.org/x/tools/go/analysis"
// Suite は cmd/fix が実行するアナライザのセットです。
var Suite = []*analysis.Analyzer{ ... }
cmd/vet と cmd/fix 自身も、これらの新パッケージを参照して実装されます(CL 780900)。vet と fix を同一パッケージにまとめる案も検討されましたが、不要なimport依存が生じるため、別パッケージとする設計が採用されました。
これによって何ができるようになるか
go vet のアナライザセットをベースにした独自解析ツールを、コピー&ペーストなしに構築できます。
コード例
// Before: 従来のワークアラウンド(vet のアナライザを手動でコピー)
import "golang.org/x/tools/go/analysis/multichecker"
func main() {
multichecker.Main(
appends.Analyzer,
asmdecl.Analyzer,
assign.Analyzer,
// ... vet のリストを手動でコピー(陳腐化リスクあり)
myCustomAnalyzer,
)
}
// After: 新パッケージを使った書き方
import (
"golang.org/x/tools/go/analysis/multichecker"
vetSuite "golang.org/x/tools/go/analysis/suite/vet"
)
func main() {
analyzers := append(vetSuite.Suite, myCustomAnalyzer)
multichecker.Main(analyzers...)
}
議論のハイライト
- パッケージ名の変遷: 当初は
x/tools/go/analysis/vet、次にx/tools/go/analysis/passes/suite/{fix,vet}が提案されましたが、最終的にレビューミーティングでpassesセグメントを除いたx/tools/go/analysis/suite/{fix,vet}に決定されました。 - 可変グローバル変数の懸念: @prattmic が
var Suiteをfunc Suite()にすべきではないかと提案しました。init()内でSuiteを改変するアナライザが生じうる点が指摘されましたが、@adonovan は「自作のアナライザがリンクされるにはmainパッケージで明示的に指定される必要があり、リスクは低い」と判断し、変数のままとすることになりました。 - 重複アナライザの扱い: 関連issue #75227 において、パッケージ自身が重複アナライザを自動除去するか、ユーザーに委ねるかが議論されましたが、今回の設計ではシンプルなスライス公開にとどめています。
- vetとfixのアナライザ分離:
go vetとgo testが実行するアナライザのセットは異なる場合があるため(#47309 参照)、個別のパッケージとして管理することで柔軟な組み合わせが可能になります。 - 6年以上のラグ: このissueは2019年11月に提出されながら、2025年5月の @adonovan による具体的なAPI提案まで実質的な議論が進まず、2026年5月に承認に至りました。