aboutsummaryrefslogtreecommitdiffstats
path: root/Godeps/_workspace/src/golang.org/x/tools/imports
diff options
context:
space:
mode:
Diffstat (limited to 'Godeps/_workspace/src/golang.org/x/tools/imports')
-rw-r--r--Godeps/_workspace/src/golang.org/x/tools/imports/fastwalk.go172
-rw-r--r--Godeps/_workspace/src/golang.org/x/tools/imports/fastwalk_dirent_fileno.go13
-rw-r--r--Godeps/_workspace/src/golang.org/x/tools/imports/fastwalk_dirent_ino.go13
-rw-r--r--Godeps/_workspace/src/golang.org/x/tools/imports/fastwalk_portable.go29
-rw-r--r--Godeps/_workspace/src/golang.org/x/tools/imports/fastwalk_unix.go122
-rw-r--r--Godeps/_workspace/src/golang.org/x/tools/imports/fix.go856
-rw-r--r--Godeps/_workspace/src/golang.org/x/tools/imports/imports.go12
-rw-r--r--Godeps/_workspace/src/golang.org/x/tools/imports/mkstdlib.go12
-rw-r--r--Godeps/_workspace/src/golang.org/x/tools/imports/zstdlib.go277
9 files changed, 1339 insertions, 167 deletions
diff --git a/Godeps/_workspace/src/golang.org/x/tools/imports/fastwalk.go b/Godeps/_workspace/src/golang.org/x/tools/imports/fastwalk.go
new file mode 100644
index 000000000..157c79225
--- /dev/null
+++ b/Godeps/_workspace/src/golang.org/x/tools/imports/fastwalk.go
@@ -0,0 +1,172 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// A faster implementation of filepath.Walk.
+//
+// filepath.Walk's design necessarily calls os.Lstat on each file,
+// even if the caller needs less info. And goimports only need to know
+// the type of each file. The kernel interface provides the type in
+// the Readdir call but the standard library ignored it.
+// fastwalk_unix.go contains a fork of the syscall routines.
+//
+// See golang.org/issue/16399
+
+package imports
+
+import (
+ "errors"
+ "os"
+ "path/filepath"
+ "runtime"
+)
+
+// traverseLink is a sentinel error for fastWalk, similar to filepath.SkipDir.
+var traverseLink = errors.New("traverse symlink, assuming target is a directory")
+
+// fastWalk walks the file tree rooted at root, calling walkFn for
+// each file or directory in the tree, including root.
+//
+// If fastWalk returns filepath.SkipDir, the directory is skipped.
+//
+// Unlike filepath.Walk:
+// * file stat calls must be done by the user.
+// The only provided metadata is the file type, which does not include
+// any permission bits.
+// * multiple goroutines stat the filesystem concurrently. The provided
+// walkFn must be safe for concurrent use.
+// * fastWalk can follow symlinks if walkFn returns the traverseLink
+// sentinel error. It is the walkFn's responsibility to prevent
+// fastWalk from going into symlink cycles.
+func fastWalk(root string, walkFn func(path string, typ os.FileMode) error) error {
+ // TODO(bradfitz): make numWorkers configurable? We used a
+ // minimum of 4 to give the kernel more info about multiple
+ // things we want, in hopes its I/O scheduling can take
+ // advantage of that. Hopefully most are in cache. Maybe 4 is
+ // even too low of a minimum. Profile more.
+ numWorkers := 4
+ if n := runtime.NumCPU(); n > numWorkers {
+ numWorkers = n
+ }
+ w := &walker{
+ fn: walkFn,
+ enqueuec: make(chan walkItem, numWorkers), // buffered for performance
+ workc: make(chan walkItem, numWorkers), // buffered for performance
+ donec: make(chan struct{}),
+
+ // buffered for correctness & not leaking goroutines:
+ resc: make(chan error, numWorkers),
+ }
+ defer close(w.donec)
+ // TODO(bradfitz): start the workers as needed? maybe not worth it.
+ for i := 0; i < numWorkers; i++ {
+ go w.doWork()
+ }
+ todo := []walkItem{{dir: root}}
+ out := 0
+ for {
+ workc := w.workc
+ var workItem walkItem
+ if len(todo) == 0 {
+ workc = nil
+ } else {
+ workItem = todo[len(todo)-1]
+ }
+ select {
+ case workc <- workItem:
+ todo = todo[:len(todo)-1]
+ out++
+ case it := <-w.enqueuec:
+ todo = append(todo, it)
+ case err := <-w.resc:
+ out--
+ if err != nil {
+ return err
+ }
+ if out == 0 && len(todo) == 0 {
+ // It's safe to quit here, as long as the buffered
+ // enqueue channel isn't also readable, which might
+ // happen if the worker sends both another unit of
+ // work and its result before the other select was
+ // scheduled and both w.resc and w.enqueuec were
+ // readable.
+ select {
+ case it := <-w.enqueuec:
+ todo = append(todo, it)
+ default:
+ return nil
+ }
+ }
+ }
+ }
+}
+
+// doWork reads directories as instructed (via workc) and runs the
+// user's callback function.
+func (w *walker) doWork() {
+ for {
+ select {
+ case <-w.donec:
+ return
+ case it := <-w.workc:
+ w.resc <- w.walk(it.dir, !it.callbackDone)
+ }
+ }
+}
+
+type walker struct {
+ fn func(path string, typ os.FileMode) error
+
+ donec chan struct{} // closed on fastWalk's return
+ workc chan walkItem // to workers
+ enqueuec chan walkItem // from workers
+ resc chan error // from workers
+}
+
+type walkItem struct {
+ dir string
+ callbackDone bool // callback already called; don't do it again
+}
+
+func (w *walker) enqueue(it walkItem) {
+ select {
+ case w.enqueuec <- it:
+ case <-w.donec:
+ }
+}
+
+func (w *walker) onDirEnt(dirName, baseName string, typ os.FileMode) error {
+ joined := dirName + string(os.PathSeparator) + baseName
+ if typ == os.ModeDir {
+ w.enqueue(walkItem{dir: joined})
+ return nil
+ }
+
+ err := w.fn(joined, typ)
+ if typ == os.ModeSymlink {
+ if err == traverseLink {
+ // Set callbackDone so we don't call it twice for both the
+ // symlink-as-symlink and the symlink-as-directory later:
+ w.enqueue(walkItem{dir: joined, callbackDone: true})
+ return nil
+ }
+ if err == filepath.SkipDir {
+ // Permit SkipDir on symlinks too.
+ return nil
+ }
+ }
+ return err
+}
+func (w *walker) walk(root string, runUserCallback bool) error {
+ if runUserCallback {
+ err := w.fn(root, os.ModeDir)
+ if err == filepath.SkipDir {
+ return nil
+ }
+ if err != nil {
+ return err
+ }
+ }
+
+ return readDir(root, w.onDirEnt)
+}
diff --git a/Godeps/_workspace/src/golang.org/x/tools/imports/fastwalk_dirent_fileno.go b/Godeps/_workspace/src/golang.org/x/tools/imports/fastwalk_dirent_fileno.go
new file mode 100644
index 000000000..f1fd64949
--- /dev/null
+++ b/Godeps/_workspace/src/golang.org/x/tools/imports/fastwalk_dirent_fileno.go
@@ -0,0 +1,13 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build freebsd openbsd netbsd
+
+package imports
+
+import "syscall"
+
+func direntInode(dirent *syscall.Dirent) uint64 {
+ return uint64(dirent.Fileno)
+}
diff --git a/Godeps/_workspace/src/golang.org/x/tools/imports/fastwalk_dirent_ino.go b/Godeps/_workspace/src/golang.org/x/tools/imports/fastwalk_dirent_ino.go
new file mode 100644
index 000000000..ee85bc4dd
--- /dev/null
+++ b/Godeps/_workspace/src/golang.org/x/tools/imports/fastwalk_dirent_ino.go
@@ -0,0 +1,13 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux,!appengine darwin
+
+package imports
+
+import "syscall"
+
+func direntInode(dirent *syscall.Dirent) uint64 {
+ return uint64(dirent.Ino)
+}
diff --git a/Godeps/_workspace/src/golang.org/x/tools/imports/fastwalk_portable.go b/Godeps/_workspace/src/golang.org/x/tools/imports/fastwalk_portable.go
new file mode 100644
index 000000000..6c2658347
--- /dev/null
+++ b/Godeps/_workspace/src/golang.org/x/tools/imports/fastwalk_portable.go
@@ -0,0 +1,29 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build appengine !linux,!darwin,!freebsd,!openbsd,!netbsd
+
+package imports
+
+import (
+ "io/ioutil"
+ "os"
+)
+
+// readDir calls fn for each directory entry in dirName.
+// It does not descend into directories or follow symlinks.
+// If fn returns a non-nil error, readDir returns with that error
+// immediately.
+func readDir(dirName string, fn func(dirName, entName string, typ os.FileMode) error) error {
+ fis, err := ioutil.ReadDir(dirName)
+ if err != nil {
+ return err
+ }
+ for _, fi := range fis {
+ if err := fn(dirName, fi.Name(), fi.Mode()&os.ModeType); err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/Godeps/_workspace/src/golang.org/x/tools/imports/fastwalk_unix.go b/Godeps/_workspace/src/golang.org/x/tools/imports/fastwalk_unix.go
new file mode 100644
index 000000000..5854233db
--- /dev/null
+++ b/Godeps/_workspace/src/golang.org/x/tools/imports/fastwalk_unix.go
@@ -0,0 +1,122 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux,!appengine darwin freebsd openbsd netbsd
+
+package imports
+
+import (
+ "bytes"
+ "fmt"
+ "os"
+ "syscall"
+ "unsafe"
+)
+
+const blockSize = 8 << 10
+
+// unknownFileMode is a sentinel (and bogus) os.FileMode
+// value used to represent a syscall.DT_UNKNOWN Dirent.Type.
+const unknownFileMode os.FileMode = os.ModeNamedPipe | os.ModeSocket | os.ModeDevice
+
+func readDir(dirName string, fn func(dirName, entName string, typ os.FileMode) error) error {
+ fd, err := syscall.Open(dirName, 0, 0)
+ if err != nil {
+ return err
+ }
+ defer syscall.Close(fd)
+
+ // The buffer must be at least a block long.
+ buf := make([]byte, blockSize) // stack-allocated; doesn't escape
+ bufp := 0 // starting read position in buf
+ nbuf := 0 // end valid data in buf
+ for {
+ if bufp >= nbuf {
+ bufp = 0
+ nbuf, err = syscall.ReadDirent(fd, buf)
+ if err != nil {
+ return os.NewSyscallError("readdirent", err)
+ }
+ if nbuf <= 0 {
+ return nil
+ }
+ }
+ consumed, name, typ := parseDirEnt(buf[bufp:nbuf])
+ bufp += consumed
+ if name == "" || name == "." || name == ".." {
+ continue
+ }
+ // Fallback for filesystems (like old XFS) that don't
+ // support Dirent.Type and have DT_UNKNOWN (0) there
+ // instead.
+ if typ == unknownFileMode {
+ fi, err := os.Lstat(dirName + "/" + name)
+ if err != nil {
+ // It got deleted in the meantime.
+ if os.IsNotExist(err) {
+ continue
+ }
+ return err
+ }
+ typ = fi.Mode() & os.ModeType
+ }
+ if err := fn(dirName, name, typ); err != nil {
+ return err
+ }
+ }
+}
+
+func parseDirEnt(buf []byte) (consumed int, name string, typ os.FileMode) {
+ // golang.org/issue/15653
+ dirent := (*syscall.Dirent)(unsafe.Pointer(&buf[0]))
+ if v := unsafe.Offsetof(dirent.Reclen) + unsafe.Sizeof(dirent.Reclen); uintptr(len(buf)) < v {
+ panic(fmt.Sprintf("buf size of %d smaller than dirent header size %d", len(buf), v))
+ }
+ if len(buf) < int(dirent.Reclen) {
+ panic(fmt.Sprintf("buf size %d < record length %d", len(buf), dirent.Reclen))
+ }
+ consumed = int(dirent.Reclen)
+ if direntInode(dirent) == 0 { // File absent in directory.
+ return
+ }
+ switch dirent.Type {
+ case syscall.DT_REG:
+ typ = 0
+ case syscall.DT_DIR:
+ typ = os.ModeDir
+ case syscall.DT_LNK:
+ typ = os.ModeSymlink
+ case syscall.DT_BLK:
+ typ = os.ModeDevice
+ case syscall.DT_FIFO:
+ typ = os.ModeNamedPipe
+ case syscall.DT_SOCK:
+ typ = os.ModeSocket
+ case syscall.DT_UNKNOWN:
+ typ = unknownFileMode
+ default:
+ // Skip weird things.
+ // It's probably a DT_WHT (http://lwn.net/Articles/325369/)
+ // or something. Revisit if/when this package is moved outside
+ // of goimports. goimports only cares about regular files,
+ // symlinks, and directories.
+ return
+ }
+
+ nameBuf := (*[unsafe.Sizeof(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0]))
+ nameLen := bytes.IndexByte(nameBuf[:], 0)
+ if nameLen < 0 {
+ panic("failed to find terminating 0 byte in dirent")
+ }
+
+ // Special cases for common things:
+ if nameLen == 1 && nameBuf[0] == '.' {
+ name = "."
+ } else if nameLen == 2 && nameBuf[0] == '.' && nameBuf[1] == '.' {
+ name = ".."
+ } else {
+ name = string(nameBuf[:nameLen])
+ }
+ return
+}
diff --git a/Godeps/_workspace/src/golang.org/x/tools/imports/fix.go b/Godeps/_workspace/src/golang.org/x/tools/imports/fix.go
index 4fc50570d..a241c2976 100644
--- a/Godeps/_workspace/src/golang.org/x/tools/imports/fix.go
+++ b/Godeps/_workspace/src/golang.org/x/tools/imports/fix.go
@@ -5,24 +5,47 @@
package imports
import (
+ "bufio"
+ "bytes"
"fmt"
"go/ast"
"go/build"
"go/parser"
"go/token"
+ "io/ioutil"
+ "log"
"os"
"path"
"path/filepath"
+ "sort"
"strings"
"sync"
"golang.org/x/tools/go/ast/astutil"
)
+// Debug controls verbose logging.
+var Debug = false
+
+var (
+ inTests = false // set true by fix_test.go; if false, no need to use testMu
+ testMu sync.RWMutex // guards globals reset by tests; used only if inTests
+)
+
+// If set, LocalPrefix instructs Process to sort import paths with the given
+// prefix into another group after 3rd-party packages.
+var LocalPrefix string
+
// importToGroup is a list of functions which map from an import path to
// a group number.
var importToGroup = []func(importPath string) (num int, ok bool){
func(importPath string) (num int, ok bool) {
+ if LocalPrefix != "" && strings.HasPrefix(importPath, LocalPrefix) {
+ return 3, true
+ }
+ return
+ },
+ func(importPath string) (num int, ok bool) {
if strings.HasPrefix(importPath, "appengine") {
return 2, true
}
@@ -45,6 +68,62 @@ func importGroup(importPath string) int {
return 0
}
+// packageInfo is a summary of features found in a package.
+type packageInfo struct {
+ Globals map[string]bool // symbol => true
+}
+
+// dirPackageInfo gets information from other files in the package.
+func dirPackageInfo(srcDir, filename string) (*packageInfo, error) {
+ considerTests := strings.HasSuffix(filename, "_test.go")
+
+ // Handle file from stdin
+ if _, err := os.Stat(filename); err != nil {
+ if os.IsNotExist(err) {
+ return &packageInfo{}, nil
+ }
+ return nil, err
+ }
+
+ fileBase := filepath.Base(filename)
+ packageFileInfos, err := ioutil.ReadDir(srcDir)
+ if err != nil {
+ return nil, err
+ }
+
+ info := &packageInfo{Globals: make(map[string]bool)}
+ for _, fi := range packageFileInfos {
+ if fi.Name() == fileBase || !strings.HasSuffix(fi.Name(), ".go") {
+ continue
+ }
+ if !considerTests && strings.HasSuffix(fi.Name(), "_test.go") {
+ continue
+ }
+
+ fileSet := token.NewFileSet()
+ root, err := parser.ParseFile(fileSet, filepath.Join(srcDir, fi.Name()), nil, 0)
+ if err != nil {
+ continue
+ }
+
+ for _, decl := range root.Decls {
+ genDecl, ok := decl.(*ast.GenDecl)
+ if !ok {
+ continue
+ }
+
+ for _, spec := range genDecl.Specs {
+ valueSpec, ok := spec.(*ast.ValueSpec)
+ if !ok {
+ continue
+ }
+ info.Globals[valueSpec.Names[0].Name] = true
+ }
+ }
+ }
+ return info, nil
+}
+
func fixImports(fset *token.FileSet, f *ast.File, filename string) (added []string, err error) {
// refs are a set of possible package references currently unsatisfied by imports.
// first key: either base package (e.g. "fmt") or renamed package
@@ -54,6 +133,18 @@ func fixImports(fset *token.FileSet, f *ast.File, filename string) (added []stri
// decls are the current package imports. key is base package or renamed package.
decls := make(map[string]*ast.ImportSpec)
+ abs, err := filepath.Abs(filename)
+ if err != nil {
+ return nil, err
+ }
+ srcDir := filepath.Dir(abs)
+ if Debug {
+ log.Printf("fixImports(filename=%q), abs=%q, srcDir=%q ...", filename, abs, srcDir)
+ }
+
+ var packageInfo *packageInfo
+ var loadedPackageInfo bool
+
// collect potential uses of packages.
var visitor visitFn
visitor = visitFn(func(node ast.Node) ast.Visitor {
@@ -64,10 +155,14 @@ func fixImports(fset *token.FileSet, f *ast.File, filename string) (added []stri
case *ast.ImportSpec:
if v.Name != nil {
decls[v.Name.Name] = v
- } else {
- local := importPathToName(strings.Trim(v.Path.Value, `\"`))
- decls[local] = v
+ break
}
+ ipath := strings.Trim(v.Path.Value, `"`)
+ if ipath == "C" {
+ break
+ }
+ local := importPathToName(ipath, srcDir)
+ decls[local] = v
case *ast.SelectorExpr:
xident, ok := v.X.(*ast.Ident)
if !ok {
@@ -81,7 +176,11 @@ func fixImports(fset *token.FileSet, f *ast.File, filename string) (added []stri
if refs[pkgName] == nil {
refs[pkgName] = make(map[string]bool)
}
- if decls[pkgName] == nil {
+ if !loadedPackageInfo {
+ loadedPackageInfo = true
+ packageInfo, _ = dirPackageInfo(srcDir, filename)
+ }
+ if decls[pkgName] == nil && (packageInfo == nil || !packageInfo.Globals[pkgName]) {
refs[pkgName][v.Sel.Name] = true
}
}
@@ -108,18 +207,22 @@ func fixImports(fset *token.FileSet, f *ast.File, filename string) (added []stri
astutil.DeleteNamedImport(fset, f, name, ipath)
}
+ for pkgName, symbols := range refs {
+ if len(symbols) == 0 {
+ // skip over packages already imported
+ delete(refs, pkgName)
+ }
+ }
+
// Search for imports matching potential package references.
searches := 0
type result struct {
- ipath string
- name string
+ ipath string // import path (if err == nil)
+ name string // optional name to rename import as
err error
}
results := make(chan result)
for pkgName, symbols := range refs {
- if len(symbols) == 0 {
- continue // skip over packages already imported
- }
go func(pkgName string, symbols map[string]bool) {
ipath, rename, err := findImport(pkgName, symbols, filename)
r := result{ipath: ipath, err: err}
@@ -149,34 +252,131 @@ func fixImports(fset *token.FileSet, f *ast.File, filename string) (added []stri
}
// importPathToName returns the package name for the given import path.
-var importPathToName = importPathToNameGoPath
+var importPathToName func(importPath, srcDir string) (packageName string) = importPathToNameGoPath
// importPathToNameBasic assumes the package name is the base of import path.
-func importPathToNameBasic(importPath string) (packageName string) {
+func importPathToNameBasic(importPath, srcDir string) (packageName string) {
return path.Base(importPath)
}
// importPathToNameGoPath finds out the actual package name, as declared in its .go files.
// If there's a problem, it falls back to using importPathToNameBasic.
-func importPathToNameGoPath(importPath string) (packageName string) {
- if buildPkg, err := build.Import(importPath, "", 0); err == nil {
- return buildPkg.Name
- } else {
- return importPathToNameBasic(importPath)
+func importPathToNameGoPath(importPath, srcDir string) (packageName string) {
+ // Fast path for standard library without going to disk.
+ if pkg, ok := stdImportPackage[importPath]; ok {
+ return pkg
+ }
+
+ pkgName, err := importPathToNameGoPathParse(importPath, srcDir)
+ if Debug {
+ log.Printf("importPathToNameGoPathParse(%q, srcDir=%q) = %q, %v", importPath, srcDir, pkgName, err)
+ }
+ if err == nil {
+ return pkgName
+ }
+ return importPathToNameBasic(importPath, srcDir)
+}
+
+// importPathToNameGoPathParse is a faster version of build.Import if
+// the only thing desired is the package name. It uses build.FindOnly
+// to find the directory and then only parses one file in the package,
+// trusting that the files in the directory are consistent.
+func importPathToNameGoPathParse(importPath, srcDir string) (packageName string, err error) {
+ buildPkg, err := build.Import(importPath, srcDir, build.FindOnly)
+ if err != nil {
+ return "", err
+ }
+ d, err := os.Open(buildPkg.Dir)
+ if err != nil {
+ return "", err
+ }
+ names, err := d.Readdirnames(-1)
+ d.Close()
+ if err != nil {
+ return "", err
+ }
+ sort.Strings(names) // to have predictable behavior
+ var lastErr error
+ var nfile int
+ for _, name := range names {
+ if !strings.HasSuffix(name, ".go") {
+ continue
+ }
+ if strings.HasSuffix(name, "_test.go") {
+ continue
+ }
+ nfile++
+ fullFile := filepath.Join(buildPkg.Dir, name)
+
+ fset := token.NewFileSet()
+ f, err := parser.ParseFile(fset, fullFile, nil, parser.PackageClauseOnly)
+ if err != nil {
+ lastErr = err
+ continue
+ }
+ pkgName := f.Name.Name
+ if pkgName == "documentation" {
+ // Special case from go/build.ImportDir, not
+ // handled by ctx.MatchFile.
+ continue
+ }
+ if pkgName == "main" {
+ // Also skip package main, assuming it's a +build ignore generator or example.
+ // Since you can't import a package main anyway, there's no harm here.
+ continue
+ }
+ return pkgName, nil
+ }
+ if lastErr != nil {
+ return "", lastErr
+ }
+ return "", fmt.Errorf("no importable package found in %d Go files", nfile)
+}
+
+var stdImportPackage = map[string]string{} // "net/http" => "http"
+
+func init() {
+ // Nothing in the standard library has a package name not
+ // matching its import base name.
+ for _, pkg := range stdlib {
+ if _, ok := stdImportPackage[pkg]; !ok {
+ stdImportPackage[pkg] = path.Base(pkg)
+ }
}
}
+// Directory-scanning state.
+var (
+ // scanGoRootOnce guards calling scanGoRoot (for $GOROOT)
+ scanGoRootOnce sync.Once
+ // scanGoPathOnce guards calling scanGoPath (for $GOPATH)
+ scanGoPathOnce sync.Once
+
+ // populateIgnoreOnce guards calling populateIgnore
+ populateIgnoreOnce sync.Once
+ ignoredDirs []os.FileInfo
+
+ dirScanMu sync.RWMutex
+ dirScan map[string]*pkg // abs dir path => *pkg
+)
+
type pkg struct {
- importpath string // full pkg import path, e.g. "net/http"
- dir string // absolute file path to pkg directory e.g. "/usr/lib/go/src/fmt"
+ dir string // absolute file path to pkg directory ("/usr/lib/go/src/net/http")
+ importPath string // full pkg import path ("net/http", "foo/bar/vendor/a/b")
+ importPathShort string // vendorless import path ("net/http", "a/b")
}
-var pkgIndexOnce sync.Once
+// byImportPathShortLength sorts by the short import path length, breaking ties on the
+// import string itself.
+type byImportPathShortLength []*pkg
+
+func (s byImportPathShortLength) Len() int { return len(s) }
+func (s byImportPathShortLength) Less(i, j int) bool {
+ vi, vj := s[i].importPathShort, s[j].importPathShort
+ return len(vi) < len(vj) || (len(vi) == len(vj) && vi < vj)
-var pkgIndex struct {
- sync.Mutex
- m map[string][]pkg // shortname => []pkg, e.g "http" => "net/http"
}
+func (s byImportPathShortLength) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
// gate is a semaphore for limiting concurrency.
type gate chan struct{}
@@ -184,194 +384,512 @@ type gate chan struct{}
func (g gate) enter() { g <- struct{}{} }
func (g gate) leave() { <-g }
-// fsgate protects the OS & filesystem from too much concurrency.
-// Too much disk I/O -> too many threads -> swapping and bad scheduling.
-var fsgate = make(gate, 8)
-
-func loadPkgIndex() {
- pkgIndex.Lock()
- pkgIndex.m = make(map[string][]pkg)
- pkgIndex.Unlock()
+var visitedSymlinks struct {
+ sync.Mutex
+ m map[string]struct{}
+}
- var wg sync.WaitGroup
- for _, path := range build.Default.SrcDirs() {
- fsgate.enter()
- f, err := os.Open(path)
- if err != nil {
- fsgate.leave()
- fmt.Fprint(os.Stderr, err)
+// guarded by populateIgnoreOnce; populates ignoredDirs.
+func populateIgnore() {
+ for _, srcDir := range build.Default.SrcDirs() {
+ if srcDir == filepath.Join(build.Default.GOROOT, "src") {
continue
}
- children, err := f.Readdir(-1)
- f.Close()
- fsgate.leave()
+ populateIgnoredDirs(srcDir)
+ }
+}
+
+// populateIgnoredDirs reads an optional config file at <path>/.goimportsignore
+// of relative directories to ignore when scanning for go files.
+// The provided path is one of the $GOPATH entries with "src" appended.
+func populateIgnoredDirs(path string) {
+ file := filepath.Join(path, ".goimportsignore")
+ slurp, err := ioutil.ReadFile(file)
+ if Debug {
if err != nil {
- fmt.Fprint(os.Stderr, err)
+ log.Print(err)
+ } else {
+ log.Printf("Read %s", file)
+ }
+ }
+ if err != nil {
+ return
+ }
+ bs := bufio.NewScanner(bytes.NewReader(slurp))
+ for bs.Scan() {
+ line := strings.TrimSpace(bs.Text())
+ if line == "" || strings.HasPrefix(line, "#") {
continue
}
- for _, child := range children {
- if child.IsDir() {
- wg.Add(1)
- go func(path, name string) {
- defer wg.Done()
- loadPkg(&wg, path, name)
- }(path, child.Name())
+ full := filepath.Join(path, line)
+ if fi, err := os.Stat(full); err == nil {
+ ignoredDirs = append(ignoredDirs, fi)
+ if Debug {
+ log.Printf("Directory added to ignore list: %s", full)
}
+ } else if Debug {
+ log.Printf("Error statting entry in .goimportsignore: %v", err)
}
}
- wg.Wait()
}
-func loadPkg(wg *sync.WaitGroup, root, pkgrelpath string) {
- importpath := filepath.ToSlash(pkgrelpath)
- dir := filepath.Join(root, importpath)
+func skipDir(fi os.FileInfo) bool {
+ for _, ignoredDir := range ignoredDirs {
+ if os.SameFile(fi, ignoredDir) {
+ return true
+ }
+ }
+ return false
+}
- fsgate.enter()
- defer fsgate.leave()
- pkgDir, err := os.Open(dir)
+// shouldTraverse reports whether the symlink fi should, found in dir,
+// should be followed. It makes sure symlinks were never visited
+// before to avoid symlink loops.
+func shouldTraverse(dir string, fi os.FileInfo) bool {
+ path := filepath.Join(dir, fi.Name())
+ target, err := filepath.EvalSymlinks(path)
if err != nil {
- return
+ if !os.IsNotExist(err) {
+ fmt.Fprintln(os.Stderr, err)
+ }
+ return false
}
- children, err := pkgDir.Readdir(-1)
- pkgDir.Close()
+ ts, err := os.Stat(target)
if err != nil {
- return
+ fmt.Fprintln(os.Stderr, err)
+ return false
+ }
+ if !ts.IsDir() {
+ return false
+ }
+
+ realParent, err := filepath.EvalSymlinks(dir)
+ if err != nil {
+ fmt.Fprint(os.Stderr, err)
+ return false
}
- // hasGo tracks whether a directory actually appears to be a
- // Go source code directory. If $GOPATH == $HOME, and
- // $HOME/src has lots of other large non-Go projects in it,
- // then the calls to importPathToName below can be expensive.
- hasGo := false
- for _, child := range children {
- // Avoid .foo, _foo, and testdata directory trees.
- name := child.Name()
- if name == "" || name[0] == '.' || name[0] == '_' || name == "testdata" {
+ realPath := filepath.Join(realParent, fi.Name())
+ visitedSymlinks.Lock()
+ defer visitedSymlinks.Unlock()
+ if visitedSymlinks.m == nil {
+ visitedSymlinks.m = make(map[string]struct{})
+ }
+ if _, ok := visitedSymlinks.m[realPath]; ok {
+ return false
+ }
+ visitedSymlinks.m[realPath] = struct{}{}
+ return true
+}
+
+var testHookScanDir = func(dir string) {}
+
+var scanGoRootDone = make(chan struct{}) // closed when scanGoRoot is done
+
+func scanGoRoot() {
+ go func() {
+ scanGoDirs(true)
+ close(scanGoRootDone)
+ }()
+}
+
+func scanGoPath() { scanGoDirs(false) }
+
+func scanGoDirs(goRoot bool) {
+ if Debug {
+ which := "$GOROOT"
+ if !goRoot {
+ which = "$GOPATH"
+ }
+ log.Printf("scanning " + which)
+ defer log.Printf("scanned " + which)
+ }
+ dirScanMu.Lock()
+ if dirScan == nil {
+ dirScan = make(map[string]*pkg)
+ }
+ dirScanMu.Unlock()
+
+ for _, srcDir := range build.Default.SrcDirs() {
+ isGoroot := srcDir == filepath.Join(build.Default.GOROOT, "src")
+ if isGoroot != goRoot {
continue
}
- if strings.HasSuffix(name, ".go") {
- hasGo = true
+ testHookScanDir(srcDir)
+ walkFn := func(path string, typ os.FileMode) error {
+ dir := filepath.Dir(path)
+ if typ.IsRegular() {
+ if dir == srcDir {
+ // Doesn't make sense to have regular files
+ // directly in your $GOPATH/src or $GOROOT/src.
+ return nil
+ }
+ if !strings.HasSuffix(path, ".go") {
+ return nil
+ }
+ dirScanMu.Lock()
+ if _, dup := dirScan[dir]; !dup {
+ importpath := filepath.ToSlash(dir[len(srcDir)+len("/"):])
+ dirScan[dir] = &pkg{
+ importPath: importpath,
+ importPathShort: vendorlessImportPath(importpath),
+ dir: dir,
+ }
+ }
+ dirScanMu.Unlock()
+ return nil
+ }
+ if typ == os.ModeDir {
+ base := filepath.Base(path)
+ if base == "" || base[0] == '.' || base[0] == '_' ||
+ base == "testdata" || base == "node_modules" {
+ return filepath.SkipDir
+ }
+ fi, err := os.Lstat(path)
+ if err == nil && skipDir(fi) {
+ if Debug {
+ log.Printf("skipping directory %q under %s", fi.Name(), dir)
+ }
+ return filepath.SkipDir
+ }
+ return nil
+ }
+ if typ == os.ModeSymlink {
+ base := filepath.Base(path)
+ if strings.HasPrefix(base, ".#") {
+ // Emacs noise.
+ return nil
+ }
+ fi, err := os.Lstat(path)
+ if err != nil {
+ // Just ignore it.
+ return nil
+ }
+ if shouldTraverse(dir, fi) {
+ return traverseLink
+ }
+ }
+ return nil
}
- if child.IsDir() {
- wg.Add(1)
- go func(root, name string) {
- defer wg.Done()
- loadPkg(wg, root, name)
- }(root, filepath.Join(importpath, name))
+ if err := fastWalk(srcDir, walkFn); err != nil {
+ log.Printf("goimports: scanning directory %v: %v", srcDir, err)
}
}
- if hasGo {
- shortName := importPathToName(importpath)
- pkgIndex.Lock()
- pkgIndex.m[shortName] = append(pkgIndex.m[shortName], pkg{
- importpath: importpath,
- dir: dir,
- })
- pkgIndex.Unlock()
- }
+}
+// vendorlessImportPath returns the devendorized version of the provided import path.
+// e.g. "foo/bar/vendor/a/b" => "a/b"
+func vendorlessImportPath(ipath string) string {
+ // Devendorize for use in import statement.
+ if i := strings.LastIndex(ipath, "/vendor/"); i >= 0 {
+ return ipath[i+len("/vendor/"):]
+ }
+ if strings.HasPrefix(ipath, "vendor/") {
+ return ipath[len("vendor/"):]
+ }
+ return ipath
}
-// loadExports returns a list exports for a package.
-var loadExports = loadExportsGoPath
+// loadExports returns the set of exported symbols in the package at dir.
+// It returns nil on error or if the package name in dir does not match expectPackage.
+var loadExports func(expectPackage, dir string) map[string]bool = loadExportsGoPath
-func loadExportsGoPath(dir string) map[string]bool {
+func loadExportsGoPath(expectPackage, dir string) map[string]bool {
+ if Debug {
+ log.Printf("loading exports in dir %s (seeking package %s)", dir, expectPackage)
+ }
exports := make(map[string]bool)
- buildPkg, err := build.ImportDir(dir, 0)
- if err != nil {
- if strings.Contains(err.Error(), "no buildable Go source files in") {
- return nil
+
+ ctx := build.Default
+
+ // ReadDir is like ioutil.ReadDir, but only returns *.go files
+ // and filters out _test.go files since they're not relevant
+ // and only slow things down.
+ ctx.ReadDir = func(dir string) (notTests []os.FileInfo, err error) {
+ all, err := ioutil.ReadDir(dir)
+ if err != nil {
+ return nil, err
}
- fmt.Fprintf(os.Stderr, "could not import %q: %v\n", dir, err)
+ notTests = all[:0]
+ for _, fi := range all {
+ name := fi.Name()
+ if strings.HasSuffix(name, ".go") && !strings.HasSuffix(name, "_test.go") {
+ notTests = append(notTests, fi)
+ }
+ }
+ return notTests, nil
+ }
+
+ files, err := ctx.ReadDir(dir)
+ if err != nil {
+ log.Print(err)
return nil
}
+
fset := token.NewFileSet()
- for _, files := range [...][]string{buildPkg.GoFiles, buildPkg.CgoFiles} {
- for _, file := range files {
- f, err := parser.ParseFile(fset, filepath.Join(dir, file), nil, 0)
- if err != nil {
- fmt.Fprintf(os.Stderr, "could not parse %q: %v\n", file, err)
- continue
+
+ for _, fi := range files {
+ match, err := ctx.MatchFile(dir, fi.Name())
+ if err != nil || !match {
+ continue
+ }
+ fullFile := filepath.Join(dir, fi.Name())
+ f, err := parser.ParseFile(fset, fullFile, nil, 0)
+ if err != nil {
+ if Debug {
+ log.Printf("Parsing %s: %v", fullFile, err)
}
- for name := range f.Scope.Objects {
- if ast.IsExported(name) {
- exports[name] = true
- }
+ return nil
+ }
+ pkgName := f.Name.Name
+ if pkgName == "documentation" {
+ // Special case from go/build.ImportDir, not
+ // handled by ctx.MatchFile.
+ continue
+ }
+ if pkgName != expectPackage {
+ if Debug {
+ log.Printf("scan of dir %v is not expected package %v (actually %v)", dir, expectPackage, pkgName)
+ }
+ return nil
+ }
+ for name := range f.Scope.Objects {
+ if ast.IsExported(name) {
+ exports[name] = true
}
}
}
+
+ if Debug {
+ exportList := make([]string, 0, len(exports))
+ for k := range exports {
+ exportList = append(exportList, k)
+ }
+ sort.Strings(exportList)
+ log.Printf("loaded exports in dir %v (package %v): %v", dir, expectPackage, strings.Join(exportList, ", "))
+ }
return exports
}
// findImport searches for a package with the given symbols.
-// If no package is found, findImport returns "".
-// Declared as a variable rather than a function so goimports can be easily
-// extended by adding a file with an init function.
-var findImport = findImportGoPath
+// If no package is found, findImport returns ("", false, nil)
+//
+// This is declared as a variable rather than a function so goimports
+// can be easily extended by adding a file with an init function.
+//
+// The rename value tells goimports whether to use the package name as
+// a local qualifier in an import. For example, if findImports("pkg",
+// "X") returns ("foo/bar", rename=true), then goimports adds the
+// import line:
+// import pkg "foo/bar"
+// to satisfy uses of pkg.X in the file.
+var findImport func(pkgName string, symbols map[string]bool, filename string) (foundPkg string, rename bool, err error) = findImportGoPath
+
+// findImportGoPath is the normal implementation of findImport.
+// (Some companies have their own internally.)
+func findImportGoPath(pkgName string, symbols map[string]bool, filename string) (foundPkg string, rename bool, err error) {
+ if inTests {
+ testMu.RLock()
+ defer testMu.RUnlock()
+ }
-func findImportGoPath(pkgName string, symbols map[string]bool, filename string) (string, bool, error) {
// Fast path for the standard library.
// In the common case we hopefully never have to scan the GOPATH, which can
// be slow with moving disks.
if pkg, rename, ok := findImportStdlib(pkgName, symbols); ok {
return pkg, rename, nil
}
+ if pkgName == "rand" && symbols["Read"] {
+ // Special-case rand.Read.
+ //
+ // If findImportStdlib didn't find it above, don't go
+ // searching for it, lest it find and pick math/rand
+ // in GOROOT (new as of Go 1.6)
+ //
+ // crypto/rand is the safer choice.
+ return "", false, nil
+ }
// TODO(sameer): look at the import lines for other Go files in the
// local directory, since the user is likely to import the same packages
// in the current Go file. Return rename=true when the other Go files
// use a renamed package that's also used in the current file.
- pkgIndexOnce.Do(loadPkgIndex)
+ // Read all the $GOPATH/src/.goimportsignore files before scanning directories.
+ populateIgnoreOnce.Do(populateIgnore)
+
+ // Start scanning the $GOROOT asynchronously, then run the
+ // GOPATH scan synchronously if needed, and then wait for the
+ // $GOROOT to finish.
+ //
+ // TODO(bradfitz): run each $GOPATH entry async. But nobody
+ // really has more than one anyway, so low priority.
+ scanGoRootOnce.Do(scanGoRoot) // async
+ if !fileInDir(filename, build.Default.GOROOT) {
+ scanGoPathOnce.Do(scanGoPath) // blocking
+ }
+ <-scanGoRootDone
- // Collect exports for packages with matching names.
- var (
- wg sync.WaitGroup
- mu sync.Mutex
- shortest string
- )
- pkgIndex.Lock()
- for _, pkg := range pkgIndex.m[pkgName] {
- if !canUse(filename, pkg.dir) {
- continue
+ // Find candidate packages, looking only at their directory names first.
+ var candidates []*pkg
+ for _, pkg := range dirScan {
+ if pkgIsCandidate(filename, pkgName, pkg) {
+ candidates = append(candidates, pkg)
+ }
+ }
+
+ // Sort the candidates by their import package length,
+ // assuming that shorter package names are better than long
+ // ones. Note that this sorts by the de-vendored name, so
+ // there's no "penalty" for vendoring.
+ sort.Sort(byImportPathShortLength(candidates))
+ if Debug {
+ for i, pkg := range candidates {
+ log.Printf("%s candidate %d/%d: %v", pkgName, i+1, len(candidates), pkg.importPathShort)
}
- wg.Add(1)
- go func(importpath, dir string) {
- defer wg.Done()
- exports := loadExports(dir)
- if exports == nil {
+ }
+
+ // Collect exports for packages with matching names.
+
+ done := make(chan struct{}) // closed when we find the answer
+ defer close(done)
+
+ rescv := make([]chan *pkg, len(candidates))
+ for i := range candidates {
+ rescv[i] = make(chan *pkg)
+ }
+ const maxConcurrentPackageImport = 4
+ loadExportsSem := make(chan struct{}, maxConcurrentPackageImport)
+
+ go func() {
+ for i, pkg := range candidates {
+ select {
+ case loadExportsSem <- struct{}{}:
+ select {
+ case <-done:
+ default:
+ }
+ case <-done:
return
}
- // If it doesn't have the right symbols, stop.
- for symbol := range symbols {
- if !exports[symbol] {
- return
+ pkg := pkg
+ resc := rescv[i]
+ go func() {
+ if inTests {
+ testMu.RLock()
+ defer testMu.RUnlock()
}
- }
+ defer func() { <-loadExportsSem }()
+ exports := loadExports(pkgName, pkg.dir)
+
+ // If it doesn't have the right
+ // symbols, send nil to mean no match.
+ for symbol := range symbols {
+ if !exports[symbol] {
+ pkg = nil
+ break
+ }
+ }
+ select {
+ case resc <- pkg:
+ case <-done:
+ }
+ }()
+ }
+ }()
+ for _, resc := range rescv {
+ pkg := <-resc
+ if pkg == nil {
+ continue
+ }
+ // If the package name in the source doesn't match the import path's base,
+ // return true so the rewriter adds a name (import foo "github.com/bar/go-foo")
+ needsRename := path.Base(pkg.importPath) != pkgName
+ return pkg.importPathShort, needsRename, nil
+ }
+ return "", false, nil
+}
- // Devendorize for use in import statement.
- if i := strings.LastIndex(importpath, "/vendor/"); i >= 0 {
- importpath = importpath[i+len("/vendor/"):]
- } else if strings.HasPrefix(importpath, "vendor/") {
- importpath = importpath[len("vendor/"):]
- }
+// pkgIsCandidate reports whether pkg is a candidate for satisfying the
+// finding which package pkgIdent in the file named by filename is trying
+// to refer to.
+//
+// This check is purely lexical and is meant to be as fast as possible
+// because it's run over all $GOPATH directories to filter out poor
+// candidates in order to limit the CPU and I/O later parsing the
+// exports in candidate packages.
+//
+// filename is the file being formatted.
+// pkgIdent is the package being searched for, like "client" (if
+// searching for "client.New")
+func pkgIsCandidate(filename, pkgIdent string, pkg *pkg) bool {
+ // Check "internal" and "vendor" visibility:
+ if !canUse(filename, pkg.dir) {
+ return false
+ }
- // Save as the answer.
- // If there are multiple candidates, the shortest wins,
- // to prefer "bytes" over "github.com/foo/bytes".
- mu.Lock()
- if shortest == "" || len(importpath) < len(shortest) || len(importpath) == len(shortest) && importpath < shortest {
- shortest = importpath
- }
- mu.Unlock()
- }(pkg.importpath, pkg.dir)
+ // Speed optimization to minimize disk I/O:
+ // the last two components on disk must contain the
+ // package name somewhere.
+ //
+ // This permits mismatch naming like directory
+ // "go-foo" being package "foo", or "pkg.v3" being "pkg",
+ // or directory "google.golang.org/api/cloudbilling/v1"
+ // being package "cloudbilling", but doesn't
+ // permit a directory "foo" to be package
+ // "bar", which is strongly discouraged
+ // anyway. There's no reason goimports needs
+ // to be slow just to accomodate that.
+ lastTwo := lastTwoComponents(pkg.importPathShort)
+ if strings.Contains(lastTwo, pkgIdent) {
+ return true
+ }
+ if hasHyphenOrUpperASCII(lastTwo) && !hasHyphenOrUpperASCII(pkgIdent) {
+ lastTwo = lowerASCIIAndRemoveHyphen(lastTwo)
+ if strings.Contains(lastTwo, pkgIdent) {
+ return true
+ }
}
- pkgIndex.Unlock()
- wg.Wait()
- return shortest, false, nil
+ return false
+}
+
+func hasHyphenOrUpperASCII(s string) bool {
+ for i := 0; i < len(s); i++ {
+ b := s[i]
+ if b == '-' || ('A' <= b && b <= 'Z') {
+ return true
+ }
+ }
+ return false
}
+func lowerASCIIAndRemoveHyphen(s string) (ret string) {
+ buf := make([]byte, 0, len(s))
+ for i := 0; i < len(s); i++ {
+ b := s[i]
+ switch {
+ case b == '-':
+ continue
+ case 'A' <= b && b <= 'Z':
+ buf = append(buf, b+('a'-'A'))
+ default:
+ buf = append(buf, b)
+ }
+ }
+ return string(buf)
+}
+
+// canUse reports whether the package in dir is usable from filename,
+// respecting the Go "internal" and "vendor" visibility rules.
func canUse(filename, dir string) bool {
+ // Fast path check, before any allocations. If it doesn't contain vendor
+ // or internal, it's not tricky:
+ // Note that this can false-negative on directories like "notinternal",
+ // but we check it correctly below. This is just a fast path.
+ if !strings.Contains(dir, "vendor") && !strings.Contains(dir, "internal") {
+ return true
+ }
+
dirSlash := filepath.ToSlash(dir)
if !strings.Contains(dirSlash, "/vendor/") && !strings.Contains(dirSlash, "/internal/") && !strings.HasSuffix(dirSlash, "/internal") {
return true
@@ -382,11 +900,15 @@ func canUse(filename, dir string) bool {
// or bar/vendor or bar/internal.
// After stripping all the leading ../, the only okay place to see vendor or internal
// is at the very beginning of the path.
- abs, err := filepath.Abs(filename)
+ absfile, err := filepath.Abs(filename)
if err != nil {
return false
}
- rel, err := filepath.Rel(abs, dir)
+ absdir, err := filepath.Abs(dir)
+ if err != nil {
+ return false
+ }
+ rel, err := filepath.Rel(absfile, absdir)
if err != nil {
return false
}
@@ -397,6 +919,21 @@ func canUse(filename, dir string) bool {
return !strings.Contains(relSlash, "/vendor/") && !strings.Contains(relSlash, "/internal/") && !strings.HasSuffix(relSlash, "/internal")
}
+// lastTwoComponents returns at most the last two path components
+// of v, using either / or \ as the path separator.
+func lastTwoComponents(v string) string {
+ nslash := 0
+ for i := len(v) - 1; i >= 0; i-- {
+ if v[i] == '/' || v[i] == '\\' {
+ nslash++
+ if nslash == 2 {
+ return v[i:]
+ }
+ }
+ }
+ return v
+}
+
type visitFn func(node ast.Node) ast.Visitor
func (fn visitFn) Visit(node ast.Node) ast.Visitor {
@@ -405,8 +942,12 @@ func (fn visitFn) Visit(node ast.Node) ast.Visitor {
func findImportStdlib(shortPkg string, symbols map[string]bool) (importPath string, rename, ok bool) {
for symbol := range symbols {
- path := stdlib[shortPkg+"."+symbol]
+ key := shortPkg + "." + symbol
+ path := stdlib[key]
if path == "" {
+ if key == "rand.Read" {
+ continue
+ }
return "", false, false
}
if importPath != "" && importPath != path {
@@ -415,5 +956,20 @@ func findImportStdlib(shortPkg string, symbols map[string]bool) (importPath stri
}
importPath = path
}
+ if importPath == "" && shortPkg == "rand" && symbols["Read"] {
+ return "crypto/rand", false, true
+ }
return importPath, false, importPath != ""
}
+
+// fileInDir reports whether the provided file path looks like
+// it's in dir. (without hitting the filesystem)
+func fileInDir(file, dir string) bool {
+ rest := strings.TrimPrefix(file, dir)
+ if len(rest) == len(file) {
+ // dir is not a prefix of file.
+ return false
+ }
+ // Check for boundary: either nothing (file == dir), or a slash.
+ return len(rest) == 0 || rest[0] == '/' || rest[0] == '\\'
+}
diff --git a/Godeps/_workspace/src/golang.org/x/tools/imports/imports.go b/Godeps/_workspace/src/golang.org/x/tools/imports/imports.go
index 099684ae6..7c6c1b653 100644
--- a/Godeps/_workspace/src/golang.org/x/tools/imports/imports.go
+++ b/Godeps/_workspace/src/golang.org/x/tools/imports/imports.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+//go:generate go run mkstdlib.go
+
// Package imports implements a Go pretty-printer (like package "go/format")
// that also adds or removes import statements as necessary.
package imports
@@ -31,6 +33,8 @@ type Options struct {
Comments bool // Print comments (true if nil *Options provided)
TabIndent bool // Use tabs for indent (true if nil *Options provided)
TabWidth int // Tab width (8 if nil *Options provided)
+
+ FormatOnly bool // Disable the insertion and deletion of imports
}
// Process formats and adjusts imports for the provided file.
@@ -50,9 +54,11 @@ func Process(filename string, src []byte, opt *Options) ([]byte, error) {
return nil, err
}
- _, err = fixImports(fileSet, file, filename)
- if err != nil {
- return nil, err
+ if !opt.FormatOnly {
+ _, err = fixImports(fileSet, file, filename)
+ if err != nil {
+ return nil, err
+ }
}
sortImports(fileSet, file)
diff --git a/Godeps/_workspace/src/golang.org/x/tools/imports/mkstdlib.go b/Godeps/_workspace/src/golang.org/x/tools/imports/mkstdlib.go
index e2dca7600..1e559e9f5 100644
--- a/Godeps/_workspace/src/golang.org/x/tools/imports/mkstdlib.go
+++ b/Godeps/_workspace/src/golang.org/x/tools/imports/mkstdlib.go
@@ -11,6 +11,7 @@ import (
"fmt"
"go/format"
"io"
+ "io/ioutil"
"log"
"os"
"path"
@@ -49,6 +50,8 @@ func main() {
mustOpen(api("go1.3.txt")),
mustOpen(api("go1.4.txt")),
mustOpen(api("go1.5.txt")),
+ mustOpen(api("go1.6.txt")),
+ mustOpen(api("go1.7.txt")),
)
sc := bufio.NewScanner(f)
fullImport := map[string]string{} // "zip.NewReader" => "archive/zip"
@@ -84,10 +87,17 @@ func main() {
outf("\t%q: %q,\n", key, fullImport[key])
}
}
+ outf("\n")
+ for _, sym := range [...]string{"Alignof", "ArbitraryType", "Offsetof", "Pointer", "Sizeof"} {
+ outf("\t%q: %q,\n", "unsafe."+sym, "unsafe")
+ }
outf("}\n")
fmtbuf, err := format.Source(buf.Bytes())
if err != nil {
log.Fatal(err)
}
- os.Stdout.Write(fmtbuf)
+ err = ioutil.WriteFile("zstdlib.go", fmtbuf, 0666)
+ if err != nil {
+ log.Fatal(err)
+ }
}
diff --git a/Godeps/_workspace/src/golang.org/x/tools/imports/zstdlib.go b/Godeps/_workspace/src/golang.org/x/tools/imports/zstdlib.go
index 39eb3c74b..28835da03 100644
--- a/Godeps/_workspace/src/golang.org/x/tools/imports/zstdlib.go
+++ b/Godeps/_workspace/src/golang.org/x/tools/imports/zstdlib.go
@@ -16,6 +16,10 @@ var stdlib = map[string]string{
"ascii85.NewDecoder": "encoding/ascii85",
"ascii85.NewEncoder": "encoding/ascii85",
"asn1.BitString": "encoding/asn1",
+ "asn1.ClassApplication": "encoding/asn1",
+ "asn1.ClassContextSpecific": "encoding/asn1",
+ "asn1.ClassPrivate": "encoding/asn1",
+ "asn1.ClassUniversal": "encoding/asn1",
"asn1.Enumerated": "encoding/asn1",
"asn1.Flag": "encoding/asn1",
"asn1.Marshal": "encoding/asn1",
@@ -24,6 +28,21 @@ var stdlib = map[string]string{
"asn1.RawValue": "encoding/asn1",
"asn1.StructuralError": "encoding/asn1",
"asn1.SyntaxError": "encoding/asn1",
+ "asn1.TagBitString": "encoding/asn1",
+ "asn1.TagBoolean": "encoding/asn1",
+ "asn1.TagEnum": "encoding/asn1",
+ "asn1.TagGeneralString": "encoding/asn1",
+ "asn1.TagGeneralizedTime": "encoding/asn1",
+ "asn1.TagIA5String": "encoding/asn1",
+ "asn1.TagInteger": "encoding/asn1",
+ "asn1.TagOID": "encoding/asn1",
+ "asn1.TagOctetString": "encoding/asn1",
+ "asn1.TagPrintableString": "encoding/asn1",
+ "asn1.TagSequence": "encoding/asn1",
+ "asn1.TagSet": "encoding/asn1",
+ "asn1.TagT61String": "encoding/asn1",
+ "asn1.TagUTCTime": "encoding/asn1",
+ "asn1.TagUTF8String": "encoding/asn1",
"asn1.Unmarshal": "encoding/asn1",
"asn1.UnmarshalWithParams": "encoding/asn1",
"ast.ArrayType": "go/ast",
@@ -212,6 +231,7 @@ var stdlib = map[string]string{
"binary.Write": "encoding/binary",
"bufio.ErrAdvanceTooFar": "bufio",
"bufio.ErrBufferFull": "bufio",
+ "bufio.ErrFinalToken": "bufio",
"bufio.ErrInvalidUnreadByte": "bufio",
"bufio.ErrInvalidUnreadRune": "bufio",
"bufio.ErrNegativeAdvance": "bufio",
@@ -238,6 +258,7 @@ var stdlib = map[string]string{
"build.Context": "go/build",
"build.Default": "go/build",
"build.FindOnly": "go/build",
+ "build.IgnoreVendor": "go/build",
"build.Import": "go/build",
"build.ImportComment": "go/build",
"build.ImportDir": "go/build",
@@ -250,6 +271,8 @@ var stdlib = map[string]string{
"bytes.Buffer": "bytes",
"bytes.Compare": "bytes",
"bytes.Contains": "bytes",
+ "bytes.ContainsAny": "bytes",
+ "bytes.ContainsRune": "bytes",
"bytes.Count": "bytes",
"bytes.Equal": "bytes",
"bytes.EqualFold": "bytes",
@@ -363,6 +386,8 @@ var stdlib = map[string]string{
"color.NRGBA64": "image/color",
"color.NRGBA64Model": "image/color",
"color.NRGBAModel": "image/color",
+ "color.NYCbCrA": "image/color",
+ "color.NYCbCrAModel": "image/color",
"color.Opaque": "image/color",
"color.Palette": "image/color",
"color.RGBA": "image/color",
@@ -406,9 +431,22 @@ var stdlib = map[string]string{
"constant.Sign": "go/constant",
"constant.String": "go/constant",
"constant.StringVal": "go/constant",
+ "constant.ToComplex": "go/constant",
+ "constant.ToFloat": "go/constant",
+ "constant.ToInt": "go/constant",
"constant.Uint64Val": "go/constant",
"constant.UnaryOp": "go/constant",
"constant.Unknown": "go/constant",
+ "context.Background": "context",
+ "context.CancelFunc": "context",
+ "context.Canceled": "context",
+ "context.Context": "context",
+ "context.DeadlineExceeded": "context",
+ "context.TODO": "context",
+ "context.WithCancel": "context",
+ "context.WithDeadline": "context",
+ "context.WithTimeout": "context",
+ "context.WithValue": "context",
"cookiejar.Jar": "net/http/cookiejar",
"cookiejar.New": "net/http/cookiejar",
"cookiejar.Options": "net/http/cookiejar",
@@ -473,6 +511,7 @@ var stdlib = map[string]string{
"debug.SetMaxStack": "runtime/debug",
"debug.SetMaxThreads": "runtime/debug",
"debug.SetPanicOnFault": "runtime/debug",
+ "debug.SetTraceback": "runtime/debug",
"debug.Stack": "runtime/debug",
"debug.WriteHeapDump": "runtime/debug",
"des.BlockSize": "crypto/des",
@@ -634,6 +673,7 @@ var stdlib = map[string]string{
"dwarf.ClassReferenceSig": "debug/dwarf",
"dwarf.ClassString": "debug/dwarf",
"dwarf.ClassStringAlt": "debug/dwarf",
+ "dwarf.ClassUnknown": "debug/dwarf",
"dwarf.CommonType": "debug/dwarf",
"dwarf.ComplexType": "debug/dwarf",
"dwarf.Data": "debug/dwarf",
@@ -732,7 +772,15 @@ var stdlib = map[string]string{
"ecdsa.Sign": "crypto/ecdsa",
"ecdsa.Verify": "crypto/ecdsa",
"elf.ARM_MAGIC_TRAMP_NUMBER": "debug/elf",
+ "elf.COMPRESS_HIOS": "debug/elf",
+ "elf.COMPRESS_HIPROC": "debug/elf",
+ "elf.COMPRESS_LOOS": "debug/elf",
+ "elf.COMPRESS_LOPROC": "debug/elf",
+ "elf.COMPRESS_ZLIB": "debug/elf",
+ "elf.Chdr32": "debug/elf",
+ "elf.Chdr64": "debug/elf",
"elf.Class": "debug/elf",
+ "elf.CompressionType": "debug/elf",
"elf.DF_BIND_NOW": "debug/elf",
"elf.DF_ORIGIN": "debug/elf",
"elf.DF_STATIC_TLS": "debug/elf",
@@ -944,6 +992,68 @@ var stdlib = map[string]string{
"elf.R_386_TLS_LE_32": "debug/elf",
"elf.R_386_TLS_TPOFF": "debug/elf",
"elf.R_386_TLS_TPOFF32": "debug/elf",
+ "elf.R_390": "debug/elf",
+ "elf.R_390_12": "debug/elf",
+ "elf.R_390_16": "debug/elf",
+ "elf.R_390_20": "debug/elf",
+ "elf.R_390_32": "debug/elf",
+ "elf.R_390_64": "debug/elf",
+ "elf.R_390_8": "debug/elf",
+ "elf.R_390_COPY": "debug/elf",
+ "elf.R_390_GLOB_DAT": "debug/elf",
+ "elf.R_390_GOT12": "debug/elf",
+ "elf.R_390_GOT16": "debug/elf",
+ "elf.R_390_GOT20": "debug/elf",
+ "elf.R_390_GOT32": "debug/elf",
+ "elf.R_390_GOT64": "debug/elf",
+ "elf.R_390_GOTENT": "debug/elf",
+ "elf.R_390_GOTOFF": "debug/elf",
+ "elf.R_390_GOTOFF16": "debug/elf",
+ "elf.R_390_GOTOFF64": "debug/elf",
+ "elf.R_390_GOTPC": "debug/elf",
+ "elf.R_390_GOTPCDBL": "debug/elf",
+ "elf.R_390_GOTPLT12": "debug/elf",
+ "elf.R_390_GOTPLT16": "debug/elf",
+ "elf.R_390_GOTPLT20": "debug/elf",
+ "elf.R_390_GOTPLT32": "debug/elf",
+ "elf.R_390_GOTPLT64": "debug/elf",
+ "elf.R_390_GOTPLTENT": "debug/elf",
+ "elf.R_390_GOTPLTOFF16": "debug/elf",
+ "elf.R_390_GOTPLTOFF32": "debug/elf",
+ "elf.R_390_GOTPLTOFF64": "debug/elf",
+ "elf.R_390_JMP_SLOT": "debug/elf",
+ "elf.R_390_NONE": "debug/elf",
+ "elf.R_390_PC16": "debug/elf",
+ "elf.R_390_PC16DBL": "debug/elf",
+ "elf.R_390_PC32": "debug/elf",
+ "elf.R_390_PC32DBL": "debug/elf",
+ "elf.R_390_PC64": "debug/elf",
+ "elf.R_390_PLT16DBL": "debug/elf",
+ "elf.R_390_PLT32": "debug/elf",
+ "elf.R_390_PLT32DBL": "debug/elf",
+ "elf.R_390_PLT64": "debug/elf",
+ "elf.R_390_RELATIVE": "debug/elf",
+ "elf.R_390_TLS_DTPMOD": "debug/elf",
+ "elf.R_390_TLS_DTPOFF": "debug/elf",
+ "elf.R_390_TLS_GD32": "debug/elf",
+ "elf.R_390_TLS_GD64": "debug/elf",
+ "elf.R_390_TLS_GDCALL": "debug/elf",
+ "elf.R_390_TLS_GOTIE12": "debug/elf",
+ "elf.R_390_TLS_GOTIE20": "debug/elf",
+ "elf.R_390_TLS_GOTIE32": "debug/elf",
+ "elf.R_390_TLS_GOTIE64": "debug/elf",
+ "elf.R_390_TLS_IE32": "debug/elf",
+ "elf.R_390_TLS_IE64": "debug/elf",
+ "elf.R_390_TLS_IEENT": "debug/elf",
+ "elf.R_390_TLS_LDCALL": "debug/elf",
+ "elf.R_390_TLS_LDM32": "debug/elf",
+ "elf.R_390_TLS_LDM64": "debug/elf",
+ "elf.R_390_TLS_LDO32": "debug/elf",
+ "elf.R_390_TLS_LDO64": "debug/elf",
+ "elf.R_390_TLS_LE32": "debug/elf",
+ "elf.R_390_TLS_LE64": "debug/elf",
+ "elf.R_390_TLS_LOAD": "debug/elf",
+ "elf.R_390_TLS_TPOFF": "debug/elf",
"elf.R_AARCH64": "debug/elf",
"elf.R_AARCH64_ABS16": "debug/elf",
"elf.R_AARCH64_ABS32": "debug/elf",
@@ -1129,6 +1239,55 @@ var stdlib = map[string]string{
"elf.R_ARM_XPC25": "debug/elf",
"elf.R_INFO": "debug/elf",
"elf.R_INFO32": "debug/elf",
+ "elf.R_MIPS": "debug/elf",
+ "elf.R_MIPS_16": "debug/elf",
+ "elf.R_MIPS_26": "debug/elf",
+ "elf.R_MIPS_32": "debug/elf",
+ "elf.R_MIPS_64": "debug/elf",
+ "elf.R_MIPS_ADD_IMMEDIATE": "debug/elf",
+ "elf.R_MIPS_CALL16": "debug/elf",
+ "elf.R_MIPS_CALL_HI16": "debug/elf",
+ "elf.R_MIPS_CALL_LO16": "debug/elf",
+ "elf.R_MIPS_DELETE": "debug/elf",
+ "elf.R_MIPS_GOT16": "debug/elf",
+ "elf.R_MIPS_GOT_DISP": "debug/elf",
+ "elf.R_MIPS_GOT_HI16": "debug/elf",
+ "elf.R_MIPS_GOT_LO16": "debug/elf",
+ "elf.R_MIPS_GOT_OFST": "debug/elf",
+ "elf.R_MIPS_GOT_PAGE": "debug/elf",
+ "elf.R_MIPS_GPREL16": "debug/elf",
+ "elf.R_MIPS_GPREL32": "debug/elf",
+ "elf.R_MIPS_HI16": "debug/elf",
+ "elf.R_MIPS_HIGHER": "debug/elf",
+ "elf.R_MIPS_HIGHEST": "debug/elf",
+ "elf.R_MIPS_INSERT_A": "debug/elf",
+ "elf.R_MIPS_INSERT_B": "debug/elf",
+ "elf.R_MIPS_JALR": "debug/elf",
+ "elf.R_MIPS_LITERAL": "debug/elf",
+ "elf.R_MIPS_LO16": "debug/elf",
+ "elf.R_MIPS_NONE": "debug/elf",
+ "elf.R_MIPS_PC16": "debug/elf",
+ "elf.R_MIPS_PJUMP": "debug/elf",
+ "elf.R_MIPS_REL16": "debug/elf",
+ "elf.R_MIPS_REL32": "debug/elf",
+ "elf.R_MIPS_RELGOT": "debug/elf",
+ "elf.R_MIPS_SCN_DISP": "debug/elf",
+ "elf.R_MIPS_SHIFT5": "debug/elf",
+ "elf.R_MIPS_SHIFT6": "debug/elf",
+ "elf.R_MIPS_SUB": "debug/elf",
+ "elf.R_MIPS_TLS_DTPMOD32": "debug/elf",
+ "elf.R_MIPS_TLS_DTPMOD64": "debug/elf",
+ "elf.R_MIPS_TLS_DTPREL32": "debug/elf",
+ "elf.R_MIPS_TLS_DTPREL64": "debug/elf",
+ "elf.R_MIPS_TLS_DTPREL_HI16": "debug/elf",
+ "elf.R_MIPS_TLS_DTPREL_LO16": "debug/elf",
+ "elf.R_MIPS_TLS_GD": "debug/elf",
+ "elf.R_MIPS_TLS_GOTTPREL": "debug/elf",
+ "elf.R_MIPS_TLS_LDM": "debug/elf",
+ "elf.R_MIPS_TLS_TPREL32": "debug/elf",
+ "elf.R_MIPS_TLS_TPREL64": "debug/elf",
+ "elf.R_MIPS_TLS_TPREL_HI16": "debug/elf",
+ "elf.R_MIPS_TLS_TPREL_LO16": "debug/elf",
"elf.R_PPC": "debug/elf",
"elf.R_PPC64": "debug/elf",
"elf.R_PPC64_ADDR14": "debug/elf",
@@ -1382,6 +1541,7 @@ var stdlib = map[string]string{
"elf.Rela32": "debug/elf",
"elf.Rela64": "debug/elf",
"elf.SHF_ALLOC": "debug/elf",
+ "elf.SHF_COMPRESSED": "debug/elf",
"elf.SHF_EXECINSTR": "debug/elf",
"elf.SHF_GROUP": "debug/elf",
"elf.SHF_INFO_LINK": "debug/elf",
@@ -1491,6 +1651,7 @@ var stdlib = map[string]string{
"errors.New": "errors",
"exec.Cmd": "os/exec",
"exec.Command": "os/exec",
+ "exec.CommandContext": "os/exec",
"exec.ErrNotFound": "os/exec",
"exec.Error": "os/exec",
"exec.ExitError": "os/exec",
@@ -1580,6 +1741,7 @@ var stdlib = map[string]string{
"flate.BestSpeed": "compress/flate",
"flate.CorruptInputError": "compress/flate",
"flate.DefaultCompression": "compress/flate",
+ "flate.HuffmanOnly": "compress/flate",
"flate.InternalError": "compress/flate",
"flate.NewReader": "compress/flate",
"flate.NewReaderDict": "compress/flate",
@@ -1714,7 +1876,9 @@ var stdlib = map[string]string{
"http.ErrNotMultipart": "net/http",
"http.ErrNotSupported": "net/http",
"http.ErrShortBody": "net/http",
+ "http.ErrSkipAltProtocol": "net/http",
"http.ErrUnexpectedTrailer": "net/http",
+ "http.ErrUseLastResponse": "net/http",
"http.ErrWriteAfterFlush": "net/http",
"http.Error": "net/http",
"http.File": "net/http",
@@ -1731,7 +1895,17 @@ var stdlib = map[string]string{
"http.Hijacker": "net/http",
"http.ListenAndServe": "net/http",
"http.ListenAndServeTLS": "net/http",
+ "http.LocalAddrContextKey": "net/http",
"http.MaxBytesReader": "net/http",
+ "http.MethodConnect": "net/http",
+ "http.MethodDelete": "net/http",
+ "http.MethodGet": "net/http",
+ "http.MethodHead": "net/http",
+ "http.MethodOptions": "net/http",
+ "http.MethodPatch": "net/http",
+ "http.MethodPost": "net/http",
+ "http.MethodPut": "net/http",
+ "http.MethodTrace": "net/http",
"http.NewFileTransport": "net/http",
"http.NewRequest": "net/http",
"http.NewServeMux": "net/http",
@@ -1757,6 +1931,7 @@ var stdlib = map[string]string{
"http.ServeFile": "net/http",
"http.ServeMux": "net/http",
"http.Server": "net/http",
+ "http.ServerContextKey": "net/http",
"http.SetCookie": "net/http",
"http.StateActive": "net/http",
"http.StateClosed": "net/http",
@@ -1764,34 +1939,47 @@ var stdlib = map[string]string{
"http.StateIdle": "net/http",
"http.StateNew": "net/http",
"http.StatusAccepted": "net/http",
+ "http.StatusAlreadyReported": "net/http",
"http.StatusBadGateway": "net/http",
"http.StatusBadRequest": "net/http",
"http.StatusConflict": "net/http",
"http.StatusContinue": "net/http",
"http.StatusCreated": "net/http",
"http.StatusExpectationFailed": "net/http",
+ "http.StatusFailedDependency": "net/http",
"http.StatusForbidden": "net/http",
"http.StatusFound": "net/http",
"http.StatusGatewayTimeout": "net/http",
"http.StatusGone": "net/http",
"http.StatusHTTPVersionNotSupported": "net/http",
+ "http.StatusIMUsed": "net/http",
+ "http.StatusInsufficientStorage": "net/http",
"http.StatusInternalServerError": "net/http",
"http.StatusLengthRequired": "net/http",
+ "http.StatusLocked": "net/http",
+ "http.StatusLoopDetected": "net/http",
"http.StatusMethodNotAllowed": "net/http",
"http.StatusMovedPermanently": "net/http",
+ "http.StatusMultiStatus": "net/http",
"http.StatusMultipleChoices": "net/http",
+ "http.StatusNetworkAuthenticationRequired": "net/http",
"http.StatusNoContent": "net/http",
"http.StatusNonAuthoritativeInfo": "net/http",
"http.StatusNotAcceptable": "net/http",
+ "http.StatusNotExtended": "net/http",
"http.StatusNotFound": "net/http",
"http.StatusNotImplemented": "net/http",
"http.StatusNotModified": "net/http",
"http.StatusOK": "net/http",
"http.StatusPartialContent": "net/http",
"http.StatusPaymentRequired": "net/http",
+ "http.StatusPermanentRedirect": "net/http",
"http.StatusPreconditionFailed": "net/http",
+ "http.StatusPreconditionRequired": "net/http",
+ "http.StatusProcessing": "net/http",
"http.StatusProxyAuthRequired": "net/http",
"http.StatusRequestEntityTooLarge": "net/http",
+ "http.StatusRequestHeaderFieldsTooLarge": "net/http",
"http.StatusRequestTimeout": "net/http",
"http.StatusRequestURITooLong": "net/http",
"http.StatusRequestedRangeNotSatisfiable": "net/http",
@@ -1802,20 +1990,34 @@ var stdlib = map[string]string{
"http.StatusTeapot": "net/http",
"http.StatusTemporaryRedirect": "net/http",
"http.StatusText": "net/http",
+ "http.StatusTooManyRequests": "net/http",
"http.StatusUnauthorized": "net/http",
+ "http.StatusUnavailableForLegalReasons": "net/http",
+ "http.StatusUnprocessableEntity": "net/http",
"http.StatusUnsupportedMediaType": "net/http",
+ "http.StatusUpgradeRequired": "net/http",
"http.StatusUseProxy": "net/http",
+ "http.StatusVariantAlsoNegotiates": "net/http",
"http.StripPrefix": "net/http",
"http.TimeFormat": "net/http",
"http.TimeoutHandler": "net/http",
"http.Transport": "net/http",
"httptest.DefaultRemoteAddr": "net/http/httptest",
"httptest.NewRecorder": "net/http/httptest",
+ "httptest.NewRequest": "net/http/httptest",
"httptest.NewServer": "net/http/httptest",
"httptest.NewTLSServer": "net/http/httptest",
"httptest.NewUnstartedServer": "net/http/httptest",
"httptest.ResponseRecorder": "net/http/httptest",
"httptest.Server": "net/http/httptest",
+ "httptrace.ClientTrace": "net/http/httptrace",
+ "httptrace.ContextClientTrace": "net/http/httptrace",
+ "httptrace.DNSDoneInfo": "net/http/httptrace",
+ "httptrace.DNSStartInfo": "net/http/httptrace",
+ "httptrace.GotConnInfo": "net/http/httptrace",
+ "httptrace.WithClientTrace": "net/http/httptrace",
+ "httptrace.WroteRequestInfo": "net/http/httptrace",
+ "httputil.BufferPool": "net/http/httputil",
"httputil.ClientConn": "net/http/httputil",
"httputil.DumpRequest": "net/http/httputil",
"httputil.DumpRequestOut": "net/http/httputil",
@@ -1845,6 +2047,7 @@ var stdlib = map[string]string{
"image.Image": "image",
"image.NRGBA": "image",
"image.NRGBA64": "image",
+ "image.NYCbCrA": "image",
"image.NewAlpha": "image",
"image.NewAlpha16": "image",
"image.NewCMYK": "image",
@@ -1852,6 +2055,7 @@ var stdlib = map[string]string{
"image.NewGray16": "image",
"image.NewNRGBA": "image",
"image.NewNRGBA64": "image",
+ "image.NewNYCbCrA": "image",
"image.NewPaletted": "image",
"image.NewRGBA": "image",
"image.NewRGBA64": "image",
@@ -1917,6 +2121,9 @@ var stdlib = map[string]string{
"io.RuneReader": "io",
"io.RuneScanner": "io",
"io.SectionReader": "io",
+ "io.SeekCurrent": "io",
+ "io.SeekEnd": "io",
+ "io.SeekStart": "io",
"io.Seeker": "io",
"io.TeeReader": "io",
"io.WriteCloser": "io",
@@ -2549,19 +2756,19 @@ var stdlib = map[string]string{
"rand.Float32": "math/rand",
"rand.Float64": "math/rand",
// "rand.Int" is ambiguous
- "rand.Int31": "math/rand",
- "rand.Int31n": "math/rand",
- "rand.Int63": "math/rand",
- "rand.Int63n": "math/rand",
- "rand.Intn": "math/rand",
- "rand.New": "math/rand",
- "rand.NewSource": "math/rand",
- "rand.NewZipf": "math/rand",
- "rand.NormFloat64": "math/rand",
- "rand.Perm": "math/rand",
- "rand.Prime": "crypto/rand",
- "rand.Rand": "math/rand",
- "rand.Read": "crypto/rand",
+ "rand.Int31": "math/rand",
+ "rand.Int31n": "math/rand",
+ "rand.Int63": "math/rand",
+ "rand.Int63n": "math/rand",
+ "rand.Intn": "math/rand",
+ "rand.New": "math/rand",
+ "rand.NewSource": "math/rand",
+ "rand.NewZipf": "math/rand",
+ "rand.NormFloat64": "math/rand",
+ "rand.Perm": "math/rand",
+ "rand.Prime": "crypto/rand",
+ "rand.Rand": "math/rand",
+ // "rand.Read" is ambiguous
"rand.Reader": "crypto/rand",
"rand.Seed": "math/rand",
"rand.Source": "math/rand",
@@ -2622,6 +2829,7 @@ var stdlib = map[string]string{
"reflect.StringHeader": "reflect",
"reflect.Struct": "reflect",
"reflect.StructField": "reflect",
+ "reflect.StructOf": "reflect",
"reflect.StructTag": "reflect",
"reflect.TypeOf": "reflect",
"reflect.Uint": "reflect",
@@ -2700,8 +2908,11 @@ var stdlib = map[string]string{
"runtime.CPUProfile": "runtime",
"runtime.Caller": "runtime",
"runtime.Callers": "runtime",
+ "runtime.CallersFrames": "runtime",
"runtime.Compiler": "runtime",
"runtime.Error": "runtime",
+ "runtime.Frame": "runtime",
+ "runtime.Frames": "runtime",
"runtime.Func": "runtime",
"runtime.FuncForPC": "runtime",
"runtime.GC": "runtime",
@@ -2712,6 +2923,7 @@ var stdlib = map[string]string{
"runtime.Goexit": "runtime",
"runtime.GoroutineProfile": "runtime",
"runtime.Gosched": "runtime",
+ "runtime.KeepAlive": "runtime",
"runtime.LockOSThread": "runtime",
"runtime.MemProfile": "runtime",
"runtime.MemProfileRate": "runtime",
@@ -2724,6 +2936,7 @@ var stdlib = map[string]string{
"runtime.ReadTrace": "runtime",
"runtime.SetBlockProfileRate": "runtime",
"runtime.SetCPUProfileRate": "runtime",
+ "runtime.SetCgoTraceback": "runtime",
"runtime.SetFinalizer": "runtime",
"runtime.Stack": "runtime",
"runtime.StackRecord": "runtime",
@@ -2837,7 +3050,9 @@ var stdlib = map[string]string{
"strconv.AppendQuote": "strconv",
"strconv.AppendQuoteRune": "strconv",
"strconv.AppendQuoteRuneToASCII": "strconv",
+ "strconv.AppendQuoteRuneToGraphic": "strconv",
"strconv.AppendQuoteToASCII": "strconv",
+ "strconv.AppendQuoteToGraphic": "strconv",
"strconv.AppendUint": "strconv",
"strconv.Atoi": "strconv",
"strconv.CanBackquote": "strconv",
@@ -2848,6 +3063,7 @@ var stdlib = map[string]string{
"strconv.FormatInt": "strconv",
"strconv.FormatUint": "strconv",
"strconv.IntSize": "strconv",
+ "strconv.IsGraphic": "strconv",
"strconv.IsPrint": "strconv",
"strconv.Itoa": "strconv",
"strconv.NumError": "strconv",
@@ -2858,7 +3074,9 @@ var stdlib = map[string]string{
"strconv.Quote": "strconv",
"strconv.QuoteRune": "strconv",
"strconv.QuoteRuneToASCII": "strconv",
+ "strconv.QuoteRuneToGraphic": "strconv",
"strconv.QuoteToASCII": "strconv",
+ "strconv.QuoteToGraphic": "strconv",
"strconv.Unquote": "strconv",
"strconv.UnquoteChar": "strconv",
"strings.Compare": "strings",
@@ -8206,12 +8424,14 @@ var stdlib = map[string]string{
"template.ErrSlashAmbig": "html/template",
"template.Error": "html/template",
"template.ErrorCode": "html/template",
+ "template.ExecError": "text/template",
// "template.FuncMap" is ambiguous
"template.HTML": "html/template",
"template.HTMLAttr": "html/template",
// "template.HTMLEscape" is ambiguous
// "template.HTMLEscapeString" is ambiguous
// "template.HTMLEscaper" is ambiguous
+ // "template.IsTrue" is ambiguous
"template.JS": "html/template",
// "template.JSEscape" is ambiguous
// "template.JSEscapeString" is ambiguous
@@ -8345,6 +8565,11 @@ var stdlib = map[string]string{
"tls.NewLRUClientSessionCache": "crypto/tls",
"tls.NewListener": "crypto/tls",
"tls.NoClientCert": "crypto/tls",
+ "tls.RecordHeaderError": "crypto/tls",
+ "tls.RenegotiateFreelyAsClient": "crypto/tls",
+ "tls.RenegotiateNever": "crypto/tls",
+ "tls.RenegotiateOnceAsClient": "crypto/tls",
+ "tls.RenegotiationSupport": "crypto/tls",
"tls.RequestClientCert": "crypto/tls",
"tls.RequireAndVerifyClientCert": "crypto/tls",
"tls.RequireAnyClientCert": "crypto/tls",
@@ -8363,7 +8588,9 @@ var stdlib = map[string]string{
"tls.TLS_FALLBACK_SCSV": "crypto/tls",
"tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA": "crypto/tls",
"tls.TLS_RSA_WITH_AES_128_CBC_SHA": "crypto/tls",
+ "tls.TLS_RSA_WITH_AES_128_GCM_SHA256": "crypto/tls",
"tls.TLS_RSA_WITH_AES_256_CBC_SHA": "crypto/tls",
+ "tls.TLS_RSA_WITH_AES_256_GCM_SHA384": "crypto/tls",
"tls.TLS_RSA_WITH_RC4_128_SHA": "crypto/tls",
"tls.VerifyClientCertIfGiven": "crypto/tls",
"tls.VersionSSL30": "crypto/tls",
@@ -8494,7 +8721,9 @@ var stdlib = map[string]string{
"types.Id": "go/types",
"types.Identical": "go/types",
"types.Implements": "go/types",
+ "types.ImportMode": "go/types",
"types.Importer": "go/types",
+ "types.ImporterFrom": "go/types",
"types.Info": "go/types",
"types.Initializer": "go/types",
"types.Int": "go/types",
@@ -8593,6 +8822,7 @@ var stdlib = map[string]string{
"types.WriteSignature": "go/types",
"types.WriteType": "go/types",
"unicode.ASCII_Hex_Digit": "unicode",
+ "unicode.Adlam": "unicode",
"unicode.Ahom": "unicode",
"unicode.Anatolian_Hieroglyphs": "unicode",
"unicode.Arabic": "unicode",
@@ -8604,6 +8834,7 @@ var stdlib = map[string]string{
"unicode.Bassa_Vah": "unicode",
"unicode.Batak": "unicode",
"unicode.Bengali": "unicode",
+ "unicode.Bhaiksuki": "unicode",
"unicode.Bidi_Control": "unicode",
"unicode.Bopomofo": "unicode",
"unicode.Brahmi": "unicode",
@@ -8715,6 +8946,7 @@ var stdlib = map[string]string{
"unicode.Malayalam": "unicode",
"unicode.Mandaic": "unicode",
"unicode.Manichaean": "unicode",
+ "unicode.Marchen": "unicode",
"unicode.Mark": "unicode",
"unicode.MaxASCII": "unicode",
"unicode.MaxCase": "unicode",
@@ -8737,6 +8969,7 @@ var stdlib = map[string]string{
"unicode.Nabataean": "unicode",
"unicode.Nd": "unicode",
"unicode.New_Tai_Lue": "unicode",
+ "unicode.Newa": "unicode",
"unicode.Nko": "unicode",
"unicode.Nl": "unicode",
"unicode.No": "unicode",
@@ -8752,6 +8985,7 @@ var stdlib = map[string]string{
"unicode.Old_South_Arabian": "unicode",
"unicode.Old_Turkic": "unicode",
"unicode.Oriya": "unicode",
+ "unicode.Osage": "unicode",
"unicode.Osmanya": "unicode",
"unicode.Other": "unicode",
"unicode.Other_Alphabetic": "unicode",
@@ -8776,6 +9010,7 @@ var stdlib = map[string]string{
"unicode.Phoenician": "unicode",
"unicode.Pi": "unicode",
"unicode.Po": "unicode",
+ "unicode.Prepended_Concatenation_Mark": "unicode",
"unicode.PrintRanges": "unicode",
"unicode.Properties": "unicode",
"unicode.Ps": "unicode",
@@ -8795,6 +9030,7 @@ var stdlib = map[string]string{
"unicode.Saurashtra": "unicode",
"unicode.Sc": "unicode",
"unicode.Scripts": "unicode",
+ "unicode.Sentence_Terminal": "unicode",
"unicode.Sharada": "unicode",
"unicode.Shavian": "unicode",
"unicode.Siddham": "unicode",
@@ -8819,6 +9055,7 @@ var stdlib = map[string]string{
"unicode.Tai_Viet": "unicode",
"unicode.Takri": "unicode",
"unicode.Tamil": "unicode",
+ "unicode.Tangut": "unicode",
"unicode.Telugu": "unicode",
"unicode.Terminal_Punctuation": "unicode",
"unicode.Thaana": "unicode",
@@ -8850,6 +9087,7 @@ var stdlib = map[string]string{
"unicode.Zs": "unicode",
"url.Error": "net/url",
"url.EscapeError": "net/url",
+ "url.InvalidHostError": "net/url",
"url.Parse": "net/url",
"url.ParseQuery": "net/url",
"url.ParseRequestURI": "net/url",
@@ -8861,8 +9099,13 @@ var stdlib = map[string]string{
"url.Userinfo": "net/url",
"url.Values": "net/url",
"user.Current": "os/user",
+ "user.Group": "os/user",
"user.Lookup": "os/user",
+ "user.LookupGroup": "os/user",
+ "user.LookupGroupId": "os/user",
"user.LookupId": "os/user",
+ "user.UnknownGroupError": "os/user",
+ "user.UnknownGroupIdError": "os/user",
"user.UnknownUserError": "os/user",
"user.UnknownUserIdError": "os/user",
"user.User": "os/user",
@@ -8925,6 +9168,7 @@ var stdlib = map[string]string{
"x509.HostnameError": "crypto/x509",
"x509.IncompatibleUsage": "crypto/x509",
"x509.IncorrectPasswordError": "crypto/x509",
+ "x509.InsecureAlgorithmError": "crypto/x509",
"x509.InvalidReason": "crypto/x509",
"x509.IsEncryptedPEMBlock": "crypto/x509",
"x509.KeyUsage": "crypto/x509",
@@ -8966,6 +9210,7 @@ var stdlib = map[string]string{
"x509.SHA384WithRSA": "crypto/x509",
"x509.SHA512WithRSA": "crypto/x509",
"x509.SignatureAlgorithm": "crypto/x509",
+ "x509.SystemCertPool": "crypto/x509",
"x509.SystemRootsError": "crypto/x509",
"x509.TooManyIntermediates": "crypto/x509",
"x509.UnhandledCriticalExtension": "crypto/x509",
@@ -9035,4 +9280,10 @@ var stdlib = map[string]string{
"zlib.NoCompression": "compress/zlib",
"zlib.Resetter": "compress/zlib",
"zlib.Writer": "compress/zlib",
+
+ "unsafe.Alignof": "unsafe",
+ "unsafe.ArbitraryType": "unsafe",
+ "unsafe.Offsetof": "unsafe",
+ "unsafe.Pointer": "unsafe",
+ "unsafe.Sizeof": "unsafe",
}