From fc2b74b64ef08c618146ebc92062f6499db5314c Mon Sep 17 00:00:00 2001 From: Alan Donovan Date: Tue, 27 Sep 2016 09:58:56 -0400 Subject: [PATCH] refactor/rename: don't stop because of "soft" errors Because go/types is slightly more strict than gc about certain "soft" errors (ones that aren't necessary to interpret a Go program), gorename rejects programs that compile under gc. This change relaxes gorename's error checks so that they are weaker than gc's. This is a workaround for issue golang/go#14596 in gorename, whose underlying problem is issue golang/go#8560 in gc. Fixes golang/go#14596 Change-Id: Ica5006c2376c0564a575224269093c1497348ee6 Reviewed-on: https://go-review.googlesource.com/29853 Reviewed-by: Brad Fitzpatrick --- refactor/rename/rename.go | 36 +++++++++++++++++++++++++++++++++- refactor/rename/rename_test.go | 23 ++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/refactor/rename/rename.go b/refactor/rename/rename.go index 766bbc2966..40ca480fc0 100644 --- a/refactor/rename/rename.go +++ b/refactor/rename/rename.go @@ -384,7 +384,41 @@ func loadProgram(ctxt *build.Context, pkgs map[string]bool) (*loader.Program, er for pkg := range pkgs { conf.ImportWithTests(pkg) } - return conf.Load() + + // 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". + conf.AllowErrors = true + prog, err := conf.Load() + 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()) + } + } + 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 } // requiresGlobalRename reports whether this renaming could potentially diff --git a/refactor/rename/rename_test.go b/refactor/rename/rename_test.go index 0b3aad6510..04931a9829 100644 --- a/refactor/rename/rename_test.go +++ b/refactor/rename/rename_test.go @@ -1058,6 +1058,29 @@ type J interface { } var _ = I(C(0)).(J) +`, + }, + }, + // Progress after "soft" type errors (Go issue 14596). + { + ctxt: fakeContext(map[string][]string{ + "main": {`package main + +func main() { + var unused, x int + print(x) +} +`, + }, + }), + offset: "/go/src/main/0.go:#54", to: "y", // var x + want: map[string]string{ + "/go/src/main/0.go": `package main + +func main() { + var unused, y int + print(y) +} `, }, },