go/analysis/analysistest: fix nil pointer dereference when sorting facts

Without this change, we can't use `ExportPackageFact` function with analysistest package.

PackageFacts are keyed by nil and analysistest.check crashed while sorting, due to a nil object dereference.

Change-Id: Ic94c71acc9c74012bf150e1d72e937da8dfdff75
GitHub-Last-Rev: 51c91008a6756e66c630bfeabc9b8da08c12bfdd
GitHub-Pull-Request: golang/tools#163
Reviewed-on: https://go-review.googlesource.com/c/tools/+/196758
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
Reviewed-by: Alan Donovan <adonovan@google.com>
This commit is contained in:
Matts966 2019-10-04 16:59:51 +00:00 committed by Rebecca Stambler
parent 27eeabb020
commit d89860af3b
5 changed files with 21 additions and 5 deletions

View File

@ -277,6 +277,11 @@ func check(t Testing, gopath string, pass *analysis.Pass, diagnostics []analysis
objects = append(objects, obj) objects = append(objects, obj)
} }
sort.Slice(objects, func(i, j int) bool { sort.Slice(objects, func(i, j int) bool {
// Package facts compare less than object facts.
ip, jp := objects[i] == nil, objects[j] == nil // whether i, j is a package fact
if ip != jp {
return ip && !jp
}
return objects[i].Pos() < objects[j].Pos() return objects[i].Pos() < objects[j].Pos()
}) })
for _, obj := range objects { for _, obj := range objects {

View File

@ -33,7 +33,7 @@ func TestTheTest(t *testing.T) {
// which (by default) reports calls to functions named 'println'. // which (by default) reports calls to functions named 'println'.
findcall.Analyzer.Flags.Set("name", "println") findcall.Analyzer.Flags.Set("name", "println")
filemap := map[string]string{"a/b.go": `package main filemap := map[string]string{"a/b.go": `package main // want package:"found"
func main() { func main() {
// The expectation is ill-formed: // The expectation is ill-formed:

View File

@ -5,7 +5,10 @@
// The findcall package defines an Analyzer that serves as a trivial // The findcall package defines an Analyzer that serves as a trivial
// example and test of the Analysis API. It reports a diagnostic for // example and test of the Analysis API. It reports a diagnostic for
// every call to a function or method of the name specified by its // every call to a function or method of the name specified by its
// -name flag. // -name flag. It also exports a fact for each declaration that
// matches the name, plus a package-level fact if the package contained
// one or more such declarations.
package findcall package findcall
import ( import (
@ -69,6 +72,10 @@ func run(pass *analysis.Pass) (interface{}, error) {
} }
} }
if len(pass.AllObjectFacts()) > 0 {
pass.ExportPackageFact(new(foundFact))
}
return nil, nil return nil, nil
} }

View File

@ -29,12 +29,14 @@ func TestFromStringLiterals(t *testing.T) {
{ {
desc: "SimpleTest", desc: "SimpleTest",
pkgpath: "main", pkgpath: "main",
files: map[string]string{"main/main.go": `package main files: map[string]string{"main/main.go": `package main // want package:"found"
func main() { func main() {
println("hello") // want "call of println" println("hello") // want "call of println"
print("goodbye") // not a call of println print("goodbye") // not a call of println
}`, }
func println(s string) {} // want println:"found"`,
}, },
}, },
} { } {

View File

@ -1,6 +1,8 @@
package main package main // want package:"found"
func main() { func main() {
println("hi") // want "call of println" println("hi") // want "call of println"
print("hi") // not a call of println print("hi") // not a call of println
} }
func println(s string) {} // want println:"found"