mirror of
https://github.com/golang/go.git
synced 2025-05-05 23:53:05 +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.
|
// Load/parse/type-check the program.
|
||||||
lprog, err := lconf.Load()
|
lprog, err := loadWithSoftErrors(&lconf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ func callers(q *Query) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Load/parse/type-check the program.
|
// Load/parse/type-check the program.
|
||||||
lprog, err := lconf.Load()
|
lprog, err := loadWithSoftErrors(&lconf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ func callstack(q *Query) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Load/parse/type-check the program.
|
// Load/parse/type-check the program.
|
||||||
lprog, err := lconf.Load()
|
lprog, err := loadWithSoftErrors(&lconf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"golang.org/x/tools/go/ast/astutil"
|
"golang.org/x/tools/go/ast/astutil"
|
||||||
"golang.org/x/tools/go/buildutil"
|
"golang.org/x/tools/go/buildutil"
|
||||||
@ -255,6 +256,53 @@ func parseQueryPos(lprog *loader.Program, pos string, needExact bool) (*queryPos
|
|||||||
|
|
||||||
// ---------- Utilities ----------
|
// ---------- 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.
|
// allowErrors causes type errors to be silently ignored.
|
||||||
// (Not suitable if SSA construction follows.)
|
// (Not suitable if SSA construction follows.)
|
||||||
func allowErrors(lconf *loader.Config) {
|
func allowErrors(lconf *loader.Config) {
|
||||||
|
@ -230,6 +230,7 @@ func TestGuru(t *testing.T) {
|
|||||||
"testdata/src/reflection/main.go",
|
"testdata/src/reflection/main.go",
|
||||||
"testdata/src/what/main.go",
|
"testdata/src/what/main.go",
|
||||||
"testdata/src/whicherrs/main.go",
|
"testdata/src/whicherrs/main.go",
|
||||||
|
"testdata/src/softerrs/main.go",
|
||||||
// JSON:
|
// JSON:
|
||||||
// TODO(adonovan): most of these are very similar; combine them.
|
// TODO(adonovan): most of these are very similar; combine them.
|
||||||
"testdata/src/calls-json/main.go",
|
"testdata/src/calls-json/main.go",
|
||||||
|
@ -31,7 +31,7 @@ func peers(q *Query) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Load/parse/type-check the program.
|
// Load/parse/type-check the program.
|
||||||
lprog, err := lconf.Load()
|
lprog, err := loadWithSoftErrors(&lconf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ func pointsto(q *Query) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Load/parse/type-check the program.
|
// Load/parse/type-check the program.
|
||||||
lprog, err := lconf.Load()
|
lprog, err := loadWithSoftErrors(&lconf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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.
|
// Load/parse/type-check the program.
|
||||||
lprog, err := lconf.Load()
|
lprog, err := loadWithSoftErrors(&lconf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user