メインコンテンツへスキップ

Go Proposal Weekly Digest

Go言語のproposal更新を毎週お届け

#35487active

x/tools/go/analysis/vet: export cmd/vet and cmd/fix's \\[]\\*Analyzer suites

新規提案

要約

AIによる要約であり、誤りを含む場合があります。

概要

cmd/vet(静的解析ツール)と cmd/fix(コード自動修正ツール)が使用するアナライザ(解析パス)の一覧を、x/tools/go/analysis/vet および x/tools/go/analysis/fix パッケージとしてエクスポートし、外部ツールが再利用できるようにするproposalです。

ステータス変更

(新規)active
2026年5月6日の週次proposal review meetingにおいて、@aclements がこのissueをactiveキューに追加しました。会議のメモには「added to minutes」と記録されており、現在レビューグループによる本格的な審議が開始されています。2019年に提起されたこの提案が、2025年5月に@adonovanが具体的なAPI設計を提示したことで前進し、activeステータスに進んだ形です。

技術的背景

現状の問題点

cmd/vetx/tools/go/analysis/passes 以下の多数のアナライザを束ねて動作しますが、そのアナライザ一覧は cmd/vet/main.go 内の非公開変数 suite に格納されています。同様に、cmd/fix/main.go も非公開の suite 変数でアナライザを管理しています。
サードパーティツール開発者が go vet と同じアナライザセットを使用するカスタムチェッカーを作りたい場合、現在は cmd/vet/main.go のアナライザリストを手動でコピーする必要があります。このコピーは go vet の更新に追従できないため、バージョンずれが発生しやすいという問題があります。

// 現状の問題:cmd/vet/main.go内の非公開変数(参照・再利用不可)
var suite = []*analysis.Analyzer{
    appends.Analyzer,
    asmdecl.Analyzer,
    assign.Analyzer,
    // ... 30以上のアナライザ
}

提案された解決策

2つの独立したパッケージを新設し、それぞれに Suite という公開変数を定義します。パッケージを分けることで、不要なインポート依存が発生しないよう設計されています。
golang.org/x/tools/go/analysis/vet パッケージ:

package vet
import "golang.org/x/tools/go/analysis"
// Suite は cmd/vet が実行するアナライザの一覧です。
// unitchecker を使ったカスタムコマンドの基盤として利用できます。
var Suite = []*analysis.Analyzer{ ... }

golang.org/x/tools/go/analysis/fix パッケージ:

package fix
import "golang.org/x/tools/go/analysis"
// Suite は cmd/fix が実行するアナライザの一覧です。
var Suite = []*analysis.Analyzer{ ... }

これによって何ができるようになるか

独自のアナライザを go vet の既存チェックに追加した統合ツールを、アナライザリストをコピーすることなく簡単に作成できるようになります。

コード例

// Before: 従来のワークアラウンド(cmd/vetのアナライザを手動コピー)
package main
import (
    "golang.org/x/tools/go/analysis/passes/appends"
    "golang.org/x/tools/go/analysis/passes/printf"
    // ... 30以上のアナライザを手動でimport・列挙
    "golang.org/x/tools/go/analysis/multichecker"
)
func main() {
    multichecker.Main(
        appends.Analyzer,
        printf.Analyzer,
        // ... 手動でコピーした全アナライザ
        myCustomAnalyzer,
    )
}
// After: 新APIを使ったシンプルな書き方
package main
import (
    "golang.org/x/tools/go/analysis/vet"
    "golang.org/x/tools/go/analysis/multichecker"
)
func main() {
    analyzers := append(vet.Suite, myCustomAnalyzer)
    multichecker.Main(analyzers...)
}

実践的なユースケース:

  • 社内リンタツールに go vet の全チェックを取り込んで拡張する
  • CI/CDパイプライン向けのカスタム静的解析ツールを go vet ベースで構築する
  • cmd/fix の自動修正スイートを継承しつつ追加の修正アナライザを組み合わせる

議論のハイライト

  • パッケージの配置場所: golang.org/x/tools/go/analysis/passes に変数を置く案や単一パッケージ案(suite.Vetsuite.Fix)も検討されたが、依存関係の増大を防ぐため別パッケージ方式が採用された
  • 重複アナライザの扱い: カスタムスイートに同一アナライザを追加した場合の重複検出について議論された。analysisflags.Validate が重複を弾くため、ユーザー側で重複チェックをする責任とする方向で検討中
  • バージョン不整合の懸念: x/tools に含まれる vet.Suitex/tools のバージョンに依存するため、特定のGoツールチェーンバージョンに同梱された cmd/vet と厳密に一致しない可能性があることが @prattmic から指摘された
  • go test との分離: go test が内部的に実行するアナライザセット(vetのサブセット)との分離が当初論点になったが、go vet スイートとして一本化する方針が支持された
  • cmd/fix との統合: go fixgo vet の補完ツールとして整備する計画(#71859)と並行してfix側のスイートも公開する方針が@adonovanから提案され、スコープが拡大された

関連リンク