/
pkg.go
115 lines (98 loc) · 2.43 KB
/
pkg.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package loader
import (
"bytes"
"go/ast"
"go/printer"
"go/token"
"go/types"
"golang.org/x/tools/go/packages"
"golang.org/x/tools/go/types/typeutil"
)
type (
Package = packages.Package
Positioner interface{ Pos() token.Pos }
)
type Pkg struct {
*Package
}
func MkPkg(p *Package) Pkg {
return Pkg{p}
}
func (p *Pkg) ShowPos(n Positioner) string {
return p.Fset.Position(n.Pos()).String()
}
func (p *Pkg) ShowNode(n ast.Node) string {
var buf bytes.Buffer
_ = printer.Fprint(&buf, p.Fset, n)
return buf.String()
}
func (p *Pkg) TypeInfo() *types.Info { return p.TypesInfo }
func (p *Pkg) ObjectOf(id *ast.Ident) types.Object { return p.TypeInfo().ObjectOf(id) }
func (p *Pkg) TypeOf(e ast.Expr) types.Type { return p.TypeInfo().TypeOf(e) }
func (p *Pkg) Callee(call *ast.CallExpr) types.Object {
return typeutil.Callee(p.TypeInfo(), call)
}
func (p *Pkg) Fun(fun ast.Expr) types.Object { return p.Callee(&ast.CallExpr{Fun: fun}) }
func (p *Pkg) ScopeFor(n ast.Node) *types.Scope {
switch fn := n.(type) {
case *ast.FuncDecl:
n = fn.Type
case *ast.FuncLit:
n = fn.Type
}
return p.TypeInfo().Scopes[n]
}
func (p *Pkg) UpdateType(e ast.Expr, t types.Type) {
p.TypeInfo().Types[e] = types.TypeAndValue{Type: t}
}
func (p *Pkg) UpdateUses(idOrSel ast.Expr, obj types.Object) {
info := p.TypeInfo()
switch x := idOrSel.(type) {
case *ast.Ident:
info.Uses[x] = obj
case *ast.SelectorExpr:
info.Uses[x.Sel] = obj
default:
panic("unreached")
}
}
func (p *Pkg) UpdateDefs(idOrSel ast.Expr, obj types.Object) {
info := p.TypeInfo()
switch x := idOrSel.(type) {
case *ast.Ident:
info.Defs[x] = obj
case *ast.SelectorExpr:
info.Defs[x.Sel] = obj
default:
panic("unreached")
}
}
func (p *Pkg) CopyTypeInfo(new, old ast.Expr) {
info := p.TypeInfo()
//goland:noinspection GoReservedWordUsedAsName
switch new := new.(type) {
case *ast.Ident:
orig := old.(*ast.Ident)
if obj, ok := info.Defs[orig]; ok {
info.Defs[new] = obj
}
if obj, ok := info.Uses[orig]; ok {
info.Uses[new] = obj
}
case *ast.SelectorExpr:
orig := old.(*ast.SelectorExpr)
if sel, ok := info.Selections[orig]; ok {
info.Selections[new] = sel
}
}
if tv, ok := info.Types[old]; ok {
info.Types[new] = tv
}
}
func (p *Pkg) NewIdent(name string, t types.Type) *ast.Ident {
ident := ast.NewIdent(name)
p.UpdateType(ident, t)
obj := types.NewVar(token.NoPos, p.Types, name, t)
p.UpdateUses(ident, obj)
return ident
}