Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cl: record def for ast.OverloadFuncDecl #1866

Merged
merged 1 commit into from
Apr 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions cl/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ type Recorder interface {
// *ast.ImportSpec *PkgName for imports without renames
// *ast.CaseClause type-specific *Var for each type switch case clause (incl. default)
// *ast.Field anonymous parameter *Var (incl. unnamed results)
// *ast.FunLit function literal in *ast.OverloadFuncDecl
//
Implicit(node ast.Node, obj types.Object)

Expand Down Expand Up @@ -1085,7 +1086,7 @@ func preloadFile(p *gogen.Package, ctx *blockCtx, f *ast.File, goFile string, ge
}
recv = otyp
if ctx.rec != nil {
ctx.rec.Refer(recv, recv.Name)
ctx.rec.ReferUse(recv, recv.Name)
}
}
onames := make([]string, 0, 4)
Expand All @@ -1103,7 +1104,7 @@ func preloadFile(p *gogen.Package, ctx *blockCtx, f *ast.File, goFile string, ge
ctx.lbinames = append(ctx.lbinames, expr.Name)
exov = true
if ctx.rec != nil {
ctx.rec.Refer(expr, expr.Name)
ctx.rec.ReferUse(expr, expr.Name)
}
case *ast.SelectorExpr:
if d.Recv == nil {
Expand All @@ -1120,8 +1121,8 @@ func preloadFile(p *gogen.Package, ctx *blockCtx, f *ast.File, goFile string, ge
ctx.lbinames = append(ctx.lbinames, recv)
exov = true
if ctx.rec != nil {
ctx.rec.Refer(rtyp, rtyp.Name)
ctx.rec.Refer(expr.Sel, rtyp.Name+"."+expr.Sel.Name)
ctx.rec.ReferUse(rtyp, rtyp.Name)
ctx.rec.ReferUse(expr.Sel, rtyp.Name+"."+expr.Sel.Name)
}
case *ast.FuncLit:
if d.Recv != nil && !d.Operator {
Expand All @@ -1131,9 +1132,13 @@ func preloadFile(p *gogen.Package, ctx *blockCtx, f *ast.File, goFile string, ge
name1 := overloadFuncName(name.Name, idx)
onames = append(onames, "") // const Gopo_xxx = "xxxInt,,xxxFloat"
ctx.lbinames = append(ctx.lbinames, name1)
id := &ast.Ident{NamePos: expr.Pos(), Name: name1}
if ctx.rec != nil {
ctx.rec.ReferDef(id, expr)
}
preloadFuncDecl(&ast.FuncDecl{
Doc: d.Doc,
Name: &ast.Ident{NamePos: expr.Pos(), Name: name1},
Name: id,
Type: expr.Type,
Body: expr.Body,
})
Expand All @@ -1160,6 +1165,9 @@ func preloadFile(p *gogen.Package, ctx *blockCtx, f *ast.File, goFile string, ge
},
})
ctx.lbinames = append(ctx.lbinames, oname)
if ctx.rec != nil {
ctx.rec.ReferDef(d.Name, d)
}
}

default:
Expand Down
53 changes: 44 additions & 9 deletions cl/recorder.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,24 +29,58 @@ import (

type goxRecorder struct {
Recorder
types map[ast.Expr]types.TypeAndValue
refers map[string][]*ast.Ident
types map[ast.Expr]types.TypeAndValue
referDefs map[*ast.Ident]ast.Node
referUses map[string][]*ast.Ident
}

func newRecorder(rec Recorder) *goxRecorder {
types := make(map[ast.Expr]types.TypeAndValue)
refers := make(map[string][]*ast.Ident)
return &goxRecorder{rec, types, refers}
referDefs := make(map[*ast.Ident]ast.Node)
referUses := make(map[string][]*ast.Ident)
return &goxRecorder{rec, types, referDefs, referUses}
}

// Refer maps identifiers to name for ast.OverloadFuncDecl.
func (p *goxRecorder) Refer(ident *ast.Ident, name string) {
p.refers[name] = append(p.refers[name], ident)
// Refer uses maps identifiers to name for ast.OverloadFuncDecl.
func (p *goxRecorder) ReferUse(ident *ast.Ident, name string) {
p.referUses[name] = append(p.referUses[name], ident)
}

// Refer def maps for ast.FuncLit or ast.OverloadFuncDecl.
func (p *goxRecorder) ReferDef(ident *ast.Ident, node ast.Node) {
p.referDefs[ident] = node
}

// Complete computes the types record.
func (p *goxRecorder) Complete(scope *types.Scope) {
for name, idents := range p.refers {
for id, node := range p.referDefs {
switch fn := node.(type) {
case *ast.FuncLit:
if obj := scope.Lookup(id.Name); obj != nil {
p.recordFuncLit(fn, obj.Type())
p.Implicit(node, obj)
}
case *ast.OverloadFuncDecl:
if fn.Recv == nil {
if obj := scope.Lookup(id.Name); obj != nil {
p.Def(id, obj)
}
} else {
if obj := scope.Lookup(fn.Recv.List[0].Type.(*ast.Ident).Name); obj != nil {
if named, ok := obj.Type().(*types.Named); ok {
n := named.NumMethods()
for i := 0; i < n; i++ {
if m := named.Method(i); m.Name() == id.Name {
p.Def(id, m)
break
}
}
}
}
}
}
}
for name, idents := range p.referUses {
pos := strings.Index(name, ".")
if pos == -1 {
if obj := scope.Lookup(name); obj != nil {
Expand All @@ -71,7 +105,8 @@ func (p *goxRecorder) Complete(scope *types.Scope) {
}
}
p.types = nil
p.refers = nil
p.referDefs = nil
p.referUses = nil
}

// Member maps identifiers to the objects they denote.
Expand Down
1 change: 1 addition & 0 deletions x/typesutil/gopinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ type Info struct {
// *ast.ImportSpec *PkgName for imports without renames
// *ast.CaseClause type-specific *Var for each type switch case clause (incl. default)
// *ast.Field anonymous parameter *Var (incl. unnamed results)
// *ast.FunLit function literal in *ast.OverloadFuncDecl
//
Implicits map[ast.Node]types.Object

Expand Down
149 changes: 124 additions & 25 deletions x/typesutil/info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2018,22 +2018,26 @@ Mul 100,200,300
008: 7: 9 | a *ast.Ident | var : float64 | variable
009: 7: 9 | a * b *ast.BinaryExpr | value : float64 | value
010: 7:13 | b *ast.Ident | var : float64 | variable
011: 13:15 | int *ast.Ident | type : int | type
012: 13:20 | int *ast.Ident | type : int | type
013: 14:10 | x *ast.Ident | var : int | variable
014: 14:10 | x * y *ast.BinaryExpr | value : int | value
015: 14:10 | x * y * z *ast.BinaryExpr | value : int | value
016: 14:14 | y *ast.Ident | var : int | variable
017: 14:18 | z *ast.Ident | var : int | variable
018: 18: 1 | Mul *ast.Ident | value : func(a int, b int) int | value
019: 18: 1 | Mul 100, 200 *ast.CallExpr | value : int | value
020: 18: 5 | 100 *ast.BasicLit | value : untyped int = 100 | constant
021: 18: 9 | 200 *ast.BasicLit | value : untyped int = 200 | constant
022: 19: 1 | Mul *ast.Ident | value : func(x int, y int, z int) int | value
023: 19: 1 | Mul 100, 200, 300 *ast.CallExpr | value : int | value
024: 19: 5 | 100 *ast.BasicLit | value : untyped int = 100 | constant
025: 19: 9 | 200 *ast.BasicLit | value : untyped int = 200 | constant
026: 19:13 | 300 *ast.BasicLit | value : untyped int = 300 | constant
011: 13: 2 | func(x, y, z int) int *ast.FuncType | type : func(x int, y int, z int) int | type
012: 13: 2 | func(x, y, z int) int {
return x * y * z
} *ast.FuncLit | value : func(x int, y int, z int) int | value
013: 13:15 | int *ast.Ident | type : int | type
014: 13:20 | int *ast.Ident | type : int | type
015: 14:10 | x *ast.Ident | var : int | variable
016: 14:10 | x * y *ast.BinaryExpr | value : int | value
017: 14:10 | x * y * z *ast.BinaryExpr | value : int | value
018: 14:14 | y *ast.Ident | var : int | variable
019: 14:18 | z *ast.Ident | var : int | variable
020: 18: 1 | Mul *ast.Ident | value : func(a int, b int) int | value
021: 18: 1 | Mul 100, 200 *ast.CallExpr | value : int | value
022: 18: 5 | 100 *ast.BasicLit | value : untyped int = 100 | constant
023: 18: 9 | 200 *ast.BasicLit | value : untyped int = 200 | constant
024: 19: 1 | Mul *ast.Ident | value : func(x int, y int, z int) int | value
025: 19: 1 | Mul 100, 200, 300 *ast.CallExpr | value : int | value
026: 19: 5 | 100 *ast.BasicLit | value : untyped int = 100 | constant
027: 19: 9 | 200 *ast.BasicLit | value : untyped int = 200 | constant
028: 19:13 | 300 *ast.BasicLit | value : untyped int = 300 | constant
== defs ==
000: 0: 0 | Gopo_Mul | const main.Gopo_Mul untyped string
001: 2: 6 | MulInt | func main.MulInt(a int, b int) int
Expand All @@ -2042,11 +2046,12 @@ Mul 100,200,300
004: 6: 6 | MulFloat | func main.MulFloat(a float64, b float64) float64
005: 6:15 | a | var a float64
006: 6:18 | b | var b float64
007: 13: 2 | Mul__2 | func main.Mul__2(x int, y int, z int) int
008: 13: 7 | x | var x int
009: 13:10 | y | var y int
010: 13:13 | z | var z int
011: 18: 1 | main | func main.main()
007: 10: 6 | Mul | func main.Mul(__gop_overload_args__ interface{_()})
008: 13: 2 | Mul__2 | func main.Mul__2(x int, y int, z int) int
009: 13: 7 | x | var x int
010: 13:10 | y | var y int
011: 13:13 | z | var z int
012: 18: 1 | main | func main.main()
== uses ==
000: 2:18 | int | type int
001: 2:23 | int | type int
Expand Down Expand Up @@ -2120,10 +2125,11 @@ var d = a.mul(c)
005: 9: 7 | a | var a *main.foo
006: 9:15 | mulFoo | func (*main.foo).mulFoo(b *main.foo) *main.foo
007: 9:22 | b | var b *main.foo
008: 18: 5 | a | var main.a *main.foo
009: 18: 8 | b | var main.b *main.foo
010: 19: 5 | c | var main.c *main.foo
011: 20: 5 | d | var main.d *main.foo
008: 13:12 | mul | func (main.foo).mul(__gop_overload_args__ interface{_()})
009: 18: 5 | a | var main.a *main.foo
010: 18: 8 | b | var main.b *main.foo
011: 19: 5 | c | var main.c *main.foo
012: 20: 5 | d | var main.d *main.foo
== uses ==
000: 5:10 | foo | type main.foo struct{}
001: 5:24 | int | type int
Expand All @@ -2145,3 +2151,96 @@ var d = a.mul(c)
017: 20:11 | mul | func (*main.foo).mulFoo(b *main.foo) *main.foo
018: 20:15 | c | var main.c *main.foo`)
}

func TestGopOverloadDecl(t *testing.T) {
testGopInfo(t, `
func addInt0() {
}

func addInt1(i int) {
}

func addInt2(i, j int) {
}

var addInt3 = func(i, j, k int) {
}

func add = (
addInt0
addInt1
addInt2
addInt3
func(a, b string) string {
return a + b
}
)

func init() {
add 100, 200
add 100, 200, 300
add("hello", "world")
}
`, ``, `== types ==
000: 0: 0 | "addInt0,addInt1,addInt2,addInt3," *ast.BasicLit | value : untyped string = "addInt0,addInt1,addInt2,addInt3," | constant
001: 5:16 | int *ast.Ident | type : int | type
002: 8:19 | int *ast.Ident | type : int | type
003: 11:15 | func(i, j, k int) *ast.FuncType | type : func(i int, j int, k int) | type
004: 11:15 | func(i, j, k int) {
} *ast.FuncLit | value : func(i int, j int, k int) | value
005: 11:28 | int *ast.Ident | type : int | type
006: 19: 2 | func(a, b string) string *ast.FuncType | type : func(a string, b string) string | type
007: 19: 2 | func(a, b string) string {
return a + b
} *ast.FuncLit | value : func(a string, b string) string | value
008: 19:12 | string *ast.Ident | type : string | type
009: 19:20 | string *ast.Ident | type : string | type
010: 20:10 | a *ast.Ident | var : string | variable
011: 20:10 | a + b *ast.BinaryExpr | value : string | value
012: 20:14 | b *ast.Ident | var : string | variable
013: 25: 2 | add *ast.Ident | value : func(i int, j int) | value
014: 25: 2 | add 100, 200 *ast.CallExpr | void : () | no value
015: 25: 6 | 100 *ast.BasicLit | value : untyped int = 100 | constant
016: 25:11 | 200 *ast.BasicLit | value : untyped int = 200 | constant
017: 26: 2 | add *ast.Ident | var : func(i int, j int, k int) | variable
018: 26: 2 | add 100, 200, 300 *ast.CallExpr | void : () | no value
019: 26: 6 | 100 *ast.BasicLit | value : untyped int = 100 | constant
020: 26:11 | 200 *ast.BasicLit | value : untyped int = 200 | constant
021: 26:16 | 300 *ast.BasicLit | value : untyped int = 300 | constant
022: 27: 2 | add *ast.Ident | value : func(a string, b string) string | value
023: 27: 2 | add("hello", "world") *ast.CallExpr | value : string | value
024: 27: 6 | "hello" *ast.BasicLit | value : untyped string = "hello" | constant
025: 27:15 | "world" *ast.BasicLit | value : untyped string = "world" | constant
== defs ==
000: 0: 0 | Gopo_add | const main.Gopo_add untyped string
001: 2: 6 | addInt0 | func main.addInt0()
002: 5: 6 | addInt1 | func main.addInt1(i int)
003: 5:14 | i | var i int
004: 8: 6 | addInt2 | func main.addInt2(i int, j int)
005: 8:14 | i | var i int
006: 8:17 | j | var j int
007: 11: 5 | addInt3 | var main.addInt3 func(i int, j int, k int)
008: 11:20 | i | var i int
009: 11:23 | j | var j int
010: 11:26 | k | var k int
011: 14: 6 | add | func main.add(__gop_overload_args__ interface{_()})
012: 19: 2 | add__4 | func main.add__4(a string, b string) string
013: 19: 7 | a | var a string
014: 19:10 | b | var b string
015: 24: 6 | init | func main.init()
== uses ==
000: 5:16 | int | type int
001: 8:19 | int | type int
002: 11:28 | int | type int
003: 15: 2 | addInt0 | func main.addInt0()
004: 16: 2 | addInt1 | func main.addInt1(i int)
005: 17: 2 | addInt2 | func main.addInt2(i int, j int)
006: 18: 2 | addInt3 | var main.addInt3 func(i int, j int, k int)
007: 19:12 | string | type string
008: 19:20 | string | type string
009: 20:10 | a | var a string
010: 20:14 | b | var b string
011: 25: 2 | add | func main.addInt2(i int, j int)
012: 26: 2 | add | var main.addInt3 func(i int, j int, k int)
013: 27: 2 | add | func main.add__4(a string, b string) string`)
}
Loading