mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
cmd/guru: add workaround to handle inconsistency between go/types and gc
Add identical workaround from gorename to guru. Only affects queries that typecheck the code first. Fixes golang/go#16530 Change-Id: I718cfceb8d26868eea9128c8873b164333c50f53 Reviewed-on: https://go-review.googlesource.com/33359 Reviewed-by: Alan Donovan <adonovan@google.com>
This commit is contained in:
parent
4c6345e8dc
commit
e64f1a4c63
@ -28,7 +28,7 @@ func callees(q *Query) error {
|
||||
}
|
||||
|
||||
// Load/parse/type-check the program.
|
||||
lprog, err := lconf.Load()
|
||||
lprog, err := loadWithSoftErrors(&lconf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ func callers(q *Query) error {
|
||||
}
|
||||
|
||||
// Load/parse/type-check the program.
|
||||
lprog, err := lconf.Load()
|
||||
lprog, err := loadWithSoftErrors(&lconf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ func callstack(q *Query) error {
|
||||
}
|
||||
|
||||
// Load/parse/type-check the program.
|
||||
lprog, err := lconf.Load()
|
||||
lprog, err := loadWithSoftErrors(&lconf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
"io"
|
||||
"log"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/go/ast/astutil"
|
||||
"golang.org/x/tools/go/buildutil"
|
||||
@ -255,6 +256,53 @@ func parseQueryPos(lprog *loader.Program, pos string, needExact bool) (*queryPos
|
||||
|
||||
// ---------- Utilities ----------
|
||||
|
||||
// loadWithSoftErrors calls lconf.Load, suppressing "soft" errors. (See Go issue 16530.)
|
||||
// TODO(adonovan): Once the loader has an option to allow soft errors,
|
||||
// replace calls to loadWithSoftErrors with loader calls with that parameter.
|
||||
func loadWithSoftErrors(lconf *loader.Config) (*loader.Program, error) {
|
||||
lconf.AllowErrors = true
|
||||
|
||||
// Ideally we would just return conf.Load() here, but go/types
|
||||
// reports certain "soft" errors that gc does not (Go issue 14596).
|
||||
// As a workaround, we set AllowErrors=true and then duplicate
|
||||
// the loader's error checking but allow soft errors.
|
||||
// It would be nice if the loader API permitted "AllowErrors: soft".
|
||||
prog, err := lconf.Load()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var errpkgs []string
|
||||
// Report hard errors in indirectly imported packages.
|
||||
for _, info := range prog.AllPackages {
|
||||
if containsHardErrors(info.Errors) {
|
||||
errpkgs = append(errpkgs, info.Pkg.Path())
|
||||
} else {
|
||||
// Enable SSA construction for packages containing only soft errors.
|
||||
info.TransitivelyErrorFree = true
|
||||
}
|
||||
}
|
||||
if errpkgs != nil {
|
||||
var more string
|
||||
if len(errpkgs) > 3 {
|
||||
more = fmt.Sprintf(" and %d more", len(errpkgs)-3)
|
||||
errpkgs = errpkgs[:3]
|
||||
}
|
||||
return nil, fmt.Errorf("couldn't load packages due to errors: %s%s",
|
||||
strings.Join(errpkgs, ", "), more)
|
||||
}
|
||||
return prog, err
|
||||
}
|
||||
|
||||
func containsHardErrors(errors []error) bool {
|
||||
for _, err := range errors {
|
||||
if err, ok := err.(types.Error); ok && err.Soft {
|
||||
continue
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// allowErrors causes type errors to be silently ignored.
|
||||
// (Not suitable if SSA construction follows.)
|
||||
func allowErrors(lconf *loader.Config) {
|
||||
|
@ -230,6 +230,7 @@ func TestGuru(t *testing.T) {
|
||||
"testdata/src/reflection/main.go",
|
||||
"testdata/src/what/main.go",
|
||||
"testdata/src/whicherrs/main.go",
|
||||
"testdata/src/softerrs/main.go",
|
||||
// JSON:
|
||||
// TODO(adonovan): most of these are very similar; combine them.
|
||||
"testdata/src/calls-json/main.go",
|
||||
|
@ -31,7 +31,7 @@ func peers(q *Query) error {
|
||||
}
|
||||
|
||||
// Load/parse/type-check the program.
|
||||
lprog, err := lconf.Load()
|
||||
lprog, err := loadWithSoftErrors(&lconf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ func pointsto(q *Query) error {
|
||||
}
|
||||
|
||||
// Load/parse/type-check the program.
|
||||
lprog, err := lconf.Load()
|
||||
lprog, err := loadWithSoftErrors(&lconf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
15
cmd/guru/testdata/src/softerrs/main.go
vendored
Normal file
15
cmd/guru/testdata/src/softerrs/main.go
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
package main
|
||||
|
||||
// Tests of various queries on a program containing only "soft" errors.
|
||||
// See go.tools/guru/guru_test.go for explanation.
|
||||
// See main.golden for expected query results.
|
||||
|
||||
func _() {
|
||||
var i int // "unused var" is a soft error
|
||||
}
|
||||
|
||||
func f() {} // @callers softerrs-callers-f "f"
|
||||
|
||||
func main() {
|
||||
f() // @describe softerrs-describe-f "f"
|
||||
}
|
8
cmd/guru/testdata/src/softerrs/main.golden
vendored
Normal file
8
cmd/guru/testdata/src/softerrs/main.golden
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
-------- @callers softerrs-callers-f --------
|
||||
softerrs.f is called from these 1 sites:
|
||||
static function call from softerrs.main
|
||||
|
||||
-------- @describe softerrs-describe-f --------
|
||||
reference to func f()
|
||||
defined here
|
||||
|
@ -37,7 +37,7 @@ func whicherrs(q *Query) error {
|
||||
}
|
||||
|
||||
// Load/parse/type-check the program.
|
||||
lprog, err := lconf.Load()
|
||||
lprog, err := loadWithSoftErrors(&lconf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user