1
2
3
4
5 package inline
6
7 import (
8 "fmt"
9 "go/ast"
10 "go/token"
11 "go/types"
12 )
13
14
15
16
17
18
19 func escape(info *types.Info, root ast.Node, f func(v *types.Var, escapes bool)) {
20
21
22
23 var lvalue func(e ast.Expr, escapes bool)
24 lvalue = func(e ast.Expr, escapes bool) {
25 switch e := e.(type) {
26 case *ast.Ident:
27 if v, ok := info.Uses[e].(*types.Var); ok {
28 if !isPkgLevel(v) {
29 f(v, escapes)
30 }
31 }
32 case *ast.ParenExpr:
33 lvalue(e.X, escapes)
34 case *ast.IndexExpr:
35
36
37
38
39
40
41
42
43
44
45
46 if _, ok := info.TypeOf(e.X).Underlying().(*types.Array); ok {
47 lvalue(e.X, escapes)
48 }
49 case *ast.SelectorExpr:
50
51 if _, ok := info.TypeOf(e.X).Underlying().(*types.Struct); ok {
52 lvalue(e.X, escapes)
53 }
54 case *ast.StarExpr:
55
56 case *ast.CompositeLit:
57
58 default:
59 panic(fmt.Sprintf("&x on %T", e))
60 }
61 }
62
63
64
65 ast.Inspect(root, func(n ast.Node) bool {
66 switch n := n.(type) {
67 case *ast.UnaryExpr:
68 if n.Op == token.AND {
69 lvalue(n.X, true)
70 }
71
72 case *ast.CallExpr:
73
74
75 if sel, ok := n.Fun.(*ast.SelectorExpr); ok {
76 if seln, ok := info.Selections[sel]; ok &&
77 seln.Kind() == types.MethodVal &&
78 isPointer(seln.Obj().Type().Underlying().(*types.Signature).Recv().Type()) {
79 tArg, indirect := effectiveReceiver(seln)
80 if !indirect && !isPointer(tArg) {
81 lvalue(sel.X, true)
82 }
83 }
84 }
85
86 case *ast.AssignStmt:
87 for _, lhs := range n.Lhs {
88 if id, ok := lhs.(*ast.Ident); ok &&
89 info.Defs[id] != nil &&
90 n.Tok == token.DEFINE {
91
92 } else {
93 lvalue(lhs, false)
94 }
95 }
96
97 case *ast.IncDecStmt:
98 lvalue(n.X, false)
99 }
100 return true
101 })
102 }
103
View as plain text