@@ -160,3 +160,142 @@ func TestAnchorID(t *testing.T) {
160
160
t .Errorf ("anchorID(%q) = %q; want %q" , in , got , want )
161
161
}
162
162
}
163
+
164
+ func TestFuncs (t * testing.T ) {
165
+ fset := token .NewFileSet ()
166
+ file , err := parser .ParseFile (fset , "funcs.go" , strings .NewReader (funcsTestFile ), parser .ParseComments )
167
+ if err != nil {
168
+ t .Fatal (err )
169
+ }
170
+ doc , err := NewFromFiles (fset , []* ast.File {file }, "importPath" , Mode (0 ))
171
+ if err != nil {
172
+ t .Fatal (err )
173
+ }
174
+
175
+ for _ , f := range doc .Funcs {
176
+ f .Decl = nil
177
+ }
178
+ for _ , ty := range doc .Types {
179
+ for _ , f := range ty .Funcs {
180
+ f .Decl = nil
181
+ }
182
+ for _ , m := range ty .Methods {
183
+ m .Decl = nil
184
+ }
185
+ }
186
+
187
+ compareFuncs := func (t * testing.T , msg string , got , want * Func ) {
188
+ // ignore Decl and Examples
189
+ got .Decl = nil
190
+ got .Examples = nil
191
+ if ! (got .Doc == want .Doc &&
192
+ got .Name == want .Name &&
193
+ got .Recv == want .Recv &&
194
+ got .Orig == want .Orig &&
195
+ got .Level == want .Level ) {
196
+ t .Errorf ("%s:\n got %+v\n want %+v" , msg , got , want )
197
+ }
198
+ }
199
+
200
+ compareSlices (t , "Funcs" , doc .Funcs , funcsPackage .Funcs , compareFuncs )
201
+ compareSlices (t , "Types" , doc .Types , funcsPackage .Types , func (t * testing.T , msg string , got , want * Type ) {
202
+ if got .Name != want .Name {
203
+ t .Errorf ("%s.Name: got %q, want %q" , msg , got .Name , want .Name )
204
+ } else {
205
+ compareSlices (t , got .Name + ".Funcs" , got .Funcs , want .Funcs , compareFuncs )
206
+ compareSlices (t , got .Name + ".Methods" , got .Methods , want .Methods , compareFuncs )
207
+ }
208
+ })
209
+ }
210
+
211
+ func compareSlices [E any ](t * testing.T , name string , got , want []E , compareElem func (* testing.T , string , E , E )) {
212
+ if len (got ) != len (want ) {
213
+ t .Errorf ("%s: got %d, want %d" , name , len (got ), len (want ))
214
+ }
215
+ for i := 0 ; i < len (got ) && i < len (want ); i ++ {
216
+ compareElem (t , fmt .Sprintf ("%s[%d]" , name , i ), got [i ], want [i ])
217
+ }
218
+ }
219
+
220
+ const funcsTestFile = `
221
+ package funcs
222
+
223
+ func F() {}
224
+
225
+ type S1 struct {
226
+ S2 // embedded, exported
227
+ s3 // embedded, unexported
228
+ }
229
+
230
+ func NewS1() S1 {return S1{} }
231
+ func NewS1p() *S1 { return &S1{} }
232
+
233
+ func (S1) M1() {}
234
+ func (r S1) M2() {}
235
+ func(S1) m3() {} // unexported not shown
236
+ func (*S1) P1() {} // pointer receiver
237
+
238
+ type S2 int
239
+ func (S2) M3() {} // shown on S2
240
+
241
+ type s3 int
242
+ func (s3) M4() {} // shown on S1
243
+
244
+ type G1[T any] struct {
245
+ *s3
246
+ }
247
+
248
+ func NewG1[T any]() G1[T] { return G1[T]{} }
249
+
250
+ func (G1[T]) MG1() {}
251
+ func (*G1[U]) MG2() {}
252
+
253
+ type G2[T, U any] struct {}
254
+
255
+ func NewG2[T, U any]() G2[T, U] { return G2[T, U]{} }
256
+
257
+ func (G2[T, U]) MG3() {}
258
+ func (*G2[A, B]) MG4() {}
259
+
260
+
261
+ `
262
+
263
+ var funcsPackage = & Package {
264
+ Funcs : []* Func {{Name : "F" }},
265
+ Types : []* Type {
266
+ {
267
+ Name : "G1" ,
268
+ Funcs : []* Func {{Name : "NewG1" }},
269
+ Methods : []* Func {
270
+ {Name : "M4" , Recv : "G1" , // TODO: synthesize a param for G1?
271
+ Orig : "s3" , Level : 1 },
272
+ {Name : "MG1" , Recv : "G1[T]" , Orig : "G1[T]" , Level : 0 },
273
+ {Name : "MG2" , Recv : "*G1[U]" , Orig : "*G1[U]" , Level : 0 },
274
+ },
275
+ },
276
+ {
277
+ Name : "G2" ,
278
+ Funcs : []* Func {{Name : "NewG2" }},
279
+ Methods : []* Func {
280
+ {Name : "MG3" , Recv : "G2[T, U]" , Orig : "G2[T, U]" , Level : 0 },
281
+ {Name : "MG4" , Recv : "*G2[A, B]" , Orig : "*G2[A, B]" , Level : 0 },
282
+ },
283
+ },
284
+ {
285
+ Name : "S1" ,
286
+ Funcs : []* Func {{Name : "NewS1" }, {Name : "NewS1p" }},
287
+ Methods : []* Func {
288
+ {Name : "M1" , Recv : "S1" , Orig : "S1" , Level : 0 },
289
+ {Name : "M2" , Recv : "S1" , Orig : "S1" , Level : 0 },
290
+ {Name : "M4" , Recv : "S1" , Orig : "s3" , Level : 1 },
291
+ {Name : "P1" , Recv : "*S1" , Orig : "*S1" , Level : 0 },
292
+ },
293
+ },
294
+ {
295
+ Name : "S2" ,
296
+ Methods : []* Func {
297
+ {Name : "M3" , Recv : "S2" , Orig : "S2" , Level : 0 },
298
+ },
299
+ },
300
+ },
301
+ }
0 commit comments