Repository: goplus/gop
Pull request #1872 (2024-04-29 15:26:01)

x/typesutil:modify info.Overloads to point to the overload decl
modify info.Overloads to point to the overload decl instead point to overload member
```go
type Info struct {
        ...
	// Overloads maps identifiers to the overload decl object.
	Overloads map[*ast.Ident][]types.Object
}
```
and modify the use of info.Overload in tools in this PR [https://github.com/goplus/tools/pull/270](https://github.com/goplus/tools/pull/270)


Patch:
diff --git a/x/typesutil/gopinfo.go b/x/typesutil/gopinfo.go
index c08530af..2416041e 100644
--- a/x/typesutil/gopinfo.go
+++ b/x/typesutil/gopinfo.go
@@ -136,8 +136,8 @@ type Info struct {
 	// appear in this list.
 	// InitOrder []*Initializer
 
-	// Overloads maps identifiers to the overload objects.
-	Overloads map[*ast.Ident][]types.Object
+	// Overloads maps identifiers to the overload decl object.
+	Overloads map[*ast.Ident]types.Object
 }
 
 // ObjectOf returns the object denoted by the specified id,
@@ -168,6 +168,18 @@ func (info *Info) TypeOf(e ast.Expr) types.Type {
 	return nil
 }
 
+// Returns the overloaded function declaration corresponding to the ident and its overloaded function members
+func (info *Info) OverloadOf(id *ast.Ident) (types.Object, []types.Object) {
+	if obj := info.Overloads[id]; obj != nil {
+		if sig, ok := obj.Type().(*types.Signature); ok {
+			if _, objs := gogen.CheckSigFuncExObjects(sig); len(objs) > 1 {
+				return obj, objs
+			}
+		}
+	}
+	return nil, nil
+}
+
 // -----------------------------------------------------------------------------
 
 type gopRecorder struct {
@@ -255,11 +267,11 @@ func (info gopRecorder) Use(id *ast.Ident, obj types.Object) {
 	}
 	if info.Overloads != nil {
 		if sig, ok := obj.Type().(*types.Signature); ok {
-			if ext, objs := gogen.CheckSigFuncExObjects(sig); len(objs) > 1 {
+			if ext, ok := gogen.CheckSigFuncEx(sig); ok {
 				if debugVerbose {
 					log.Println("==> Overloads:", id, ext)
 				}
-				info.Overloads[id] = objs
+				info.Overloads[id] = obj
 			}
 		}
 	}


Test patch:
diff --git a/x/typesutil/check_test.go b/x/typesutil/check_test.go
index 5e784e16..07da8446 100644
--- a/x/typesutil/check_test.go
+++ b/x/typesutil/check_test.go
@@ -78,7 +78,7 @@ func checkInfo(fset *token.FileSet, files []*ast.File, gofiles []*goast.File) (*
 		Implicits:  make(map[ast.Node]types.Object),
 		Selections: make(map[*ast.SelectorExpr]*types.Selection),
 		Scopes:     make(map[ast.Node]*types.Scope),
-		Overloads:  make(map[*ast.Ident][]types.Object),
+		Overloads:  make(map[*ast.Ident]types.Object),
 	}
 	ginfo := &types.Info{
 		Types:      make(map[goast.Expr]types.TypeAndValue),
@@ -196,3 +196,83 @@ func TestBadFile(t *testing.T) {
 	_ = checker.Files([]*goast.File{{Name: goast.NewIdent("main")}},
 		[]*ast.File{{Name: ast.NewIdent("main")}})
 }
+
+func TestCheckOverload(t *testing.T) {
+	fset := token.NewFileSet()
+	info, ginfo, err := checkFiles(fset, "main.gop", `
+type foo struct {
+}
+
+func (a *foo) mulInt(b int) *foo {
+	return a
+}
+
+func (a *foo) mulFoo(b *foo) *foo {
+	return a
+}
+
+func (foo).mul = (
+	(foo).mulInt
+	(foo).mulFoo
+)
+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
+	}
+)
+
+var a, b *foo
+var c = a.mul(100)
+var d = a.mul(c)
+
+func init() {
+	add 100, 200
+	add 100, 200, 300
+	add("hello", "world")
+}
+`, "", "", "", "")
+	if err != nil || info == nil || ginfo == nil {
+		t.Fatalf("check failed: %v", err)
+	}
+	for use, ovDeclObj := range info.Overloads {
+		o := info.ObjectOf(use)
+		declObj, ovObjs := info.OverloadOf(use)
+		if ovDeclObj != declObj {
+			t.Fatal("bad overload", o)
+		}
+		found := false
+		for _, ovObj := range ovObjs {
+			if o == ovObj {
+				found = true
+				break
+			}
+		}
+		if !found {
+			t.Fatal("bad overload", o)
+		}
+	}
+	for use, o := range info.Uses {
+		declObj, ovObjs := info.OverloadOf(use)
+		if declObj != nil && ovObjs != nil {
+			if info.Overloads[use] == nil {
+				t.Fatal("bad overload", o)
+			}
+		}
+	}
+}
diff --git a/x/typesutil/info_test.go b/x/typesutil/info_test.go
index b82a510a..b059ce71 100644
--- a/x/typesutil/info_test.go
+++ b/x/typesutil/info_test.go
@@ -91,7 +91,7 @@ func parseMixedSource(mod *gopmod.Module, fset *token.FileSet, name, src string,
 		Implicits:  make(map[ast.Node]types.Object),
 		Selections: make(map[*ast.SelectorExpr]*types.Selection),
 		Scopes:     make(map[ast.Node]*types.Scope),
-		Overloads:  make(map[*ast.Ident][]types.Object),
+		Overloads:  make(map[*ast.Ident]types.Object),
 	}
 	ginfo := &types.Info{
 		Types:      make(map[goast.Expr]types.TypeAndValue),
@@ -129,7 +129,7 @@ func parseSource(fset *token.FileSet, filename string, src interface{}, mode par
 		Implicits:  make(map[ast.Node]types.Object),
 		Selections: make(map[*ast.SelectorExpr]*types.Selection),
 		Scopes:     make(map[ast.Node]*types.Scope),
-		Overloads:  make(map[*ast.Ident][]types.Object),
+		Overloads:  make(map[*ast.Ident]types.Object),
 	}
 	check := typesutil.NewChecker(conf, chkOpts, nil, info)
 	err = check.Files(nil, []*ast.File{f})
@@ -179,6 +179,10 @@ func testGopInfoEx(t *testing.T, mod *gopmod.Module, name string, src string, go
 	list = append(list, defsList(fset, info.Defs, true)...)
 	list = append(list, "== uses ==")
 	list = append(list, usesList(fset, info.Uses)...)
+	if len(info.Overloads) > 0 {
+		list = append(list, "== overloads ==")
+		list = append(list, overloadsList(fset, info.Overloads)...)
+	}
 	result := strings.Join(list, "\n")
 	t.Log(result)
 	if result != expect {
@@ -341,6 +345,20 @@ func goUsesList(fset *token.FileSet, uses map[*goast.Ident]types.Object) []strin
 	return sortItems(items)
 }
 
+func overloadsList(fset *token.FileSet, overloads map[*ast.Ident]types.Object) []string {
+	var items []string
+	for expr, obj := range overloads {
+		var buf strings.Builder
+		posn := fset.Position(expr.Pos())
+		// line:col | expr | mode : type = value
+		fmt.Fprintf(&buf, "%2d:%2d | %-19s | %s",
+			posn.Line, posn.Column, expr,
+			obj)
+		items = append(items, buf.String())
+	}
+	return sortItems(items)
+}
+
 /*
 func selectionList(fset *token.FileSet, sels map[*ast.SelectorExpr]*types.Selection) []string {
 	var items []string
@@ -1163,7 +1181,21 @@ func OnKey__a(a, b string, v ...int) {
 023: 33:26 | x                   | var x int
 024: 34: 9 | x                   | var x int
 025: 36: 1 | OnKey               | func main.OnKey__a(a string, b string, v ...int)
-026: 37: 1 | OnKey               | func main.OnKey__a(a string, b string, v ...int)`)
+026: 37: 1 | OnKey               | func main.OnKey__a(a string, b string, v ...int)
+== overloads ==
+000: 14: 1 | OnKey               | func main.OnKey(__gop_overload_args__ interface{_()})
+001: 16: 1 | OnKey               | func main.OnKey(__gop_overload_args__ interface{_()})
+002: 18: 1 | OnKey               | func main.OnKey(__gop_overload_args__ interface{_()})
+003: 20: 1 | OnKey               | func main.OnKey(__gop_overload_args__ interface{_()})
+004: 22: 1 | OnKey               | func main.OnKey(__gop_overload_args__ interface{_()})
+005: 24: 1 | OnKey               | func main.OnKey(__gop_overload_args__ interface{_()})
+006: 26: 1 | OnKey               | func main.OnKey(__gop_overload_args__ interface{_()})
+007: 28: 1 | OnKey               | func main.OnKey(__gop_overload_args__ interface{_()})
+008: 30: 1 | OnKey               | func main.OnKey(__gop_overload_args__ interface{_()})
+009: 32: 1 | OnKey               | func main.OnKey(__gop_overload_args__ interface{_()})
+010: 33: 1 | OnKey               | func main.OnKey(__gop_overload_args__ interface{_()})
+011: 36: 1 | OnKey               | func main.OnKey(__gop_overload_args__ interface{_()})
+012: 37: 1 | OnKey               | func main.OnKey(__gop_overload_args__ interface{_()})`)
 }
 
 func TestMixedOverload2(t *testing.T) {
@@ -1387,7 +1419,18 @@ func OnKey__a(a, b string, v ...int) {
 028: 31: 3 | onKey               | func (*main.N).OnKey__6(a []string, b []string, fn func(key string))
 029: 31:16 | nil                 | nil
 030: 33: 1 | n                   | var n *main.N
-031: 33: 3 | onKey               | func (*main.N).OnKey__8(x int, y int)`)
+031: 33: 3 | onKey               | func (*main.N).OnKey__8(x int, y int)
+== overloads ==
+000: 15: 3 | onKey               | func (main.N).OnKey(__gop_overload_args__ interface{_()})
+001: 17: 3 | onKey               | func (main.N).OnKey(__gop_overload_args__ interface{_()})
+002: 19: 3 | onKey               | func (main.N).OnKey(__gop_overload_args__ interface{_()})
+003: 21: 3 | onKey               | func (main.N).OnKey(__gop_overload_args__ interface{_()})
+004: 23: 3 | onKey               | func (main.N).OnKey(__gop_overload_args__ interface{_()})
+005: 25: 3 | onKey               | func (main.N).OnKey(__gop_overload_args__ interface{_()})
+006: 27: 3 | onKey               | func (main.N).OnKey(__gop_overload_args__ interface{_()})
+007: 29: 3 | onKey               | func (main.N).OnKey(__gop_overload_args__ interface{_()})
+008: 31: 3 | onKey               | func (main.N).OnKey(__gop_overload_args__ interface{_()})
+009: 33: 3 | onKey               | func (main.N).OnKey(__gop_overload_args__ interface{_()})`)
 }
 
 func TestMixedOverload3(t *testing.T) {
@@ -1432,7 +1475,12 @@ func (p *N) Test__1(n int) {
 003:  5: 1 | n                   | var n main.N
 004:  5: 3 | test                | func (*main.N).Test__0()
 005:  6: 1 | n                   | var n main.N
-006:  6: 3 | test                | func (*main.N).Test__1(n int)`)
+006:  6: 3 | test                | func (*main.N).Test__1(n int)
+== overloads ==
+000:  2: 1 | Test                | func main.Test(__gop_overload_args__ interface{_()})
+001:  3: 1 | Test                | func main.Test(__gop_overload_args__ interface{_()})
+002:  5: 3 | test                | func (main.N).Test(__gop_overload_args__ interface{_()})
+003:  6: 3 | test                | func (main.N).Test(__gop_overload_args__ interface{_()})`)
 }
 
 func TestOverloadNamed(t *testing.T) {
@@ -1476,7 +1524,12 @@ d := bar.Var(bar.M)
 010:  7: 6 | bar                 | package bar ("github.com/goplus/gop/cl/internal/overload/bar")
 011:  7:10 | Var                 | func github.com/goplus/gop/cl/internal/overload/bar.Gopx_Var_Cast__1[T map[string]any]() *github.com/goplus/gop/cl/internal/overload/bar.Var__1[T]
 012:  7:14 | bar                 | package bar ("github.com/goplus/gop/cl/internal/overload/bar")
-013:  7:18 | M                   | type github.com/goplus/gop/cl/internal/overload/bar.M = map[string]any`)
+013:  7:18 | M                   | type github.com/goplus/gop/cl/internal/overload/bar.M = map[string]any
+== overloads ==
+000:  4:11 | Var                 | type github.com/goplus/gop/cl/internal/overload/bar.Var = func(__gop_overload_args__ interface{_()})
+001:  5:11 | Var                 | type github.com/goplus/gop/cl/internal/overload/bar.Var = func(__gop_overload_args__ interface{_()})
+002:  6:10 | Var                 | type github.com/goplus/gop/cl/internal/overload/bar.Var = func(__gop_overload_args__ interface{_()})
+003:  7:10 | Var                 | type github.com/goplus/gop/cl/internal/overload/bar.Var = func(__gop_overload_args__ interface{_()})`)
 }
 
 func TestMixedOverloadNamed(t *testing.T) {
@@ -1536,7 +1589,12 @@ func Gopx_Var_Cast__1[T map[string]any]() *Var__1[T] {
 004:  4: 6 | Var                 | func main.Gopx_Var_Cast__0[T main.basetype]() *main.Var__0[T]
 005:  4:10 | string              | type string
 006:  5: 6 | Var                 | func main.Gopx_Var_Cast__1[T map[string]any]() *main.Var__1[T]
-007:  5:10 | M                   | type main.M = map[string]any`)
+007:  5:10 | M                   | type main.M = map[string]any
+== overloads ==
+000:  2: 7 | Var                 | type main.Var = func(__gop_overload_args__ interface{_()})
+001:  3: 7 | Var                 | type main.Var = func(__gop_overload_args__ interface{_()})
+002:  4: 6 | Var                 | type main.Var = func(__gop_overload_args__ interface{_()})
+003:  5: 6 | Var                 | type main.Var = func(__gop_overload_args__ interface{_()})`)
 }
 
 func TestMixedRawNamed(t *testing.T) {
@@ -1675,7 +1733,11 @@ func onCloned() {
 009: 14: 8 | info                | type main.info struct{x int; y int}
 010: 15: 2 | clone               | func github.com/goplus/gop/cl/internal/spx.Gopt_Sprite_Clone__1(sprite interface{}, data interface{})
 011: 15: 9 | info                | type main.info struct{x int; y int}
-012: 19: 2 | say                 | func (*github.com/goplus/gop/cl/internal/spx.Sprite).Say(msg string, secs ...float64)`)
+012: 19: 2 | say                 | func (*github.com/goplus/gop/cl/internal/spx.Sprite).Say(msg string, secs ...float64)
+== overloads ==
+000: 13: 2 | clone               | func (github.com/goplus/gop/cl/internal/spx.Sprite).Clone(__gop_overload_args__ interface{_()})
+001: 14: 2 | clone               | func (github.com/goplus/gop/cl/internal/spx.Sprite).Clone(__gop_overload_args__ interface{_()})
+002: 15: 2 | clone               | func (github.com/goplus/gop/cl/internal/spx.Sprite).Clone(__gop_overload_args__ interface{_()})`)
 }
 
 func TestScopesInfo(t *testing.T) {
@@ -2069,7 +2131,10 @@ Mul 100,200,300
 013: 14:14 | y                   | var y int
 014: 14:18 | z                   | var z int
 015: 18: 1 | Mul                 | func main.MulInt(a int, b int) int
-016: 19: 1 | Mul                 | func main.Mul__2(x int, y int, z int) int`)
+016: 19: 1 | Mul                 | func main.Mul__2(x int, y int, z int) int
+== overloads ==
+000: 18: 1 | Mul                 | func main.Mul(__gop_overload_args__ interface{_()})
+001: 19: 1 | Mul                 | func main.Mul(__gop_overload_args__ interface{_()})`)
 
 	testGopInfo(t, `
 type foo struct {
@@ -2149,7 +2214,11 @@ var d = a.mul(c)
 015: 19:11 | mul                 | func (*main.foo).mulInt(b int) *main.foo
 016: 20: 9 | a                   | var main.a *main.foo
 017: 20:11 | mul                 | func (*main.foo).mulFoo(b *main.foo) *main.foo
-018: 20:15 | c                   | var main.c *main.foo`)
+018: 20:15 | c                   | var main.c *main.foo
+== overloads ==
+000: 19:11 | mul                 | func (main.foo).mul(__gop_overload_args__ interface{_()})
+001: 20:11 | mul                 | func (main.foo).mul(__gop_overload_args__ interface{_()})`)
+
 }
 
 func TestGopOverloadDecl(t *testing.T) {
@@ -2242,7 +2311,11 @@ func init() {
 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`)
+013: 27: 2 | add                 | func main.add__4(a string, b string) string
+== overloads ==
+000: 25: 2 | add                 | func main.add(__gop_overload_args__ interface{_()})
+001: 26: 2 | add                 | func main.add(__gop_overload_args__ interface{_()})
+002: 27: 2 | add                 | func main.add(__gop_overload_args__ interface{_()})`)
 
 	testGopInfo(t, `
 func add = (
@@ -2304,5 +2377,8 @@ func init() {
 006:  7:10 | a                   | var a string
 007:  7:14 | b                   | var b string
 008: 12: 2 | add                 | func main.add__0(a int, b int) int
-009: 13: 2 | add                 | func main.add__1(a string, b string) string`)
+009: 13: 2 | add                 | func main.add__1(a string, b string) string
+== overloads ==
+000: 12: 2 | add                 | func main.add(__gop_overload_args__ interface{_()})
+001: 13: 2 | add                 | func main.add(__gop_overload_args__ interface{_()})`)
 }