Skip to content

Commit 4789ca9

Browse files
committed
go/analysis/internal/analysisflags: call gob.Register on deleted analyzers
Otherwise the specific set of gob registrations varies according to the command line, which makes it impossible for a narrow analysis run (for example, just one analyzer) to read fact files written by less narrow runs (for example, all the analyzers). This will start mattering in the standard repo vet. For golang/go#31916. Change-Id: I6fa90b3dfdf28ede6f995db3904211b6be68bb73 Reviewed-on: https://go-review.googlesource.com/c/tools/+/176357 Reviewed-by: Alan Donovan <[email protected]> Reviewed-by: Michael Matloob <[email protected]>
1 parent 7d589f2 commit 4789ca9

File tree

1 file changed

+37
-0
lines changed
  • go/analysis/internal/analysisflags

1 file changed

+37
-0
lines changed

go/analysis/internal/analysisflags/flags.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package analysisflags
88

99
import (
1010
"crypto/sha256"
11+
"encoding/gob"
1112
"encoding/json"
1213
"flag"
1314
"fmt"
@@ -32,6 +33,14 @@ var (
3233
// including (in multi mode) a flag named after the analyzer,
3334
// parses the flags, then filters and returns the list of
3435
// analyzers enabled by flags.
36+
//
37+
// The result is intended to be passed to unitchecker.Run or checker.Run.
38+
// Use in unitchecker.Run will gob.Register all fact types for the returned
39+
// graph of analyzers but of course not the ones only reachable from
40+
// dropped analyzers. To avoid inconsistency about which gob types are
41+
// registered from run to run, Parse itself gob.Registers all the facts
42+
// only reachable from dropped analyzers.
43+
// This is not a particularly elegant API, but this is an internal package.
3544
func Parse(analyzers []*analysis.Analyzer, multi bool) []*analysis.Analyzer {
3645
// Connect each analysis flag to the command line as -analysis.flag.
3746
enabled := make(map[*analysis.Analyzer]*triState)
@@ -88,6 +97,8 @@ func Parse(analyzers []*analysis.Analyzer, multi bool) []*analysis.Analyzer {
8897
os.Exit(0)
8998
}
9099

100+
everything := expand(analyzers)
101+
91102
// If any -NAME flag is true, run only those analyzers. Otherwise,
92103
// if any -NAME flag is false, run all but those analyzers.
93104
if multi {
@@ -119,9 +130,35 @@ func Parse(analyzers []*analysis.Analyzer, multi bool) []*analysis.Analyzer {
119130
}
120131
}
121132

133+
// Register fact types of skipped analyzers
134+
// in case we encounter them in imported files.
135+
kept := expand(analyzers)
136+
for a := range everything {
137+
if !kept[a] {
138+
for _, f := range a.FactTypes {
139+
gob.Register(f)
140+
}
141+
}
142+
}
143+
122144
return analyzers
123145
}
124146

147+
func expand(analyzers []*analysis.Analyzer) map[*analysis.Analyzer]bool {
148+
seen := make(map[*analysis.Analyzer]bool)
149+
var visitAll func([]*analysis.Analyzer)
150+
visitAll = func(analyzers []*analysis.Analyzer) {
151+
for _, a := range analyzers {
152+
if !seen[a] {
153+
seen[a] = true
154+
visitAll(a.Requires)
155+
}
156+
}
157+
}
158+
visitAll(analyzers)
159+
return seen
160+
}
161+
125162
func printFlags() {
126163
type jsonFlag struct {
127164
Name string

0 commit comments

Comments
 (0)