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

x/typesutil:modify info.Overloads to point to the overload decl #1872

Merged
merged 2 commits into from
May 3, 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
82 changes: 81 additions & 1 deletion x/typesutil/check_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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)
}
}
}
}
20 changes: 16 additions & 4 deletions x/typesutil/gopinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
luoliwoshang marked this conversation as resolved.
Show resolved Hide resolved
log.Println("==> Overloads:", id, ext)
}
info.Overloads[id] = objs
info.Overloads[id] = obj
}
}
}
Expand Down
100 changes: 88 additions & 12 deletions x/typesutil/info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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})
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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 = (
Expand Down Expand Up @@ -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{_()})`)
}
Loading