Skip to content

Commit 0ab4fb6

Browse files
committed
cl: record def for ast.OverloadFuncDecl
1 parent 64a3001 commit 0ab4fb6

File tree

4 files changed

+182
-39
lines changed

4 files changed

+182
-39
lines changed

cl/compile.go

+13-5
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ type Recorder interface {
127127
// *ast.ImportSpec *PkgName for imports without renames
128128
// *ast.CaseClause type-specific *Var for each type switch case clause (incl. default)
129129
// *ast.Field anonymous parameter *Var (incl. unnamed results)
130+
// *ast.FunLit function literal in *ast.OverloadFuncDecl
130131
//
131132
Implicit(node ast.Node, obj types.Object)
132133

@@ -1085,7 +1086,7 @@ func preloadFile(p *gogen.Package, ctx *blockCtx, f *ast.File, goFile string, ge
10851086
}
10861087
recv = otyp
10871088
if ctx.rec != nil {
1088-
ctx.rec.Refer(recv, recv.Name)
1089+
ctx.rec.ReferUse(recv, recv.Name)
10891090
}
10901091
}
10911092
onames := make([]string, 0, 4)
@@ -1103,7 +1104,7 @@ func preloadFile(p *gogen.Package, ctx *blockCtx, f *ast.File, goFile string, ge
11031104
ctx.lbinames = append(ctx.lbinames, expr.Name)
11041105
exov = true
11051106
if ctx.rec != nil {
1106-
ctx.rec.Refer(expr, expr.Name)
1107+
ctx.rec.ReferUse(expr, expr.Name)
11071108
}
11081109
case *ast.SelectorExpr:
11091110
if d.Recv == nil {
@@ -1120,8 +1121,8 @@ func preloadFile(p *gogen.Package, ctx *blockCtx, f *ast.File, goFile string, ge
11201121
ctx.lbinames = append(ctx.lbinames, recv)
11211122
exov = true
11221123
if ctx.rec != nil {
1123-
ctx.rec.Refer(rtyp, rtyp.Name)
1124-
ctx.rec.Refer(expr.Sel, rtyp.Name+"."+expr.Sel.Name)
1124+
ctx.rec.ReferUse(rtyp, rtyp.Name)
1125+
ctx.rec.ReferUse(expr.Sel, rtyp.Name+"."+expr.Sel.Name)
11251126
}
11261127
case *ast.FuncLit:
11271128
if d.Recv != nil && !d.Operator {
@@ -1131,9 +1132,13 @@ func preloadFile(p *gogen.Package, ctx *blockCtx, f *ast.File, goFile string, ge
11311132
name1 := overloadFuncName(name.Name, idx)
11321133
onames = append(onames, "") // const Gopo_xxx = "xxxInt,,xxxFloat"
11331134
ctx.lbinames = append(ctx.lbinames, name1)
1135+
id := &ast.Ident{NamePos: expr.Pos(), Name: name1}
1136+
if ctx.rec != nil {
1137+
ctx.rec.ReferDef(id, expr)
1138+
}
11341139
preloadFuncDecl(&ast.FuncDecl{
11351140
Doc: d.Doc,
1136-
Name: &ast.Ident{NamePos: expr.Pos(), Name: name1},
1141+
Name: id,
11371142
Type: expr.Type,
11381143
Body: expr.Body,
11391144
})
@@ -1160,6 +1165,9 @@ func preloadFile(p *gogen.Package, ctx *blockCtx, f *ast.File, goFile string, ge
11601165
},
11611166
})
11621167
ctx.lbinames = append(ctx.lbinames, oname)
1168+
if ctx.rec != nil {
1169+
ctx.rec.ReferDef(d.Name, d)
1170+
}
11631171
}
11641172

11651173
default:

cl/recorder.go

+44-9
Original file line numberDiff line numberDiff line change
@@ -29,24 +29,58 @@ import (
2929

3030
type goxRecorder struct {
3131
Recorder
32-
types map[ast.Expr]types.TypeAndValue
33-
refers map[string][]*ast.Ident
32+
types map[ast.Expr]types.TypeAndValue
33+
referDefs map[*ast.Ident]ast.Node
34+
referUses map[string][]*ast.Ident
3435
}
3536

3637
func newRecorder(rec Recorder) *goxRecorder {
3738
types := make(map[ast.Expr]types.TypeAndValue)
38-
refers := make(map[string][]*ast.Ident)
39-
return &goxRecorder{rec, types, refers}
39+
referDefs := make(map[*ast.Ident]ast.Node)
40+
referUses := make(map[string][]*ast.Ident)
41+
return &goxRecorder{rec, types, referDefs, referUses}
4042
}
4143

42-
// Refer maps identifiers to name for ast.OverloadFuncDecl.
43-
func (p *goxRecorder) Refer(ident *ast.Ident, name string) {
44-
p.refers[name] = append(p.refers[name], ident)
44+
// Refer uses maps identifiers to name for ast.OverloadFuncDecl.
45+
func (p *goxRecorder) ReferUse(ident *ast.Ident, name string) {
46+
p.referUses[name] = append(p.referUses[name], ident)
47+
}
48+
49+
// Refer def maps for ast.FuncLit or ast.OverloadFuncDecl.
50+
func (p *goxRecorder) ReferDef(ident *ast.Ident, node ast.Node) {
51+
p.referDefs[ident] = node
4552
}
4653

4754
// Complete computes the types record.
4855
func (p *goxRecorder) Complete(scope *types.Scope) {
49-
for name, idents := range p.refers {
56+
for id, node := range p.referDefs {
57+
switch fn := node.(type) {
58+
case *ast.FuncLit:
59+
if obj := scope.Lookup(id.Name); obj != nil {
60+
p.recordFuncLit(fn, obj.Type())
61+
p.Implicit(node, obj)
62+
}
63+
case *ast.OverloadFuncDecl:
64+
if fn.Recv == nil {
65+
if obj := scope.Lookup(id.Name); obj != nil {
66+
p.Def(id, obj)
67+
}
68+
} else {
69+
if obj := scope.Lookup(fn.Recv.List[0].Type.(*ast.Ident).Name); obj != nil {
70+
if named, ok := obj.Type().(*types.Named); ok {
71+
n := named.NumMethods()
72+
for i := 0; i < n; i++ {
73+
if m := named.Method(i); m.Name() == id.Name {
74+
p.Def(id, m)
75+
break
76+
}
77+
}
78+
}
79+
}
80+
}
81+
}
82+
}
83+
for name, idents := range p.referUses {
5084
pos := strings.Index(name, ".")
5185
if pos == -1 {
5286
if obj := scope.Lookup(name); obj != nil {
@@ -71,7 +105,8 @@ func (p *goxRecorder) Complete(scope *types.Scope) {
71105
}
72106
}
73107
p.types = nil
74-
p.refers = nil
108+
p.referDefs = nil
109+
p.referUses = nil
75110
}
76111

77112
// Member maps identifiers to the objects they denote.

x/typesutil/gopinfo.go

+1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ type Info struct {
9191
// *ast.ImportSpec *PkgName for imports without renames
9292
// *ast.CaseClause type-specific *Var for each type switch case clause (incl. default)
9393
// *ast.Field anonymous parameter *Var (incl. unnamed results)
94+
// *ast.FunLit function literal in *ast.OverloadFuncDecl
9495
//
9596
Implicits map[ast.Node]types.Object
9697

x/typesutil/info_test.go

+124-25
Original file line numberDiff line numberDiff line change
@@ -2018,22 +2018,26 @@ Mul 100,200,300
20182018
008: 7: 9 | a *ast.Ident | var : float64 | variable
20192019
009: 7: 9 | a * b *ast.BinaryExpr | value : float64 | value
20202020
010: 7:13 | b *ast.Ident | var : float64 | variable
2021-
011: 13:15 | int *ast.Ident | type : int | type
2022-
012: 13:20 | int *ast.Ident | type : int | type
2023-
013: 14:10 | x *ast.Ident | var : int | variable
2024-
014: 14:10 | x * y *ast.BinaryExpr | value : int | value
2025-
015: 14:10 | x * y * z *ast.BinaryExpr | value : int | value
2026-
016: 14:14 | y *ast.Ident | var : int | variable
2027-
017: 14:18 | z *ast.Ident | var : int | variable
2028-
018: 18: 1 | Mul *ast.Ident | value : func(a int, b int) int | value
2029-
019: 18: 1 | Mul 100, 200 *ast.CallExpr | value : int | value
2030-
020: 18: 5 | 100 *ast.BasicLit | value : untyped int = 100 | constant
2031-
021: 18: 9 | 200 *ast.BasicLit | value : untyped int = 200 | constant
2032-
022: 19: 1 | Mul *ast.Ident | value : func(x int, y int, z int) int | value
2033-
023: 19: 1 | Mul 100, 200, 300 *ast.CallExpr | value : int | value
2034-
024: 19: 5 | 100 *ast.BasicLit | value : untyped int = 100 | constant
2035-
025: 19: 9 | 200 *ast.BasicLit | value : untyped int = 200 | constant
2036-
026: 19:13 | 300 *ast.BasicLit | value : untyped int = 300 | constant
2021+
011: 13: 2 | func(x, y, z int) int *ast.FuncType | type : func(x int, y int, z int) int | type
2022+
012: 13: 2 | func(x, y, z int) int {
2023+
return x * y * z
2024+
} *ast.FuncLit | value : func(x int, y int, z int) int | value
2025+
013: 13:15 | int *ast.Ident | type : int | type
2026+
014: 13:20 | int *ast.Ident | type : int | type
2027+
015: 14:10 | x *ast.Ident | var : int | variable
2028+
016: 14:10 | x * y *ast.BinaryExpr | value : int | value
2029+
017: 14:10 | x * y * z *ast.BinaryExpr | value : int | value
2030+
018: 14:14 | y *ast.Ident | var : int | variable
2031+
019: 14:18 | z *ast.Ident | var : int | variable
2032+
020: 18: 1 | Mul *ast.Ident | value : func(a int, b int) int | value
2033+
021: 18: 1 | Mul 100, 200 *ast.CallExpr | value : int | value
2034+
022: 18: 5 | 100 *ast.BasicLit | value : untyped int = 100 | constant
2035+
023: 18: 9 | 200 *ast.BasicLit | value : untyped int = 200 | constant
2036+
024: 19: 1 | Mul *ast.Ident | value : func(x int, y int, z int) int | value
2037+
025: 19: 1 | Mul 100, 200, 300 *ast.CallExpr | value : int | value
2038+
026: 19: 5 | 100 *ast.BasicLit | value : untyped int = 100 | constant
2039+
027: 19: 9 | 200 *ast.BasicLit | value : untyped int = 200 | constant
2040+
028: 19:13 | 300 *ast.BasicLit | value : untyped int = 300 | constant
20372041
== defs ==
20382042
000: 0: 0 | Gopo_Mul | const main.Gopo_Mul untyped string
20392043
001: 2: 6 | MulInt | func main.MulInt(a int, b int) int
@@ -2042,11 +2046,12 @@ Mul 100,200,300
20422046
004: 6: 6 | MulFloat | func main.MulFloat(a float64, b float64) float64
20432047
005: 6:15 | a | var a float64
20442048
006: 6:18 | b | var b float64
2045-
007: 13: 2 | Mul__2 | func main.Mul__2(x int, y int, z int) int
2046-
008: 13: 7 | x | var x int
2047-
009: 13:10 | y | var y int
2048-
010: 13:13 | z | var z int
2049-
011: 18: 1 | main | func main.main()
2049+
007: 10: 6 | Mul | func main.Mul(__gop_overload_args__ interface{_()})
2050+
008: 13: 2 | Mul__2 | func main.Mul__2(x int, y int, z int) int
2051+
009: 13: 7 | x | var x int
2052+
010: 13:10 | y | var y int
2053+
011: 13:13 | z | var z int
2054+
012: 18: 1 | main | func main.main()
20502055
== uses ==
20512056
000: 2:18 | int | type int
20522057
001: 2:23 | int | type int
@@ -2120,10 +2125,11 @@ var d = a.mul(c)
21202125
005: 9: 7 | a | var a *main.foo
21212126
006: 9:15 | mulFoo | func (*main.foo).mulFoo(b *main.foo) *main.foo
21222127
007: 9:22 | b | var b *main.foo
2123-
008: 18: 5 | a | var main.a *main.foo
2124-
009: 18: 8 | b | var main.b *main.foo
2125-
010: 19: 5 | c | var main.c *main.foo
2126-
011: 20: 5 | d | var main.d *main.foo
2128+
008: 13:12 | mul | func (main.foo).mul(__gop_overload_args__ interface{_()})
2129+
009: 18: 5 | a | var main.a *main.foo
2130+
010: 18: 8 | b | var main.b *main.foo
2131+
011: 19: 5 | c | var main.c *main.foo
2132+
012: 20: 5 | d | var main.d *main.foo
21272133
== uses ==
21282134
000: 5:10 | foo | type main.foo struct{}
21292135
001: 5:24 | int | type int
@@ -2145,3 +2151,96 @@ var d = a.mul(c)
21452151
017: 20:11 | mul | func (*main.foo).mulFoo(b *main.foo) *main.foo
21462152
018: 20:15 | c | var main.c *main.foo`)
21472153
}
2154+
2155+
func TestGopOverloadDecl(t *testing.T) {
2156+
testGopInfo(t, `
2157+
func addInt0() {
2158+
}
2159+
2160+
func addInt1(i int) {
2161+
}
2162+
2163+
func addInt2(i, j int) {
2164+
}
2165+
2166+
var addInt3 = func(i, j, k int) {
2167+
}
2168+
2169+
func add = (
2170+
addInt0
2171+
addInt1
2172+
addInt2
2173+
addInt3
2174+
func(a, b string) string {
2175+
return a + b
2176+
}
2177+
)
2178+
2179+
func init() {
2180+
add 100, 200
2181+
add 100, 200, 300
2182+
add("hello", "world")
2183+
}
2184+
`, ``, `== types ==
2185+
000: 0: 0 | "addInt0,addInt1,addInt2,addInt3," *ast.BasicLit | value : untyped string = "addInt0,addInt1,addInt2,addInt3," | constant
2186+
001: 5:16 | int *ast.Ident | type : int | type
2187+
002: 8:19 | int *ast.Ident | type : int | type
2188+
003: 11:15 | func(i, j, k int) *ast.FuncType | type : func(i int, j int, k int) | type
2189+
004: 11:15 | func(i, j, k int) {
2190+
} *ast.FuncLit | value : func(i int, j int, k int) | value
2191+
005: 11:28 | int *ast.Ident | type : int | type
2192+
006: 19: 2 | func(a, b string) string *ast.FuncType | type : func(a string, b string) string | type
2193+
007: 19: 2 | func(a, b string) string {
2194+
return a + b
2195+
} *ast.FuncLit | value : func(a string, b string) string | value
2196+
008: 19:12 | string *ast.Ident | type : string | type
2197+
009: 19:20 | string *ast.Ident | type : string | type
2198+
010: 20:10 | a *ast.Ident | var : string | variable
2199+
011: 20:10 | a + b *ast.BinaryExpr | value : string | value
2200+
012: 20:14 | b *ast.Ident | var : string | variable
2201+
013: 25: 2 | add *ast.Ident | value : func(i int, j int) | value
2202+
014: 25: 2 | add 100, 200 *ast.CallExpr | void : () | no value
2203+
015: 25: 6 | 100 *ast.BasicLit | value : untyped int = 100 | constant
2204+
016: 25:11 | 200 *ast.BasicLit | value : untyped int = 200 | constant
2205+
017: 26: 2 | add *ast.Ident | var : func(i int, j int, k int) | variable
2206+
018: 26: 2 | add 100, 200, 300 *ast.CallExpr | void : () | no value
2207+
019: 26: 6 | 100 *ast.BasicLit | value : untyped int = 100 | constant
2208+
020: 26:11 | 200 *ast.BasicLit | value : untyped int = 200 | constant
2209+
021: 26:16 | 300 *ast.BasicLit | value : untyped int = 300 | constant
2210+
022: 27: 2 | add *ast.Ident | value : func(a string, b string) string | value
2211+
023: 27: 2 | add("hello", "world") *ast.CallExpr | value : string | value
2212+
024: 27: 6 | "hello" *ast.BasicLit | value : untyped string = "hello" | constant
2213+
025: 27:15 | "world" *ast.BasicLit | value : untyped string = "world" | constant
2214+
== defs ==
2215+
000: 0: 0 | Gopo_add | const main.Gopo_add untyped string
2216+
001: 2: 6 | addInt0 | func main.addInt0()
2217+
002: 5: 6 | addInt1 | func main.addInt1(i int)
2218+
003: 5:14 | i | var i int
2219+
004: 8: 6 | addInt2 | func main.addInt2(i int, j int)
2220+
005: 8:14 | i | var i int
2221+
006: 8:17 | j | var j int
2222+
007: 11: 5 | addInt3 | var main.addInt3 func(i int, j int, k int)
2223+
008: 11:20 | i | var i int
2224+
009: 11:23 | j | var j int
2225+
010: 11:26 | k | var k int
2226+
011: 14: 6 | add | func main.add(__gop_overload_args__ interface{_()})
2227+
012: 19: 2 | add__4 | func main.add__4(a string, b string) string
2228+
013: 19: 7 | a | var a string
2229+
014: 19:10 | b | var b string
2230+
015: 24: 6 | init | func main.init()
2231+
== uses ==
2232+
000: 5:16 | int | type int
2233+
001: 8:19 | int | type int
2234+
002: 11:28 | int | type int
2235+
003: 15: 2 | addInt0 | func main.addInt0()
2236+
004: 16: 2 | addInt1 | func main.addInt1(i int)
2237+
005: 17: 2 | addInt2 | func main.addInt2(i int, j int)
2238+
006: 18: 2 | addInt3 | var main.addInt3 func(i int, j int, k int)
2239+
007: 19:12 | string | type string
2240+
008: 19:20 | string | type string
2241+
009: 20:10 | a | var a string
2242+
010: 20:14 | b | var b string
2243+
011: 25: 2 | add | func main.addInt2(i int, j int)
2244+
012: 26: 2 | add | var main.addInt3 func(i int, j int, k int)
2245+
013: 27: 2 | add | func main.add__4(a string, b string) string`)
2246+
}

0 commit comments

Comments
 (0)