x/exp/apidiff: copy changes from x/tools/internal/apidiff
We copied golang.org/x/exp/apidiff to x/tools a few months ago in anticipation of developing gorelease in x/tools, which would depend on apidiff. We've decided to develop gorelease here in x/exp instead, which means the copy in x/tools is no longer needed. This CL copies changes made to the copy in x/tools since it was made. Another CL will delete the copy in x/tools. Change-Id: Ied79138616c2f3b2f49a0ee5ca95ff3179351354 Reviewed-on: https://go-review.googlesource.com/c/exp/+/197298 Run-TryBot: Jay Conrod <jayconrod@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Jonathan Amsterdam <jba@google.com>
This commit is contained in:
Родитель
81c71964d7
Коммит
26a69ce95b
|
@ -265,7 +265,7 @@ var x = C // old type is int64, new is int
|
|||
var y int64 = x // fails with new: different types in assignment
|
||||
```
|
||||
|
||||
A change to the value of a constant can break compatiblity if the value is used
|
||||
A change to the value of a constant can break compatibility if the value is used
|
||||
in an array type:
|
||||
|
||||
```
|
||||
|
|
|
@ -24,10 +24,14 @@ import (
|
|||
func Changes(old, new *types.Package) Report {
|
||||
d := newDiffer(old, new)
|
||||
d.checkPackage()
|
||||
return Report{
|
||||
Incompatible: d.incompatibles.collect(),
|
||||
Compatible: d.compatibles.collect(),
|
||||
r := Report{}
|
||||
for _, m := range d.incompatibles.collect() {
|
||||
r.Changes = append(r.Changes, Change{Message: m, Compatible: false})
|
||||
}
|
||||
for _, m := range d.compatibles.collect() {
|
||||
r.Changes = append(r.Changes, Change{Message: m, Compatible: true})
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
type differ struct {
|
||||
|
|
|
@ -6,8 +6,10 @@ import (
|
|||
"go/types"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
|
@ -26,22 +28,24 @@ func TestChanges(t *testing.T) {
|
|||
sort.Strings(wanti)
|
||||
sort.Strings(wantc)
|
||||
|
||||
oldpkg, err := load("apidiff/old", dir)
|
||||
oldpkg, err := load(t, "apidiff/old", dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
newpkg, err := load("apidiff/new", dir)
|
||||
newpkg, err := load(t, "apidiff/new", dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
report := Changes(oldpkg.Types, newpkg.Types)
|
||||
|
||||
if !reflect.DeepEqual(report.Incompatible, wanti) {
|
||||
t.Errorf("incompatibles: got %v\nwant %v\n", report.Incompatible, wanti)
|
||||
got := report.messages(false)
|
||||
if !reflect.DeepEqual(got, wanti) {
|
||||
t.Errorf("incompatibles: got %v\nwant %v\n", got, wanti)
|
||||
}
|
||||
if !reflect.DeepEqual(report.Compatible, wantc) {
|
||||
t.Errorf("compatibles: got %v\nwant %v\n", report.Compatible, wantc)
|
||||
got = report.messages(true)
|
||||
if !reflect.DeepEqual(got, wantc) {
|
||||
t.Errorf("compatibles: got %v\nwant %v\n", got, wantc)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,7 +117,9 @@ func splitIntoPackages(t *testing.T, dir string) (incompatibles, compatibles []s
|
|||
return
|
||||
}
|
||||
|
||||
func load(importPath, goPath string) (*packages.Package, error) {
|
||||
func load(t *testing.T, importPath, goPath string) (*packages.Package, error) {
|
||||
needsGoPackages(t)
|
||||
|
||||
cfg := &packages.Config{
|
||||
Mode: packages.LoadTypes,
|
||||
}
|
||||
|
@ -132,7 +138,7 @@ func load(importPath, goPath string) (*packages.Package, error) {
|
|||
}
|
||||
|
||||
func TestExportedFields(t *testing.T) {
|
||||
pkg, err := load("golang.org/x/exp/apidiff/testdata/exported_fields", "")
|
||||
pkg, err := load(t, "golang.org/x/exp/apidiff/testdata/exported_fields", "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -164,3 +170,69 @@ func TestExportedFields(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// needsGoPackages skips t if the go/packages driver (or 'go' tool) implied by
|
||||
// the current process environment is not present in the path.
|
||||
//
|
||||
// Copied and adapted from golang.org/x/tools/internal/testenv.
|
||||
func needsGoPackages(t *testing.T) {
|
||||
t.Helper()
|
||||
|
||||
tool := os.Getenv("GOPACKAGESDRIVER")
|
||||
switch tool {
|
||||
case "off":
|
||||
// "off" forces go/packages to use the go command.
|
||||
tool = "go"
|
||||
case "":
|
||||
if _, err := exec.LookPath("gopackagesdriver"); err == nil {
|
||||
tool = "gopackagesdriver"
|
||||
} else {
|
||||
tool = "go"
|
||||
}
|
||||
}
|
||||
|
||||
needsTool(t, tool)
|
||||
}
|
||||
|
||||
// needsTool skips t if the named tool is not present in the path.
|
||||
//
|
||||
// Copied and adapted from golang.org/x/tools/internal/testenv.
|
||||
func needsTool(t *testing.T, tool string) {
|
||||
_, err := exec.LookPath(tool)
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
|
||||
t.Helper()
|
||||
if allowMissingTool(tool) {
|
||||
t.Skipf("skipping because %s tool not available: %v", tool, err)
|
||||
} else {
|
||||
t.Fatalf("%s tool not available: %v", tool, err)
|
||||
}
|
||||
}
|
||||
|
||||
func allowMissingTool(tool string) bool {
|
||||
if runtime.GOOS == "android" {
|
||||
// Android builds generally run tests on a separate machine from the build,
|
||||
// so don't expect any external tools to be available.
|
||||
return true
|
||||
}
|
||||
|
||||
if tool == "go" && os.Getenv("GO_BUILDER_NAME") == "illumos-amd64-joyent" {
|
||||
// Work around a misconfigured builder (see https://golang.org/issue/33950).
|
||||
return true
|
||||
}
|
||||
|
||||
// If a developer is actively working on this test, we expect them to have all
|
||||
// of its dependencies installed. However, if it's just a dependency of some
|
||||
// other module (for example, being run via 'go test all'), we should be more
|
||||
// tolerant of unusual environments.
|
||||
return !packageMainIsDevel()
|
||||
}
|
||||
|
||||
// packageMainIsDevel reports whether the module containing package main
|
||||
// is a development version (if module information is available).
|
||||
//
|
||||
// Builds in GOPATH mode and builds that lack module information are assumed to
|
||||
// be development versions.
|
||||
var packageMainIsDevel = func() bool { return true }
|
||||
|
|
|
@ -8,7 +8,23 @@ import (
|
|||
|
||||
// Report describes the changes detected by Changes.
|
||||
type Report struct {
|
||||
Incompatible, Compatible []string
|
||||
Changes []Change
|
||||
}
|
||||
|
||||
// A Change describes a single API change.
|
||||
type Change struct {
|
||||
Message string
|
||||
Compatible bool
|
||||
}
|
||||
|
||||
func (r Report) messages(compatible bool) []string {
|
||||
var msgs []string
|
||||
for _, c := range r.Changes {
|
||||
if c.Compatible == compatible {
|
||||
msgs = append(msgs, c.Message)
|
||||
}
|
||||
}
|
||||
return msgs
|
||||
}
|
||||
|
||||
func (r Report) String() string {
|
||||
|
@ -28,13 +44,13 @@ func (r Report) Text(w io.Writer) error {
|
|||
|
||||
func (r Report) TextIncompatible(w io.Writer, withHeader bool) error {
|
||||
if withHeader {
|
||||
return r.writeMessages(w, "Incompatible changes:", r.Incompatible)
|
||||
return r.writeMessages(w, "Incompatible changes:", r.messages(false))
|
||||
}
|
||||
return r.writeMessages(w, "", r.Incompatible)
|
||||
return r.writeMessages(w, "", r.messages(false))
|
||||
}
|
||||
|
||||
func (r Report) TextCompatible(w io.Writer) error {
|
||||
return r.writeMessages(w, "Compatible changes:", r.Compatible)
|
||||
return r.writeMessages(w, "Compatible changes:", r.messages(true))
|
||||
}
|
||||
|
||||
func (r Report) writeMessages(w io.Writer, header string, msgs []string) error {
|
||||
|
|
2
go.mod
2
go.mod
|
@ -10,5 +10,5 @@ require (
|
|||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028
|
||||
golang.org/x/mod v0.1.0
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d
|
||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479
|
||||
golang.org/x/tools v0.0.0-20190925164712-ae58c0ff6b32
|
||||
)
|
||||
|
|
4
go.sum
4
go.sum
|
@ -23,6 +23,6 @@ golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479 h1:lfN2PY/jymfnxkNHlbBF5DwPsUvhqUnrdgfK01iH2s0=
|
||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190925164712-ae58c0ff6b32 h1:xE6VFETO5vvJp3W3iihukTHFkQiu9yrTMJNKu20CwE4=
|
||||
golang.org/x/tools v0.0.0-20190925164712-ae58c0ff6b32/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
|
Загрузка…
Ссылка в новой задаче