Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / honnef.co / go / tools@v0.0.1-2020.1.5 / ir / create.go
1 // Copyright 2013 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package ir
6
7 // This file implements the CREATE phase of IR construction.
8 // See builder.go for explanation.
9
10 import (
11         "fmt"
12         "go/ast"
13         "go/token"
14         "go/types"
15         "os"
16         "sync"
17
18         "golang.org/x/tools/go/types/typeutil"
19 )
20
21 // NewProgram returns a new IR Program.
22 //
23 // mode controls diagnostics and checking during IR construction.
24 //
25 func NewProgram(fset *token.FileSet, mode BuilderMode) *Program {
26         prog := &Program{
27                 Fset:     fset,
28                 imported: make(map[string]*Package),
29                 packages: make(map[*types.Package]*Package),
30                 thunks:   make(map[selectionKey]*Function),
31                 bounds:   make(map[*types.Func]*Function),
32                 mode:     mode,
33         }
34
35         h := typeutil.MakeHasher() // protected by methodsMu, in effect
36         prog.methodSets.SetHasher(h)
37         prog.canon.SetHasher(h)
38
39         return prog
40 }
41
42 // memberFromObject populates package pkg with a member for the
43 // typechecker object obj.
44 //
45 // For objects from Go source code, syntax is the associated syntax
46 // tree (for funcs and vars only); it will be used during the build
47 // phase.
48 //
49 func memberFromObject(pkg *Package, obj types.Object, syntax ast.Node) {
50         name := obj.Name()
51         switch obj := obj.(type) {
52         case *types.Builtin:
53                 if pkg.Pkg != types.Unsafe {
54                         panic("unexpected builtin object: " + obj.String())
55                 }
56
57         case *types.TypeName:
58                 pkg.Members[name] = &Type{
59                         object: obj,
60                         pkg:    pkg,
61                 }
62
63         case *types.Const:
64                 c := &NamedConst{
65                         object: obj,
66                         Value:  NewConst(obj.Val(), obj.Type()),
67                         pkg:    pkg,
68                 }
69                 pkg.values[obj] = c.Value
70                 pkg.Members[name] = c
71
72         case *types.Var:
73                 g := &Global{
74                         Pkg:    pkg,
75                         name:   name,
76                         object: obj,
77                         typ:    types.NewPointer(obj.Type()), // address
78                 }
79                 pkg.values[obj] = g
80                 pkg.Members[name] = g
81
82         case *types.Func:
83                 sig := obj.Type().(*types.Signature)
84                 if sig.Recv() == nil && name == "init" {
85                         pkg.ninit++
86                         name = fmt.Sprintf("init#%d", pkg.ninit)
87                 }
88                 fn := &Function{
89                         name:      name,
90                         object:    obj,
91                         Signature: sig,
92                         Pkg:       pkg,
93                         Prog:      pkg.Prog,
94                 }
95
96                 fn.source = syntax
97                 fn.initHTML(pkg.printFunc)
98                 if syntax == nil {
99                         fn.Synthetic = "loaded from gc object file"
100                 } else {
101                         fn.functionBody = new(functionBody)
102                 }
103
104                 pkg.values[obj] = fn
105                 pkg.Functions = append(pkg.Functions, fn)
106                 if sig.Recv() == nil {
107                         pkg.Members[name] = fn // package-level function
108                 }
109
110         default: // (incl. *types.Package)
111                 panic("unexpected Object type: " + obj.String())
112         }
113 }
114
115 // membersFromDecl populates package pkg with members for each
116 // typechecker object (var, func, const or type) associated with the
117 // specified decl.
118 //
119 func membersFromDecl(pkg *Package, decl ast.Decl) {
120         switch decl := decl.(type) {
121         case *ast.GenDecl: // import, const, type or var
122                 switch decl.Tok {
123                 case token.CONST:
124                         for _, spec := range decl.Specs {
125                                 for _, id := range spec.(*ast.ValueSpec).Names {
126                                         if !isBlankIdent(id) {
127                                                 memberFromObject(pkg, pkg.info.Defs[id], nil)
128                                         }
129                                 }
130                         }
131
132                 case token.VAR:
133                         for _, spec := range decl.Specs {
134                                 for _, id := range spec.(*ast.ValueSpec).Names {
135                                         if !isBlankIdent(id) {
136                                                 memberFromObject(pkg, pkg.info.Defs[id], spec)
137                                         }
138                                 }
139                         }
140
141                 case token.TYPE:
142                         for _, spec := range decl.Specs {
143                                 id := spec.(*ast.TypeSpec).Name
144                                 if !isBlankIdent(id) {
145                                         memberFromObject(pkg, pkg.info.Defs[id], nil)
146                                 }
147                         }
148                 }
149
150         case *ast.FuncDecl:
151                 id := decl.Name
152                 if !isBlankIdent(id) {
153                         memberFromObject(pkg, pkg.info.Defs[id], decl)
154                 }
155         }
156 }
157
158 // CreatePackage constructs and returns an IR Package from the
159 // specified type-checked, error-free file ASTs, and populates its
160 // Members mapping.
161 //
162 // importable determines whether this package should be returned by a
163 // subsequent call to ImportedPackage(pkg.Path()).
164 //
165 // The real work of building IR form for each function is not done
166 // until a subsequent call to Package.Build().
167 //
168 func (prog *Program) CreatePackage(pkg *types.Package, files []*ast.File, info *types.Info, importable bool) *Package {
169         p := &Package{
170                 Prog:      prog,
171                 Members:   make(map[string]Member),
172                 values:    make(map[types.Object]Value),
173                 Pkg:       pkg,
174                 info:      info,  // transient (CREATE and BUILD phases)
175                 files:     files, // transient (CREATE and BUILD phases)
176                 printFunc: prog.PrintFunc,
177         }
178
179         // Add init() function.
180         p.init = &Function{
181                 name:         "init",
182                 Signature:    new(types.Signature),
183                 Synthetic:    "package initializer",
184                 Pkg:          p,
185                 Prog:         prog,
186                 functionBody: new(functionBody),
187         }
188         p.init.initHTML(prog.PrintFunc)
189         p.Members[p.init.name] = p.init
190         p.Functions = append(p.Functions, p.init)
191
192         // CREATE phase.
193         // Allocate all package members: vars, funcs, consts and types.
194         if len(files) > 0 {
195                 // Go source package.
196                 for _, file := range files {
197                         for _, decl := range file.Decls {
198                                 membersFromDecl(p, decl)
199                         }
200                 }
201         } else {
202                 // GC-compiled binary package (or "unsafe")
203                 // No code.
204                 // No position information.
205                 scope := p.Pkg.Scope()
206                 for _, name := range scope.Names() {
207                         obj := scope.Lookup(name)
208                         memberFromObject(p, obj, nil)
209                         if obj, ok := obj.(*types.TypeName); ok {
210                                 if named, ok := obj.Type().(*types.Named); ok {
211                                         for i, n := 0, named.NumMethods(); i < n; i++ {
212                                                 memberFromObject(p, named.Method(i), nil)
213                                         }
214                                 }
215                         }
216                 }
217         }
218
219         // Add initializer guard variable.
220         initguard := &Global{
221                 Pkg:  p,
222                 name: "init$guard",
223                 typ:  types.NewPointer(tBool),
224         }
225         p.Members[initguard.Name()] = initguard
226
227         if prog.mode&GlobalDebug != 0 {
228                 p.SetDebugMode(true)
229         }
230
231         if prog.mode&PrintPackages != 0 {
232                 printMu.Lock()
233                 p.WriteTo(os.Stdout)
234                 printMu.Unlock()
235         }
236
237         if importable {
238                 prog.imported[p.Pkg.Path()] = p
239         }
240         prog.packages[p.Pkg] = p
241
242         return p
243 }
244
245 // printMu serializes printing of Packages/Functions to stdout.
246 var printMu sync.Mutex
247
248 // AllPackages returns a new slice containing all packages in the
249 // program prog in unspecified order.
250 //
251 func (prog *Program) AllPackages() []*Package {
252         pkgs := make([]*Package, 0, len(prog.packages))
253         for _, pkg := range prog.packages {
254                 pkgs = append(pkgs, pkg)
255         }
256         return pkgs
257 }
258
259 // ImportedPackage returns the importable Package whose PkgPath
260 // is path, or nil if no such Package has been created.
261 //
262 // A parameter to CreatePackage determines whether a package should be
263 // considered importable. For example, no import declaration can resolve
264 // to the ad-hoc main package created by 'go build foo.go'.
265 //
266 // TODO(adonovan): rethink this function and the "importable" concept;
267 // most packages are importable. This function assumes that all
268 // types.Package.Path values are unique within the ir.Program, which is
269 // false---yet this function remains very convenient.
270 // Clients should use (*Program).Package instead where possible.
271 // IR doesn't really need a string-keyed map of packages.
272 //
273 func (prog *Program) ImportedPackage(path string) *Package {
274         return prog.imported[path]
275 }