Skip to content

Commit 913473f

Browse files
vbauersterfatih
authored andcommitted
Full signature: correct population for unnamed method receiver (#8)
* Full signature: don't omit parens for multiple return funcs
1 parent e21f4a5 commit 913473f

File tree

2 files changed

+63
-39
lines changed

2 files changed

+63
-39
lines changed

astcontext/funcs.go

+30-39
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ func (f *Func) IsLiteral() bool {
6969
// be of type *ast.FuncDecl or *ast.FuncLit
7070
func NewFuncSignature(node ast.Node) *FuncSignature {
7171
getParams := func(list []*ast.Field) string {
72-
var named bool
7372
buf := new(bytes.Buffer)
7473
for i, p := range list {
7574
for j, n := range p.Names {
@@ -80,82 +79,74 @@ func NewFuncSignature(node ast.Node) *FuncSignature {
8079
}
8180

8281
if len(p.Names) != 0 {
83-
named = true
8482
buf.WriteString(" ")
8583
}
8684

8785
types.WriteExpr(buf, p.Type)
8886

8987
if len(list) != i+1 {
90-
named = true
9188
buf.WriteString(", ")
9289
}
9390
}
94-
if named {
95-
return fmt.Sprintf("(%s)", buf.String())
96-
}
9791
return buf.String()
9892
}
93+
isResultsNeedParens := func(list []*ast.Field) bool {
94+
if len(list) > 1 {
95+
return true
96+
}
97+
return len(list) != 0 && len(list[0].Names) != 0
98+
}
9999

100100
switch x := node.(type) {
101101
case *ast.FuncDecl:
102102
sig := &FuncSignature{
103103
Name: x.Name.Name,
104104
}
105105

106-
if x.Type.Params != nil {
107-
sig.In = getParams(x.Type.Params.List)
108-
}
109-
if x.Type.Results != nil {
110-
sig.Out = getParams(x.Type.Results.List)
111-
}
106+
buf := bytes.NewBufferString("func ")
107+
112108
if x.Recv != nil {
113109
sig.Recv = getParams(x.Recv.List)
110+
fmt.Fprintf(buf, "(%s) ", sig.Recv)
114111
}
115112

116-
full := "func "
117-
118-
if sig.Recv != "" {
119-
full += fmt.Sprintf("%s ", sig.Recv)
120-
}
121-
122-
full += fmt.Sprintf("%s", sig.Name)
113+
fmt.Fprintf(buf, "%s", sig.Name)
123114

124-
if sig.In != "" {
125-
full += fmt.Sprintf("%s", sig.In)
126-
} else {
127-
full += "()"
115+
if x.Type.Params != nil {
116+
sig.In = getParams(x.Type.Params.List)
117+
fmt.Fprintf(buf, "(%s)", sig.In)
128118
}
129119

130-
if sig.Out != "" {
131-
full += fmt.Sprintf(" %s", sig.Out)
120+
if x.Type.Results != nil {
121+
sig.Out = getParams(x.Type.Results.List)
122+
if isResultsNeedParens(x.Type.Results.List) {
123+
fmt.Fprintf(buf, " (%s)", sig.Out)
124+
} else {
125+
fmt.Fprintf(buf, " %s", sig.Out)
126+
}
132127
}
133128

134-
sig.Full = full
129+
sig.Full = buf.String()
135130
return sig
136131
case *ast.FuncLit:
137132
sig := &FuncSignature{}
138133

134+
buf := bytes.NewBufferString("func")
135+
139136
if x.Type.Params != nil {
140137
sig.In = getParams(x.Type.Params.List)
138+
fmt.Fprintf(buf, "(%s)", sig.In)
141139
}
142140
if x.Type.Results != nil {
143141
sig.Out = getParams(x.Type.Results.List)
142+
if isResultsNeedParens(x.Type.Results.List) {
143+
fmt.Fprintf(buf, " (%s)", sig.Out)
144+
} else {
145+
fmt.Fprintf(buf, " %s", sig.Out)
146+
}
144147
}
145148

146-
full := "func"
147-
148-
if sig.In != "" {
149-
full += fmt.Sprintf("%s", sig.In)
150-
} else {
151-
full += "()"
152-
}
153-
154-
if sig.Out != "" {
155-
full += fmt.Sprintf(" %s", sig.Out)
156-
}
157-
158-
sig.Full = full
149+
sig.Full = buf.String()
159150
return sig
160151
default:
161152
return &FuncSignature{Full: "UNKNOWN"}

astcontext/funcs_test.go

+33
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,39 @@ func namedMultipleOut() (err error, res string) {
181181
}
182182
}
183183

184+
func TestFunc_Signature_Extra(t *testing.T) {
185+
var src = `package main
186+
type s struct {}
187+
func (a s) valueReceiver() {}
188+
func (s) valueReceiver2() {}
189+
`
190+
191+
testFuncs := []struct {
192+
want string
193+
}{
194+
{want: "func (a s) valueReceiver()"},
195+
{want: "func (s) valueReceiver2()"},
196+
}
197+
198+
opts := &ParserOptions{
199+
Src: []byte(src),
200+
}
201+
parser, err := NewParser(opts)
202+
if err != nil {
203+
t.Fatal(err)
204+
}
205+
206+
funcs := parser.Funcs()
207+
208+
for i, fn := range funcs {
209+
fmt.Printf("[%d] %s\n", i, fn.Signature.Full)
210+
if fn.Signature.Full != testFuncs[i].want {
211+
t.Errorf("function signatures\n\twant: %s\n\tgot : %s",
212+
testFuncs[i].want, fn.Signature)
213+
}
214+
}
215+
}
216+
184217
func TestFuncs_NoFuncs(t *testing.T) {
185218
var src = `package foo`
186219

0 commit comments

Comments
 (0)