summaryrefslogtreecommitdiff
path: root/src/cmd/api
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/api')
-rw-r--r--src/cmd/api/goapi.go158
-rw-r--r--src/cmd/api/goapi_test.go24
-rw-r--r--src/cmd/api/run.go9
3 files changed, 168 insertions, 23 deletions
diff --git a/src/cmd/api/goapi.go b/src/cmd/api/goapi.go
index 4bde794a1..4a63eac71 100644
--- a/src/cmd/api/goapi.go
+++ b/src/cmd/api/goapi.go
@@ -107,6 +107,8 @@ func setContexts() {
}
}
+var internalPkg = regexp.MustCompile(`(^|/)internal($|/)`)
+
func main() {
flag.Parse()
@@ -132,12 +134,16 @@ func main() {
if err != nil {
log.Fatal(err)
}
- pkgNames = strings.Fields(string(stds))
+ for _, pkg := range strings.Fields(string(stds)) {
+ if !internalPkg.MatchString(pkg) {
+ pkgNames = append(pkgNames, pkg)
+ }
+ }
}
var featureCtx = make(map[string]map[string]bool) // feature -> context name -> true
for _, context := range contexts {
- w := NewWalker(context, filepath.Join(build.Default.GOROOT, "src/pkg"))
+ w := NewWalker(context, filepath.Join(build.Default.GOROOT, "src"))
for _, name := range pkgNames {
// - Package "unsafe" contains special signatures requiring
@@ -277,7 +283,7 @@ func compareAPI(w io.Writer, features, required, optional, exception []string) (
delete(optionalSet, newFeature)
} else {
fmt.Fprintf(w, "+%s\n", newFeature)
- if !*allowNew {
+ if !*allowNew || !strings.Contains(runtime.Version(), "devel") {
ok = false // we're in lock-down mode for next release
}
}
@@ -307,11 +313,15 @@ func fileFeatures(filename string) []string {
if err != nil {
log.Fatalf("Error reading file %s: %v", filename, err)
}
- text := strings.TrimSpace(string(bs))
- if text == "" {
- return nil
+ lines := strings.Split(string(bs), "\n")
+ var nonblank []string
+ for _, line := range lines {
+ line = strings.TrimSpace(line)
+ if line != "" && !strings.HasPrefix(line, "#") {
+ nonblank = append(nonblank, line)
+ }
}
- return strings.Split(text, "\n")
+ return nonblank
}
var fset = token.NewFileSet()
@@ -370,6 +380,106 @@ func (w *Walker) parseFile(dir, file string) (*ast.File, error) {
log.Fatalf("incorrect generated file: %s", err)
}
}
+ if w.context != nil && file == fmt.Sprintf("zruntime_defs_%s_%s.go", w.context.GOOS, w.context.GOARCH) {
+ // Just enough to keep the api checker happy. Keep sorted.
+ src := "package runtime; type (" +
+ " _defer struct{};" +
+ " _func struct{};" +
+ " _panic struct{};" +
+ " _select struct{}; " +
+ " _type struct{};" +
+ " alg struct{};" +
+ " chantype struct{};" +
+ " context struct{};" + // windows
+ " eface struct{};" +
+ " epollevent struct{};" +
+ " funcval struct{};" +
+ " g struct{};" +
+ " gobuf struct{};" +
+ " hchan struct{};" +
+ " iface struct{};" +
+ " interfacetype struct{};" +
+ " itab struct{};" +
+ " keventt struct{};" +
+ " m struct{};" +
+ " maptype struct{};" +
+ " mcache struct{};" +
+ " mspan struct{};" +
+ " mutex struct{};" +
+ " note struct{};" +
+ " p struct{};" +
+ " parfor struct{};" +
+ " slicetype struct{};" +
+ " stkframe struct{};" +
+ " sudog struct{};" +
+ " timespec struct{};" +
+ " waitq struct{};" +
+ " wincallbackcontext struct{};" +
+ "); " +
+ "const (" +
+ " cb_max = 2000;" +
+ " _CacheLineSize = 64;" +
+ " _Gidle = 1;" +
+ " _Grunnable = 2;" +
+ " _Grunning = 3;" +
+ " _Gsyscall = 4;" +
+ " _Gwaiting = 5;" +
+ " _Gdead = 6;" +
+ " _Genqueue = 7;" +
+ " _Gcopystack = 8;" +
+ " _NSIG = 32;" +
+ " _FlagNoScan = iota;" +
+ " _FlagNoZero;" +
+ " _TinySize;" +
+ " _TinySizeClass;" +
+ " _MaxSmallSize;" +
+ " _PageShift;" +
+ " _PageSize;" +
+ " _PageMask;" +
+ " _BitsPerPointer;" +
+ " _BitsMask;" +
+ " _PointersPerByte;" +
+ " _MaxGCMask;" +
+ " _BitsDead;" +
+ " _BitsPointer;" +
+ " _MSpanInUse;" +
+ " _ConcurrentSweep;" +
+ " _KindBool;" +
+ " _KindInt;" +
+ " _KindInt8;" +
+ " _KindInt16;" +
+ " _KindInt32;" +
+ " _KindInt64;" +
+ " _KindUint;" +
+ " _KindUint8;" +
+ " _KindUint16;" +
+ " _KindUint32;" +
+ " _KindUint64;" +
+ " _KindUintptr;" +
+ " _KindFloat32;" +
+ " _KindFloat64;" +
+ " _KindComplex64;" +
+ " _KindComplex128;" +
+ " _KindArray;" +
+ " _KindChan;" +
+ " _KindFunc;" +
+ " _KindInterface;" +
+ " _KindMap;" +
+ " _KindPtr;" +
+ " _KindSlice;" +
+ " _KindString;" +
+ " _KindStruct;" +
+ " _KindUnsafePointer;" +
+ " _KindDirectIface;" +
+ " _KindGCProg;" +
+ " _KindNoPointers;" +
+ " _KindMask;" +
+ ")"
+ f, err = parser.ParseFile(fset, filename, src, 0)
+ if err != nil {
+ log.Fatalf("incorrect generated file: %s", err)
+ }
+ }
if f == nil {
f, err = parser.ParseFile(fset, filename, nil, 0)
@@ -391,6 +501,11 @@ func contains(list []string, s string) bool {
return false
}
+// The package cache doesn't operate correctly in rare (so far artificial)
+// circumstances (issue 8425). Disable before debugging non-obvious errors
+// from the type-checker.
+const usePkgCache = true
+
var (
pkgCache = map[string]*types.Package{} // map tagKey to package
pkgTags = map[string][]string{} // map import dir to list of relevant tags
@@ -452,11 +567,13 @@ func (w *Walker) Import(name string) (pkg *types.Package) {
// If we've already done an import with the same set
// of relevant tags, reuse the result.
var key string
- if tags, ok := pkgTags[dir]; ok {
- key = tagKey(dir, context, tags)
- if pkg := pkgCache[key]; pkg != nil {
- w.imported[name] = pkg
- return pkg
+ if usePkgCache {
+ if tags, ok := pkgTags[dir]; ok {
+ key = tagKey(dir, context, tags)
+ if pkg := pkgCache[key]; pkg != nil {
+ w.imported[name] = pkg
+ return pkg
+ }
}
}
@@ -469,9 +586,11 @@ func (w *Walker) Import(name string) (pkg *types.Package) {
}
// Save tags list first time we see a directory.
- if _, ok := pkgTags[dir]; !ok {
- pkgTags[dir] = info.AllTags
- key = tagKey(dir, context, info.AllTags)
+ if usePkgCache {
+ if _, ok := pkgTags[dir]; !ok {
+ pkgTags[dir] = info.AllTags
+ key = tagKey(dir, context, info.AllTags)
+ }
}
filenames := append(append([]string{}, info.GoFiles...), info.CgoFiles...)
@@ -488,6 +607,11 @@ func (w *Walker) Import(name string) (pkg *types.Package) {
if !contains(filenames, n) {
filenames = append(filenames, n)
}
+
+ n = fmt.Sprintf("zruntime_defs_%s_%s.go", w.context.GOOS, w.context.GOARCH)
+ if !contains(filenames, n) {
+ filenames = append(filenames, n)
+ }
}
// Parse package files.
@@ -519,7 +643,9 @@ func (w *Walker) Import(name string) (pkg *types.Package) {
log.Fatalf("error typechecking package %s: %s (%s)", name, err, ctxt)
}
- pkgCache[key] = pkg
+ if usePkgCache {
+ pkgCache[key] = pkg
+ }
w.imported[name] = pkg
return
diff --git a/src/cmd/api/goapi_test.go b/src/cmd/api/goapi_test.go
index b909c32b3..f4fb7d319 100644
--- a/src/cmd/api/goapi_test.go
+++ b/src/cmd/api/goapi_test.go
@@ -38,7 +38,7 @@ func TestGolden(t *testing.T) {
continue
}
- goldenFile := filepath.Join("testdata", "src", "pkg", fi.Name(), "golden.txt")
+ goldenFile := filepath.Join("testdata", "src", fi.Name(), "golden.txt")
w := NewWalker(nil, "testdata/src/pkg")
w.export(w.Import(fi.Name()))
@@ -142,6 +142,26 @@ func TestCompareAPI(t *testing.T) {
}
}
+func TestSkipInternal(t *testing.T) {
+ tests := []struct {
+ pkg string
+ want bool
+ }{
+ {"net/http", true},
+ {"net/http/internal-foo", true},
+ {"net/http/internal", false},
+ {"net/http/internal/bar", false},
+ {"internal/foo", false},
+ {"internal", false},
+ }
+ for _, tt := range tests {
+ got := !internalPkg.MatchString(tt.pkg)
+ if got != tt.want {
+ t.Errorf("%s is internal = %v; want %v", tt.pkg, got, tt.want)
+ }
+ }
+}
+
func BenchmarkAll(b *testing.B) {
stds, err := exec.Command("go", "list", "std").Output()
if err != nil {
@@ -156,7 +176,7 @@ func BenchmarkAll(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, context := range contexts {
- w := NewWalker(context, filepath.Join(build.Default.GOROOT, "src/pkg"))
+ w := NewWalker(context, filepath.Join(build.Default.GOROOT, "src"))
for _, name := range pkgNames {
if name != "unsafe" && !strings.HasPrefix(name, "cmd/") {
w.export(w.Import(name))
diff --git a/src/cmd/api/run.go b/src/cmd/api/run.go
index 896b2b4a1..ed5613edd 100644
--- a/src/cmd/api/run.go
+++ b/src/cmd/api/run.go
@@ -21,6 +21,7 @@ import (
"os/exec"
"os/user"
"path/filepath"
+ "runtime"
"strings"
)
@@ -53,7 +54,7 @@ func main() {
}
out, err = exec.Command("go", "tool", "api",
- "-c", file("go1", "go1.1", "go1.2", "go1.3"),
+ "-c", file("go1", "go1.1", "go1.2", "go1.3", "go1.4"),
"-next", file("next"),
"-except", file("except")).CombinedOutput()
if err != nil {
@@ -98,16 +99,14 @@ func prepGoPath() string {
if err == nil {
username = u.Username
} else {
- // Only need to handle Unix here, as Windows's os/user uses
- // native syscall and should work fine without cgo.
username = os.Getenv("USER")
if username == "" {
- log.Fatalf("Error getting current user: %v", err)
+ username = "nobody"
}
}
// The GOPATH we'll return
- gopath := filepath.Join(os.TempDir(), "gopath-api-"+cleanUsername(username), goToolsVersion)
+ gopath := filepath.Join(os.TempDir(), "gopath-api-"+cleanUsername(username)+"-"+cleanUsername(strings.Fields(runtime.Version())[0]), goToolsVersion)
// cloneDir is where we run "hg clone".
cloneDir := filepath.Join(gopath, "src", "code.google.com", "p")