Skip to content

Commit 35ef268

Browse files
committed
go/analysis: change AllObjectFacts and AllPackageFacts to filter facts
Facts are intended to be private to an analysis. Even though it's hard to guarantee with the information we have that facts won't leak to the wrong analysis, we can filter some analyses that couldn't possibly have come from the same analysis. AllObjectFacts and AllPackageFacts will now filter facts if their type isn't specified in an analysis's FactTypes. Change-Id: I2794437a5810e08fe6a9652b3569c5e3c17e159f Reviewed-on: https://go-review.googlesource.com/c/tools/+/189037 Run-TryBot: Michael Matloob <[email protected]> Reviewed-by: Dominik Honnef <[email protected]>
1 parent c5a2fd3 commit 35ef268

File tree

4 files changed

+66
-8
lines changed

4 files changed

+66
-8
lines changed

go/analysis/analysis.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,13 @@ type Pass struct {
128128
// See comments for ExportObjectFact.
129129
ExportPackageFact func(fact Fact)
130130

131-
// AllPackageFacts returns a new slice containing all package facts in unspecified order.
131+
// AllPackageFacts returns a new slice containing all package facts of the analysis's FactTypes
132+
// in unspecified order.
132133
// WARNING: This is an experimental API and may change in the future.
133134
AllPackageFacts func() []PackageFact
134135

135-
// AllObjectFacts returns a new slice containing all object facts in unspecified order.
136+
// AllObjectFacts returns a new slice containing all object facts of the analysis's FactTypes
137+
// in unspecified order.
136138
// WARNING: This is an experimental API and may change in the future.
137139
AllObjectFacts func() []ObjectFact
138140

go/analysis/internal/facts/facts.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,10 @@ func (s *Set) ExportObjectFact(obj types.Object, fact analysis.Fact) {
9999
s.mu.Unlock()
100100
}
101101

102-
func (s *Set) AllObjectFacts() []analysis.ObjectFact {
102+
func (s *Set) AllObjectFacts(filter map[reflect.Type]bool) []analysis.ObjectFact {
103103
var facts []analysis.ObjectFact
104104
for k, v := range s.m {
105-
if k.obj != nil {
105+
if k.obj != nil && filter[k.t] {
106106
facts = append(facts, analysis.ObjectFact{k.obj, v})
107107
}
108108
}
@@ -132,10 +132,10 @@ func (s *Set) ExportPackageFact(fact analysis.Fact) {
132132
s.mu.Unlock()
133133
}
134134

135-
func (s *Set) AllPackageFacts() []analysis.PackageFact {
135+
func (s *Set) AllPackageFacts(filter map[reflect.Type]bool) []analysis.PackageFact {
136136
var facts []analysis.PackageFact
137137
for k, v := range s.m {
138-
if k.obj == nil {
138+
if k.obj == nil && filter[k.t] {
139139
facts = append(facts, analysis.PackageFact{k.pkg, v})
140140
}
141141
}

go/analysis/internal/facts/facts_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"go/token"
1111
"go/types"
1212
"os"
13+
"reflect"
1314
"testing"
1415

1516
"golang.org/x/tools/go/analysis/analysistest"
@@ -172,3 +173,52 @@ func load(dir string, path string) (*types.Package, error) {
172173
}
173174
return pkgs[0].Types, nil
174175
}
176+
177+
type otherFact struct {
178+
S string
179+
}
180+
181+
func (f *otherFact) String() string { return fmt.Sprintf("otherFact(%s)", f.S) }
182+
func (f *otherFact) AFact() {}
183+
184+
func TestFactFilter(t *testing.T) {
185+
files := map[string]string{
186+
"a/a.go": `package a; type A int`,
187+
}
188+
dir, cleanup, err := analysistest.WriteFiles(files)
189+
if err != nil {
190+
t.Fatal(err)
191+
}
192+
defer cleanup()
193+
194+
pkg, err := load(dir, "a")
195+
if err != nil {
196+
t.Fatal(err)
197+
}
198+
199+
obj := pkg.Scope().Lookup("A")
200+
s, err := facts.Decode(pkg, func(string) ([]byte, error) { return nil, nil })
201+
if err != nil {
202+
t.Fatal(err)
203+
}
204+
s.ExportObjectFact(obj, &myFact{"good object fact"})
205+
s.ExportPackageFact(&myFact{"good package fact"})
206+
s.ExportObjectFact(obj, &otherFact{"bad object fact"})
207+
s.ExportPackageFact(&otherFact{"bad package fact"})
208+
209+
filter := map[reflect.Type]bool{
210+
reflect.TypeOf(&myFact{}): true,
211+
}
212+
213+
pkgFacts := s.AllPackageFacts(filter)
214+
wantPkgFacts := `[{package a ("a") myFact(good package fact)}]`
215+
if got := fmt.Sprintf("%v", pkgFacts); got != wantPkgFacts {
216+
t.Errorf("AllPackageFacts: got %v, want %v", got, wantPkgFacts)
217+
}
218+
219+
objFacts := s.AllObjectFacts(filter)
220+
wantObjFacts := "[{type a.A int myFact(good object fact)}]"
221+
if got := fmt.Sprintf("%v", objFacts); got != wantObjFacts {
222+
t.Errorf("AllObjectFacts: got %v, want %v", got, wantObjFacts)
223+
}
224+
}

go/analysis/unitchecker/unitchecker.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import (
4242
"log"
4343
"os"
4444
"path/filepath"
45+
"reflect"
4546
"sort"
4647
"strings"
4748
"sync"
@@ -322,6 +323,11 @@ func run(fset *token.FileSet, cfg *Config, analyzers []*analysis.Analyzer) ([]re
322323
return
323324
}
324325

326+
factFilter := make(map[reflect.Type]bool)
327+
for _, f := range a.FactTypes {
328+
factFilter[reflect.TypeOf(f)] = true
329+
}
330+
325331
pass := &analysis.Pass{
326332
Analyzer: a,
327333
Fset: fset,
@@ -334,10 +340,10 @@ func run(fset *token.FileSet, cfg *Config, analyzers []*analysis.Analyzer) ([]re
334340
Report: func(d analysis.Diagnostic) { act.diagnostics = append(act.diagnostics, d) },
335341
ImportObjectFact: facts.ImportObjectFact,
336342
ExportObjectFact: facts.ExportObjectFact,
337-
AllObjectFacts: facts.AllObjectFacts,
343+
AllObjectFacts: func() []analysis.ObjectFact { return facts.AllObjectFacts(factFilter) },
338344
ImportPackageFact: facts.ImportPackageFact,
339345
ExportPackageFact: facts.ExportPackageFact,
340-
AllPackageFacts: facts.AllPackageFacts,
346+
AllPackageFacts: func() []analysis.PackageFact { return facts.AllPackageFacts(factFilter) },
341347
}
342348

343349
t0 := time.Now()

0 commit comments

Comments
 (0)