diff --git a/codebuild.go b/codebuild.go index a773c057..e83c50bc 100644 --- a/codebuild.go +++ b/codebuild.go @@ -1421,10 +1421,29 @@ func (p *CodeBuilder) Member(name string, lhs bool, src ...ast.Node) (kind Membe if debugInstr { log.Println("Member", name, lhs, "//", arg.Type) } + var isTypeType bool + at := arg.Type + if t, ok := at.(*TypeType); ok { + at = t.typ + isTypeType = true + } if lhs { - kind = p.refMember(arg.Type, name, arg.Val) + kind = p.refMember(at, name, arg.Val) } else { - kind = p.findMember(arg.Type, name, arg.Val, srcExpr) + kind = p.findMember(at, name, arg.Val, srcExpr) + } + if isTypeType && kind == MemberMethod { + e := p.Get(-1) + if sig, ok := e.Type.(*types.Signature); ok { + var vars []*types.Var + vars = append(vars, types.NewVar(token.NoPos, nil, "recv", at)) + sp := sig.Params() + spLen := sp.Len() + for i := 0; i < spLen; i++ { + vars = append(vars, sp.At(i)) + } + e.Type = types.NewSignature(nil, types.NewTuple(vars...), sig.Results(), sig.Variadic()) + } } if kind != MemberInvalid { return diff --git a/package_test.go b/package_test.go index 9c90db11..91d9b1cd 100644 --- a/package_test.go +++ b/package_test.go @@ -2612,6 +2612,47 @@ func main() { } } +func TestInterfaceMethodVarCall(t *testing.T) { + pkg := newMainPackage() + fmt := pkg.Import("fmt") + tyInt := types.Typ[types.Int] + tyString := types.Typ[types.String] + methods := []*types.Func{ + types.NewFunc(token.NoPos, pkg.Types, "bar", types.NewSignature(nil, types.NewTuple(types.NewVar(token.NoPos, nil, "info", tyString)), nil, false)), + } + tyInterf := types.NewInterfaceType(methods, nil).Complete() + foo := pkg.NewType("foo").InitType(pkg, tyInterf) + _ = foo + tt := pkg.NewType("t").InitType(pkg, tyInt) + recv := pkg.NewParam(token.NoPos, "tt", tt) + pkg.NewFunc(recv, "bar", types.NewTuple(types.NewVar(token.NoPos, nil, "info", tyString)), nil, false).BodyStart(pkg). + Val(fmt.Ref("Println")).Val(recv).Val(pkg.NewParam(token.NoPos, "info", tyString)).Call(2).EndStmt(). // fmt.Println(v) + End() + pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg). + DefineVarStart(0, "v").Val(ctxRef(pkg, "foo")).MemberVal("bar").EndInit(1). + NewVarStart(tt, "tt").Val(123).EndInit(1). + Val(ctxRef(pkg, "v")).Val(ctxRef(pkg, "tt")).Val("hello").Call(2, false). + EndStmt().End() + domTest(t, pkg, `package main + +import fmt "fmt" + +type foo interface { + bar(info string) +} +type t int + +func (tt t) bar(info string) { + fmt.Println(tt, info) +} +func main() { + v := foo.bar + var tt t = 123 + v(tt, "hello") +} +`) +} + func TestTypeNamed(t *testing.T) { pkg := newMainPackage() fields := []*types.Var{