Skip to content

Commit

Permalink
avoid name collisions between receiver and params/results
Browse files Browse the repository at this point in the history
Fixes #46
  • Loading branch information
tttoad authored and josharian committed Nov 20, 2022
1 parent df2fb2f commit 2363157
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 2 deletions.
21 changes: 19 additions & 2 deletions impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -349,13 +349,30 @@ var tmpl = template.Must(template.New("test").Parse(stub))
// genStubs won't generate stubs for
// already implemented methods of receiver.
func genStubs(recv string, fns []Func, implemented map[string]bool) []byte {
var buf bytes.Buffer
var recvName string
if recvs := strings.Fields(recv); len(recvs) > 1 {
recvName = recvs[0]
}

// (r *recv) F(r string) {} => (r *recv) F(_ string)
fixParams := func(params []Param) {
for i, p := range params {
if p.Name == recvName {
params[i].Name = "_"
}
}
}

buf := new(bytes.Buffer)
for _, fn := range fns {
if implemented[fn.Name] {
continue
}

fixParams(fn.Params)
fixParams(fn.Res)
meth := Method{Recv: recv, Func: fn}
tmpl.Execute(&buf, meth)
tmpl.Execute(buf, meth)
}

pretty, err := format.Source(buf.Bytes())
Expand Down
42 changes: 42 additions & 0 deletions impl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -647,3 +647,45 @@ func TestStubGenerationForImplemented(t *testing.T) {
})
}
}

func TestStubGenerationForRepeatedName(t *testing.T) {
cases := []struct {
desc string
iface string
recv string
recvPkg string
want string
}{
{
desc: "receiver and in.Params with the same name",
iface: "github.com/josharian/impl/testdata.Interface6",
recv: "arg1 *Implemented",
recvPkg: "testdata",
want: testdata.Interface7Output,
},
{
desc: "receiver and out.Params with the same name",
iface: "github.com/josharian/impl/testdata.Interface6",
recv: "arg3 *Implemented",
recvPkg: "testdata",
want: testdata.Interface8Output,
},
}
for _, tt := range cases {
t.Run(tt.desc, func(t *testing.T) {
fns, err := funcs(tt.iface, ".", tt.recvPkg, WithComments)
if err != nil {
t.Errorf("funcs(%q).err=%v", tt.iface, err)
}

implemented, err := implementedFuncs(fns, tt.recv, "testdata")
if err != nil {
t.Errorf("ifuncs.err=%v", err)
}
src := genStubs(tt.recv, fns, implemented)
if string(src) != tt.want {
t.Errorf("genStubs(\"r *Implemented\", %+#v).src=\n\n%#v\n\nwant\n\n%#v\n\n", fns, string(src), tt.want)
}
})
}
}
19 changes: 19 additions & 0 deletions testdata/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,22 @@ func (r *Implemented) Method2(arg1 string, arg2 testdata.Interface2, arg3 testda
}
`

type Interface6 interface {
// Method is the first method of Interface6.
Method2(arg1 string, arg2 int) (arg3 error)
}

var Interface7Output = `// Method is the first method of Interface6.
func (arg1 *Implemented) Method2(_ string, arg2 int) (arg3 error) {
panic("not implemented") // TODO: Implement
}
`

var Interface8Output = `// Method is the first method of Interface6.
func (arg3 *Implemented) Method2(arg1 string, arg2 int) (_ error) {
panic("not implemented") // TODO: Implement
}
`

0 comments on commit 2363157

Please sign in to comment.