aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/golang.org/x/tools/imports/mkindex.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/tools/imports/mkindex.go')
-rw-r--r--vendor/golang.org/x/tools/imports/mkindex.go173
1 files changed, 173 insertions, 0 deletions
diff --git a/vendor/golang.org/x/tools/imports/mkindex.go b/vendor/golang.org/x/tools/imports/mkindex.go
new file mode 100644
index 000000000..755e2394f
--- /dev/null
+++ b/vendor/golang.org/x/tools/imports/mkindex.go
@@ -0,0 +1,173 @@
+// +build ignore
+
+// Copyright 2013 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.
+
+// Command mkindex creates the file "pkgindex.go" containing an index of the Go
+// standard library. The file is intended to be built as part of the imports
+// package, so that the package may be used in environments where a GOROOT is
+// not available (such as App Engine).
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "go/ast"
+ "go/build"
+ "go/format"
+ "go/parser"
+ "go/token"
+ "io/ioutil"
+ "log"
+ "os"
+ "path"
+ "path/filepath"
+ "strings"
+)
+
+var (
+ pkgIndex = make(map[string][]pkg)
+ exports = make(map[string]map[string]bool)
+)
+
+func main() {
+ // Don't use GOPATH.
+ ctx := build.Default
+ ctx.GOPATH = ""
+
+ // Populate pkgIndex global from GOROOT.
+ for _, path := range ctx.SrcDirs() {
+ f, err := os.Open(path)
+ if err != nil {
+ log.Print(err)
+ continue
+ }
+ children, err := f.Readdir(-1)
+ f.Close()
+ if err != nil {
+ log.Print(err)
+ continue
+ }
+ for _, child := range children {
+ if child.IsDir() {
+ loadPkg(path, child.Name())
+ }
+ }
+ }
+ // Populate exports global.
+ for _, ps := range pkgIndex {
+ for _, p := range ps {
+ e := loadExports(p.dir)
+ if e != nil {
+ exports[p.dir] = e
+ }
+ }
+ }
+
+ // Construct source file.
+ var buf bytes.Buffer
+ fmt.Fprint(&buf, pkgIndexHead)
+ fmt.Fprintf(&buf, "var pkgIndexMaster = %#v\n", pkgIndex)
+ fmt.Fprintf(&buf, "var exportsMaster = %#v\n", exports)
+ src := buf.Bytes()
+
+ // Replace main.pkg type name with pkg.
+ src = bytes.Replace(src, []byte("main.pkg"), []byte("pkg"), -1)
+ // Replace actual GOROOT with "/go".
+ src = bytes.Replace(src, []byte(ctx.GOROOT), []byte("/go"), -1)
+ // Add some line wrapping.
+ src = bytes.Replace(src, []byte("}, "), []byte("},\n"), -1)
+ src = bytes.Replace(src, []byte("true, "), []byte("true,\n"), -1)
+
+ var err error
+ src, err = format.Source(src)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // Write out source file.
+ err = ioutil.WriteFile("pkgindex.go", src, 0644)
+ if err != nil {
+ log.Fatal(err)
+ }
+}
+
+const pkgIndexHead = `package imports
+
+func init() {
+ pkgIndexOnce.Do(func() {
+ pkgIndex.m = pkgIndexMaster
+ })
+ loadExports = func(dir string) map[string]bool {
+ return exportsMaster[dir]
+ }
+}
+`
+
+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"
+}
+
+var fset = token.NewFileSet()
+
+func loadPkg(root, importpath string) {
+ shortName := path.Base(importpath)
+ if shortName == "testdata" {
+ return
+ }
+
+ dir := filepath.Join(root, importpath)
+ pkgIndex[shortName] = append(pkgIndex[shortName], pkg{
+ importpath: importpath,
+ dir: dir,
+ })
+
+ pkgDir, err := os.Open(dir)
+ if err != nil {
+ return
+ }
+ children, err := pkgDir.Readdir(-1)
+ pkgDir.Close()
+ if err != nil {
+ return
+ }
+ for _, child := range children {
+ name := child.Name()
+ if name == "" {
+ continue
+ }
+ if c := name[0]; c == '.' || ('0' <= c && c <= '9') {
+ continue
+ }
+ if child.IsDir() {
+ loadPkg(root, filepath.Join(importpath, name))
+ }
+ }
+}
+
+func loadExports(dir string) map[string]bool {
+ 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
+ }
+ log.Printf("could not import %q: %v", dir, err)
+ return nil
+ }
+ for _, file := range buildPkg.GoFiles {
+ f, err := parser.ParseFile(fset, filepath.Join(dir, file), nil, 0)
+ if err != nil {
+ log.Printf("could not parse %q: %v", file, err)
+ continue
+ }
+ for name := range f.Scope.Objects {
+ if ast.IsExported(name) {
+ exports[name] = true
+ }
+ }
+ }
+ return exports
+}