Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201028153306-37f0764111ff / internal / imports / mkindex.go
1 // +build ignore
2
3 // Copyright 2013 The Go Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file.
6
7 // Command mkindex creates the file "pkgindex.go" containing an index of the Go
8 // standard library. The file is intended to be built as part of the imports
9 // package, so that the package may be used in environments where a GOROOT is
10 // not available (such as App Engine).
11 package imports
12
13 import (
14         "bytes"
15         "fmt"
16         "go/ast"
17         "go/build"
18         "go/format"
19         "go/parser"
20         "go/token"
21         "io/ioutil"
22         "log"
23         "os"
24         "path"
25         "path/filepath"
26         "strings"
27 )
28
29 var (
30         pkgIndex = make(map[string][]pkg)
31         exports  = make(map[string]map[string]bool)
32 )
33
34 func main() {
35         // Don't use GOPATH.
36         ctx := build.Default
37         ctx.GOPATH = ""
38
39         // Populate pkgIndex global from GOROOT.
40         for _, path := range ctx.SrcDirs() {
41                 f, err := os.Open(path)
42                 if err != nil {
43                         log.Print(err)
44                         continue
45                 }
46                 children, err := f.Readdir(-1)
47                 f.Close()
48                 if err != nil {
49                         log.Print(err)
50                         continue
51                 }
52                 for _, child := range children {
53                         if child.IsDir() {
54                                 loadPkg(path, child.Name())
55                         }
56                 }
57         }
58         // Populate exports global.
59         for _, ps := range pkgIndex {
60                 for _, p := range ps {
61                         e := loadExports(p.dir)
62                         if e != nil {
63                                 exports[p.dir] = e
64                         }
65                 }
66         }
67
68         // Construct source file.
69         var buf bytes.Buffer
70         fmt.Fprint(&buf, pkgIndexHead)
71         fmt.Fprintf(&buf, "var pkgIndexMaster = %#v\n", pkgIndex)
72         fmt.Fprintf(&buf, "var exportsMaster = %#v\n", exports)
73         src := buf.Bytes()
74
75         // Replace main.pkg type name with pkg.
76         src = bytes.Replace(src, []byte("main.pkg"), []byte("pkg"), -1)
77         // Replace actual GOROOT with "/go".
78         src = bytes.Replace(src, []byte(ctx.GOROOT), []byte("/go"), -1)
79         // Add some line wrapping.
80         src = bytes.Replace(src, []byte("}, "), []byte("},\n"), -1)
81         src = bytes.Replace(src, []byte("true, "), []byte("true,\n"), -1)
82
83         var err error
84         src, err = format.Source(src)
85         if err != nil {
86                 log.Fatal(err)
87         }
88
89         // Write out source file.
90         err = ioutil.WriteFile("pkgindex.go", src, 0644)
91         if err != nil {
92                 log.Fatal(err)
93         }
94 }
95
96 const pkgIndexHead = `package imports
97
98 func init() {
99         pkgIndexOnce.Do(func() {
100                 pkgIndex.m = pkgIndexMaster
101         })
102         loadExports = func(dir string) map[string]bool {
103                 return exportsMaster[dir]
104         }
105 }
106 `
107
108 type pkg struct {
109         importpath string // full pkg import path, e.g. "net/http"
110         dir        string // absolute file path to pkg directory e.g. "/usr/lib/go/src/fmt"
111 }
112
113 var fset = token.NewFileSet()
114
115 func loadPkg(root, importpath string) {
116         shortName := path.Base(importpath)
117         if shortName == "testdata" {
118                 return
119         }
120
121         dir := filepath.Join(root, importpath)
122         pkgIndex[shortName] = append(pkgIndex[shortName], pkg{
123                 importpath: importpath,
124                 dir:        dir,
125         })
126
127         pkgDir, err := os.Open(dir)
128         if err != nil {
129                 return
130         }
131         children, err := pkgDir.Readdir(-1)
132         pkgDir.Close()
133         if err != nil {
134                 return
135         }
136         for _, child := range children {
137                 name := child.Name()
138                 if name == "" {
139                         continue
140                 }
141                 if c := name[0]; c == '.' || ('0' <= c && c <= '9') {
142                         continue
143                 }
144                 if child.IsDir() {
145                         loadPkg(root, filepath.Join(importpath, name))
146                 }
147         }
148 }
149
150 func loadExports(dir string) map[string]bool {
151         exports := make(map[string]bool)
152         buildPkg, err := build.ImportDir(dir, 0)
153         if err != nil {
154                 if strings.Contains(err.Error(), "no buildable Go source files in") {
155                         return nil
156                 }
157                 log.Printf("could not import %q: %v", dir, err)
158                 return nil
159         }
160         for _, file := range buildPkg.GoFiles {
161                 f, err := parser.ParseFile(fset, filepath.Join(dir, file), nil, 0)
162                 if err != nil {
163                         log.Printf("could not parse %q: %v", file, err)
164                         continue
165                 }
166                 for name := range f.Scope.Objects {
167                         if ast.IsExported(name) {
168                                 exports[name] = true
169                         }
170                 }
171         }
172         return exports
173 }