diff --git a/cl/compile.go b/cl/compile.go index e1581eef1..fc4018638 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -1071,13 +1071,26 @@ func preloadFile(p *gogen.Package, ctx *blockCtx, f *ast.File, goFile string, ge case *ast.OverloadFuncDecl: var recv *ast.Ident + if ctx.classRecv != nil { // in class file (.spx/.gmx) + if recv := d.Recv; recv == nil || len(recv.List) == 0 { + d.Recv = &ast.FieldList{ + List: []*ast.Field{ + { + Type: ctx.classRecv.List[0].Type.(*ast.StarExpr).X, + }, + }, + } + d.IsClass = true + } + } if d.Recv != nil { - otyp, ok := d.Recv.List[0].Type.(*ast.Ident) + var ok bool + recv, ok = d.Recv.List[0].Type.(*ast.Ident) if !ok { ctx.handleErrorf(d.Recv.List[0].Type.Pos(), "invalid recv type %v", ctx.LoadExpr(d.Recv.List[0].Type)) break } - recv = otyp + ctx.lbinames = append(ctx.lbinames, recv) if ctx.rec != nil { ctx.rec.ReferUse(recv, recv.Name) } @@ -1086,18 +1099,27 @@ func preloadFile(p *gogen.Package, ctx *blockCtx, f *ast.File, goFile string, ge exov := false name := d.Name LoopFunc: + for idx, fn := range d.Funcs { switch expr := fn.(type) { case *ast.Ident: - if d.Recv != nil && !d.Operator { + if d.Recv != nil && !d.Operator && !d.IsClass { ctx.handleErrorf(expr.Pos(), "invalid method %v", ctx.LoadExpr(expr)) break LoopFunc } - onames = append(onames, expr.Name) - ctx.lbinames = append(ctx.lbinames, expr.Name) exov = true + if d.IsClass { + onames = append(onames, "."+expr.Name) + } else { + onames = append(onames, expr.Name) + ctx.lbinames = append(ctx.lbinames, expr.Name) + } if ctx.rec != nil { - ctx.rec.ReferUse(expr, expr.Name) + if d.IsClass { + ctx.rec.ReferUse(expr, recv.Name+"."+expr.Name) + } else { + ctx.rec.ReferUse(expr, expr.Name) + } } case *ast.SelectorExpr: if d.Recv == nil { @@ -1111,14 +1133,13 @@ func preloadFile(p *gogen.Package, ctx *blockCtx, f *ast.File, goFile string, ge } onames = append(onames, "."+expr.Sel.Name) - ctx.lbinames = append(ctx.lbinames, recv) exov = true if ctx.rec != nil { 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 { + if d.Recv != nil && !d.Operator && !d.IsClass { ctx.handleErrorf(expr.Pos(), "invalid method %v", ctx.LoadExpr(expr)) break LoopFunc } diff --git a/cl/compile_spx_test.go b/cl/compile_spx_test.go index d205537b6..617d0073e 100644 --- a/cl/compile_spx_test.go +++ b/cl/compile_spx_test.go @@ -1397,6 +1397,42 @@ type foo struct { `, "foo.gox") } +func TestGopxOverload(t *testing.T) { + gopClTestFile(t, ` +func addString(a, b string) string { + return a + b +} + +func addInt(a, b int) int { + return a + b +} + +func add = ( + addInt + func(a, b float64) float64 { + return a + b + } + addString +) +`, `package main + +const Gopo_Rect_add = ".addInt,,.addString" + +type Rect struct { +} + +func (this *Rect) addString(a string, b string) string { + return a + b +} +func (this *Rect) addInt(a int, b int) int { + return a + b +} +func (this *Rect) add__1(a float64, b float64) float64 { + return a + b +} +`, "Rect.gox") +} + func TestClassFileGopx(t *testing.T) { gopClTestFile(t, ` var ( diff --git a/x/typesutil/info_test.go b/x/typesutil/info_test.go index b059ce71e..ef1ca10e2 100644 --- a/x/typesutil/info_test.go +++ b/x/typesutil/info_test.go @@ -2382,3 +2382,69 @@ func init() { 000: 12: 2 | add | func main.add(__gop_overload_args__ interface{_()}) 001: 13: 2 | add | func main.add(__gop_overload_args__ interface{_()})`) } + +func TestGoxOverloadInfo(t *testing.T) { + testSpxInfo(t, "Rect.gox", ` +func addInt(a, b int) int { + return a + b +} + +func addString(a, b string) string { + return a + b +} + +func add = ( + addInt + func(a, b float64) float64 { + return a + b + } + addString +) +`, `== types == +000: 0: 0 | ".addInt,,.addString" *ast.BasicLit | value : untyped string = ".addInt,,.addString" | constant +001: 0: 0 | Rect *ast.Ident | type : main.Rect | type +002: 2:18 | int *ast.Ident | type : int | type +003: 2:23 | int *ast.Ident | type : int | type +004: 3: 9 | a *ast.Ident | var : int | variable +005: 3: 9 | a + b *ast.BinaryExpr | value : int | value +006: 3:13 | b *ast.Ident | var : int | variable +007: 6:21 | string *ast.Ident | type : string | type +008: 6:29 | string *ast.Ident | type : string | type +009: 7: 9 | a *ast.Ident | var : string | variable +010: 7: 9 | a + b *ast.BinaryExpr | value : string | value +011: 7:13 | b *ast.Ident | var : string | variable +012: 12:12 | float64 *ast.Ident | type : float64 | type +013: 12:21 | float64 *ast.Ident | type : float64 | type +014: 13:10 | a *ast.Ident | var : float64 | variable +015: 13:10 | a + b *ast.BinaryExpr | value : float64 | value +016: 13:14 | b *ast.Ident | var : float64 | variable +== defs == +000: 0: 0 | Gopo_Rect_add | const main.Gopo_Rect_add untyped string +001: 0: 0 | this | var this *main.Rect +002: 2: 6 | addInt | func (*main.Rect).addInt(a int, b int) int +003: 2:13 | a | var a int +004: 2:16 | b | var b int +005: 6: 6 | addString | func (*main.Rect).addString(a string, b string) string +006: 6:16 | a | var a string +007: 6:19 | b | var b string +008: 10: 6 | add | func (main.Rect).add(__gop_overload_args__ interface{_()}) +009: 12: 2 | add__1 | func (*main.Rect).add__1(a float64, b float64) float64 +010: 12: 7 | a | var a float64 +011: 12:10 | b | var b float64 +== uses == +000: 0: 0 | Rect | type main.Rect struct{} +001: 2:18 | int | type int +002: 2:23 | int | type int +003: 3: 9 | a | var a int +004: 3:13 | b | var b int +005: 6:21 | string | type string +006: 6:29 | string | type string +007: 7: 9 | a | var a string +008: 7:13 | b | var b string +009: 11: 2 | addInt | func (*main.Rect).addInt(a int, b int) int +010: 12:12 | float64 | type float64 +011: 12:21 | float64 | type float64 +012: 13:10 | a | var a float64 +013: 13:14 | b | var b float64 +014: 15: 2 | addString | func (*main.Rect).addString(a string, b string) string`) +}