• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

99designs / gqlgen / 12320669056

13 Dec 2024 06:01PM UTC coverage: 73.884% (-0.04%) from 73.919%
12320669056

push

github

web-flow
enable testifylint.encoded-compare and fix lint issues (#3434)

8575 of 11606 relevant lines covered (73.88%)

641.17 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

72.94
/codegen/field.go
1
package codegen
2

3
import (
4
        "errors"
5
        "fmt"
6
        goast "go/ast"
7
        "go/types"
8
        "log"
9
        "reflect"
10
        "strconv"
11
        "strings"
12

13
        "github.com/vektah/gqlparser/v2/ast"
14
        "golang.org/x/text/cases"
15
        "golang.org/x/text/language"
16

17
        "github.com/99designs/gqlgen/codegen/config"
18
        "github.com/99designs/gqlgen/codegen/templates"
19
        "github.com/99designs/gqlgen/internal/code"
20
)
21

22
type Field struct {
23
        *ast.FieldDefinition
24

25
        TypeReference    *config.TypeReference
26
        GoFieldType      GoFieldType      // The field type in go, if any
27
        GoReceiverName   string           // The name of method & var receiver in go, if any
28
        GoFieldName      string           // The name of the method or var in go, if any
29
        IsResolver       bool             // Does this field need a resolver
30
        Args             []*FieldArgument // A list of arguments to be passed to this field
31
        MethodHasContext bool             // If this is bound to a go method, does the method also take a context
32
        NoErr            bool             // If this is bound to a go method, does that method have an error as the second argument
33
        VOkFunc          bool             // If this is bound to a go method, is it of shape (interface{}, bool)
34
        Object           *Object          // A link back to the parent object
35
        Default          any              // The default value
36
        Stream           bool             // does this field return a channel?
37
        Directives       []*Directive
38
}
39

40
func (b *builder) buildField(obj *Object, field *ast.FieldDefinition) (*Field, error) {
552✔
41
        dirs, err := b.getDirectives(field.Directives)
552✔
42
        if err != nil {
552✔
43
                return nil, err
×
44
        }
×
45

46
        f := Field{
552✔
47
                FieldDefinition: field,
552✔
48
                Object:          obj,
552✔
49
                Directives:      dirs,
552✔
50
                GoFieldName:     templates.ToGo(field.Name),
552✔
51
                GoFieldType:     GoFieldVariable,
552✔
52
                GoReceiverName:  "obj",
552✔
53
        }
552✔
54

552✔
55
        if field.DefaultValue != nil {
552✔
56
                var err error
×
57
                f.Default, err = field.DefaultValue.Value(nil)
×
58
                if err != nil {
×
59
                        return nil, fmt.Errorf("default value %s is not valid: %w", field.Name, err)
×
60
                }
×
61
        }
62

63
        for _, arg := range field.Arguments {
607✔
64
                newArg, err := b.buildArg(obj, arg)
55✔
65
                if err != nil {
55✔
66
                        return nil, err
×
67
                }
×
68
                f.Args = append(f.Args, newArg)
55✔
69
        }
70

71
        if err = b.bindField(obj, &f); err != nil {
572✔
72
                f.IsResolver = true
20✔
73
                if errors.Is(err, config.ErrTypeNotFound) {
20✔
74
                        return nil, err
×
75
                }
×
76
                log.Println(err.Error())
20✔
77
        }
78

79
        if f.IsResolver && b.Config.ResolversAlwaysReturnPointers && !f.TypeReference.IsPtr() && f.TypeReference.IsStruct() {
572✔
80
                f.TypeReference = b.Binder.PointerTo(f.TypeReference)
20✔
81
        }
20✔
82

83
        return &f, nil
552✔
84
}
85

86
func (b *builder) bindField(obj *Object, f *Field) (errret error) {
552✔
87
        defer func() {
1,104✔
88
                if f.TypeReference == nil {
617✔
89
                        tr, err := b.Binder.TypeReference(f.Type, nil)
65✔
90
                        if err != nil {
65✔
91
                                errret = err
×
92
                        }
×
93
                        f.TypeReference = tr
65✔
94
                }
95
                if f.TypeReference != nil {
1,104✔
96
                        dirs, err := b.getDirectives(f.TypeReference.Definition.Directives)
552✔
97
                        if err != nil {
552✔
98
                                errret = err
×
99
                        }
×
100
                        for _, dir := range obj.Directives {
580✔
101
                                if dir.IsLocation(ast.LocationInputObject) {
28✔
102
                                        dirs = append(dirs, dir)
×
103
                                }
×
104
                        }
105
                        f.Directives = append(dirs, f.Directives...)
552✔
106
                }
107
        }()
108

109
        f.Stream = obj.Stream
552✔
110

552✔
111
        switch {
552✔
112
        case f.Name == "__schema":
12✔
113
                f.GoFieldType = GoFieldMethod
12✔
114
                f.GoReceiverName = "ec"
12✔
115
                f.GoFieldName = "introspectSchema"
12✔
116
                return nil
12✔
117
        case f.Name == "__type":
12✔
118
                f.GoFieldType = GoFieldMethod
12✔
119
                f.GoReceiverName = "ec"
12✔
120
                f.GoFieldName = "introspectType"
12✔
121
                return nil
12✔
122
        case f.Name == "_entities":
2✔
123
                f.GoFieldType = GoFieldMethod
2✔
124
                f.GoReceiverName = "ec"
2✔
125
                f.GoFieldName = "__resolve_entities"
2✔
126
                f.MethodHasContext = true
2✔
127
                f.NoErr = true
2✔
128
                return nil
2✔
129
        case f.Name == "_service":
3✔
130
                f.GoFieldType = GoFieldMethod
3✔
131
                f.GoReceiverName = "ec"
3✔
132
                f.GoFieldName = "__resolve__service"
3✔
133
                f.MethodHasContext = true
3✔
134
                return nil
3✔
135
        case obj.Root:
16✔
136
                f.IsResolver = true
16✔
137
                return nil
16✔
138
        case b.Config.Models[obj.Name].Fields[f.Name].Resolver:
×
139
                f.IsResolver = true
×
140
                return nil
×
141
        case obj.Type == config.MapType:
×
142
                f.GoFieldType = GoFieldMap
×
143
                return nil
×
144
        case b.Config.Models[obj.Name].Fields[f.Name].FieldName != "":
×
145
                f.GoFieldName = b.Config.Models[obj.Name].Fields[f.Name].FieldName
×
146
        }
147

148
        target, err := b.findBindTarget(obj.Type, f.GoFieldName)
507✔
149
        if err != nil {
507✔
150
                return err
×
151
        }
×
152

153
        pos := b.Binder.ObjectPosition(target)
507✔
154

507✔
155
        switch target := target.(type) {
507✔
156
        case nil:
18✔
157
                // Skips creating a resolver for any root types
18✔
158
                if b.Config.IsRoot(b.Schema.Types[f.Type.Name()]) {
18✔
159
                        return nil
×
160
                }
×
161

162
                objPos := b.Binder.TypePosition(obj.Type)
18✔
163
                return fmt.Errorf(
18✔
164
                        "%s:%d adding resolver method for %s.%s, nothing matched",
18✔
165
                        objPos.Filename,
18✔
166
                        objPos.Line,
18✔
167
                        obj.Name,
18✔
168
                        f.Name,
18✔
169
                )
18✔
170

171
        case *types.Func:
301✔
172
                sig := target.Type().(*types.Signature)
301✔
173
                if sig.Results().Len() == 1 {
602✔
174
                        f.NoErr = true
301✔
175
                } else if s := sig.Results(); s.Len() == 2 && s.At(1).Type().String() == "bool" {
301✔
176
                        f.VOkFunc = true
×
177
                } else if sig.Results().Len() != 2 {
×
178
                        return errors.New("method has wrong number of args")
×
179
                }
×
180
                params := sig.Params()
301✔
181
                // If the first argument is the context, remove it from the comparison and set
301✔
182
                // the MethodHasContext flag so that the context will be passed to this model's method
301✔
183
                if params.Len() > 0 && params.At(0).Type().String() == "context.Context" {
301✔
184
                        f.MethodHasContext = true
×
185
                        vars := make([]*types.Var, params.Len()-1)
×
186
                        for i := 1; i < params.Len(); i++ {
×
187
                                vars[i-1] = params.At(i)
×
188
                        }
×
189
                        params = types.NewTuple(vars...)
×
190
                }
191

192
                // Try to match target function's arguments with GraphQL field arguments.
193
                newArgs, err := b.bindArgs(f, sig, params)
301✔
194
                if err != nil {
301✔
195
                        return fmt.Errorf("%s:%d: %w", pos.Filename, pos.Line, err)
×
196
                }
×
197

198
                // Try to match target function's return types with GraphQL field return type
199
                result := sig.Results().At(0)
301✔
200
                tr, err := b.Binder.TypeReference(f.Type, result.Type())
301✔
201
                if err != nil {
301✔
202
                        return err
×
203
                }
×
204

205
                // success, args and return type match. Bind to method
206
                f.GoFieldType = GoFieldMethod
301✔
207
                f.GoReceiverName = "obj"
301✔
208
                f.GoFieldName = target.Name()
301✔
209
                f.Args = newArgs
301✔
210
                f.TypeReference = tr
301✔
211

301✔
212
                return nil
301✔
213

214
        case *types.Var:
188✔
215
                tr, err := b.Binder.TypeReference(f.Type, target.Type())
188✔
216
                if err != nil {
190✔
217
                        return err
2✔
218
                }
2✔
219

220
                // success, bind to var
221
                f.GoFieldType = GoFieldVariable
186✔
222
                f.GoReceiverName = "obj"
186✔
223
                f.GoFieldName = target.Name()
186✔
224
                f.TypeReference = tr
186✔
225

186✔
226
                return nil
186✔
227
        default:
×
228
                panic(fmt.Errorf("unknown bind target %T for %s", target, f.Name))
×
229
        }
230
}
231

232
// findBindTarget attempts to match the name to a field or method on a Type
233
// with the following priorities:
234
// 1. Any Fields with a struct tag (see config.StructTag). Errors if more than one match is found
235
// 2. Any method or field with a matching name. Errors if more than one match is found
236
// 3. Same logic again for embedded fields
237
func (b *builder) findBindTarget(t types.Type, name string) (types.Object, error) {
515✔
238
        // NOTE: a struct tag will override both methods and fields
515✔
239
        // Bind to struct tag
515✔
240
        found, err := b.findBindStructTagTarget(t, name)
515✔
241
        if found != nil || err != nil {
517✔
242
                return found, err
2✔
243
        }
2✔
244

245
        // Search for a method to bind to
246
        foundMethod, err := b.findBindMethodTarget(t, name)
513✔
247
        if err != nil {
513✔
248
                return nil, err
×
249
        }
×
250

251
        // Search for a field to bind to
252
        foundField, err := b.findBindFieldTarget(t, name)
513✔
253
        if err != nil {
513✔
254
                return nil, err
×
255
        }
×
256

257
        switch {
513✔
258
        case foundField == nil && foundMethod != nil:
301✔
259
                // Bind to method
301✔
260
                return foundMethod, nil
301✔
261
        case foundField != nil && foundMethod == nil:
193✔
262
                // Bind to field
193✔
263
                return foundField, nil
193✔
264
        case foundField != nil && foundMethod != nil:
×
265
                // Error
×
266
                return nil, fmt.Errorf("found more than one way to bind for %s", name)
×
267
        }
268

269
        // Search embeds
270
        return b.findBindEmbedsTarget(t, name)
19✔
271
}
272

273
func (b *builder) findBindStructTagTarget(in types.Type, name string) (types.Object, error) {
518✔
274
        if b.Config.StructTag == "" {
1,030✔
275
                return nil, nil
512✔
276
        }
512✔
277

278
        switch t := in.(type) {
6✔
279
        case *types.Named:
3✔
280
                return b.findBindStructTagTarget(t.Underlying(), name)
3✔
281
        case *types.Struct:
3✔
282
                var found types.Object
3✔
283
                for i := 0; i < t.NumFields(); i++ {
9✔
284
                        field := t.Field(i)
6✔
285
                        if !field.Exported() || field.Embedded() {
6✔
286
                                continue
×
287
                        }
288
                        tags := reflect.StructTag(t.Tag(i))
6✔
289
                        if val, ok := tags.Lookup(b.Config.StructTag); ok && equalFieldName(val, name) {
9✔
290
                                if found != nil {
4✔
291
                                        return nil, fmt.Errorf("tag %s is ambiguous; multiple fields have the same tag value of %s", b.Config.StructTag, val)
1✔
292
                                }
1✔
293

294
                                found = field
2✔
295
                        }
296
                }
297

298
                return found, nil
2✔
299
        }
300

301
        return nil, nil
×
302
}
303

304
func (b *builder) findBindMethodTarget(in types.Type, name string) (types.Object, error) {
522✔
305
        switch t := in.(type) {
522✔
306
        case *types.Named:
513✔
307
                if _, ok := t.Underlying().(*types.Interface); ok {
522✔
308
                        return b.findBindMethodTarget(t.Underlying(), name)
9✔
309
                }
9✔
310

311
                return b.findBindMethoderTarget(t.Method, t.NumMethods(), name)
504✔
312
        case *types.Interface:
9✔
313
                // FIX-ME: Should use ExplicitMethod here? What's the difference?
9✔
314
                return b.findBindMethoderTarget(t.Method, t.NumMethods(), name)
9✔
315
        }
316

317
        return nil, nil
×
318
}
319

320
func (b *builder) findBindMethoderTarget(methodFunc func(i int) *types.Func, methodCount int, name string) (types.Object, error) {
513✔
321
        var found types.Object
513✔
322
        for i := 0; i < methodCount; i++ {
2,792✔
323
                method := methodFunc(i)
2,279✔
324
                if !method.Exported() || !strings.EqualFold(method.Name(), name) {
4,257✔
325
                        continue
1,978✔
326
                }
327

328
                if found != nil {
301✔
329
                        return nil, fmt.Errorf("found more than one matching method to bind for %s", name)
×
330
                }
×
331

332
                found = method
301✔
333
        }
334

335
        return found, nil
513✔
336
}
337

338
func (b *builder) findBindFieldTarget(in types.Type, name string) (types.Object, error) {
1,026✔
339
        switch t := in.(type) {
1,026✔
340
        case *types.Named:
513✔
341
                return b.findBindFieldTarget(t.Underlying(), name)
513✔
342
        case *types.Struct:
504✔
343
                var found types.Object
504✔
344
                for i := 0; i < t.NumFields(); i++ {
2,144✔
345
                        field := t.Field(i)
1,640✔
346
                        if !field.Exported() || !equalFieldName(field.Name(), name) {
3,087✔
347
                                continue
1,447✔
348
                        }
349

350
                        if found != nil {
193✔
351
                                return nil, fmt.Errorf("found more than one matching field to bind for %s", name)
×
352
                        }
×
353

354
                        found = field
193✔
355
                }
356

357
                return found, nil
504✔
358
        }
359

360
        return nil, nil
9✔
361
}
362

363
func (b *builder) findBindEmbedsTarget(in types.Type, name string) (types.Object, error) {
38✔
364
        switch t := in.(type) {
38✔
365
        case *types.Named:
19✔
366
                return b.findBindEmbedsTarget(t.Underlying(), name)
19✔
367
        case *types.Struct:
10✔
368
                return b.findBindStructEmbedsTarget(t, name)
10✔
369
        case *types.Interface:
9✔
370
                return b.findBindInterfaceEmbedsTarget(t, name)
9✔
371
        }
372

373
        return nil, nil
×
374
}
375

376
func (b *builder) findBindStructEmbedsTarget(strukt *types.Struct, name string) (types.Object, error) {
10✔
377
        var found types.Object
10✔
378
        for i := 0; i < strukt.NumFields(); i++ {
14✔
379
                field := strukt.Field(i)
4✔
380
                if !field.Embedded() {
7✔
381
                        continue
3✔
382
                }
383

384
                fieldType := code.Unalias(field.Type())
1✔
385
                if ptr, ok := fieldType.(*types.Pointer); ok {
1✔
386
                        fieldType = ptr.Elem()
×
387
                }
×
388

389
                f, err := b.findBindTarget(fieldType, name)
1✔
390
                if err != nil {
1✔
391
                        return nil, err
×
392
                }
×
393

394
                if f != nil && found != nil {
1✔
395
                        return nil, fmt.Errorf("found more than one way to bind for %s", name)
×
396
                }
×
397

398
                if f != nil {
2✔
399
                        found = f
1✔
400
                }
1✔
401
        }
402

403
        return found, nil
10✔
404
}
405

406
func (b *builder) findBindInterfaceEmbedsTarget(iface *types.Interface, name string) (types.Object, error) {
9✔
407
        var found types.Object
9✔
408
        for i := 0; i < iface.NumEmbeddeds(); i++ {
9✔
409
                embeddedType := iface.EmbeddedType(i)
×
410

×
411
                f, err := b.findBindTarget(embeddedType, name)
×
412
                if err != nil {
×
413
                        return nil, err
×
414
                }
×
415

416
                if f != nil && found != nil {
×
417
                        return nil, fmt.Errorf("found more than one way to bind for %s", name)
×
418
                }
×
419

420
                if f != nil {
×
421
                        found = f
×
422
                }
×
423
        }
424

425
        return found, nil
9✔
426
}
427

428
func (f *Field) HasDirectives() bool {
274✔
429
        return len(f.ImplDirectives()) > 0
274✔
430
}
274✔
431

432
func (f *Field) DirectiveObjName() string {
×
433
        if f.Object.Root {
×
434
                return "nil"
×
435
        }
×
436
        return f.GoReceiverName
×
437
}
438

439
func (f *Field) ImplDirectives() []*Directive {
286✔
440
        var d []*Directive
286✔
441
        loc := ast.LocationFieldDefinition
286✔
442
        if f.Object.IsInputType() {
298✔
443
                loc = ast.LocationInputFieldDefinition
12✔
444
        }
12✔
445
        for i := range f.Directives {
286✔
446
                if !f.Directives[i].SkipRuntime &&
×
447
                        (f.Directives[i].IsLocation(loc, ast.LocationObject) || f.Directives[i].IsLocation(loc, ast.LocationInputObject)) {
×
448
                        d = append(d, f.Directives[i])
×
449
                }
×
450
        }
451
        return d
286✔
452
}
453

454
func (f *Field) IsReserved() bool {
128✔
455
        return strings.HasPrefix(f.Name, "__")
128✔
456
}
128✔
457

458
func (f *Field) IsMethod() bool {
536✔
459
        return f.GoFieldType == GoFieldMethod
536✔
460
}
536✔
461

462
func (f *Field) IsVariable() bool {
104✔
463
        return f.GoFieldType == GoFieldVariable
104✔
464
}
104✔
465

466
func (f *Field) IsMap() bool {
262✔
467
        return f.GoFieldType == GoFieldMap
262✔
468
}
262✔
469

470
func (f *Field) IsConcurrent() bool {
936✔
471
        if f.Object.DisableConcurrency {
948✔
472
                return false
12✔
473
        }
12✔
474
        return f.MethodHasContext || f.IsResolver
924✔
475
}
476

477
func (f *Field) GoNameUnexported() string {
×
478
        return templates.ToGoPrivate(f.Name)
×
479
}
×
480

481
func (f *Field) ShortInvocation() string {
12✔
482
        caser := cases.Title(language.English, cases.NoLower)
12✔
483
        if f.Object.Kind == ast.InputObject {
12✔
484
                return fmt.Sprintf("%s().%s(ctx, &it, data)", caser.String(f.Object.Definition.Name), f.GoFieldName)
×
485
        }
×
486
        return fmt.Sprintf("%s().%s(%s)", caser.String(f.Object.Definition.Name), f.GoFieldName, f.CallArgs())
12✔
487
}
488

489
func (f *Field) ArgsFunc() string {
54✔
490
        if len(f.Args) == 0 {
54✔
491
                return ""
×
492
        }
×
493

494
        return "field_" + f.Object.Definition.Name + "_" + f.Name + "_args"
54✔
495
}
496

497
func (f *Field) FieldContextFunc() string {
548✔
498
        return "fieldContext_" + f.Object.Definition.Name + "_" + f.Name
548✔
499
}
548✔
500

501
func (f *Field) ChildFieldContextFunc(name string) string {
860✔
502
        return "fieldContext_" + f.TypeReference.Definition.Name + "_" + name
860✔
503
}
860✔
504

505
func (f *Field) ResolverType() string {
×
506
        if !f.IsResolver {
×
507
                return ""
×
508
        }
×
509

510
        return fmt.Sprintf("%s().%s(%s)", f.Object.Definition.Name, f.GoFieldName, f.CallArgs())
×
511
}
512

513
func (f *Field) IsInputObject() bool {
×
514
        return f.Object.Kind == ast.InputObject
×
515
}
×
516

517
func (f *Field) IsRoot() bool {
×
518
        return f.Object.Root
×
519
}
×
520

521
func (f *Field) ShortResolverDeclaration() string {
20✔
522
        return f.ShortResolverSignature(nil)
20✔
523
}
20✔
524

525
// ShortResolverSignature is identical to ShortResolverDeclaration,
526
// but respects previous naming (return) conventions, if any.
527
func (f *Field) ShortResolverSignature(ft *goast.FuncType) string {
30✔
528
        if f.Object.Kind == ast.InputObject {
30✔
529
                return fmt.Sprintf("(ctx context.Context, obj %s, data %s) error",
×
530
                        templates.CurrentImports.LookupType(f.Object.Reference()),
×
531
                        templates.CurrentImports.LookupType(f.TypeReference.GO),
×
532
                )
×
533
        }
×
534

535
        res := "(ctx context.Context"
30✔
536

30✔
537
        if !f.Object.Root {
36✔
538
                res += fmt.Sprintf(", obj %s", templates.CurrentImports.LookupType(f.Object.Reference()))
6✔
539
        }
6✔
540
        for _, arg := range f.Args {
39✔
541
                res += fmt.Sprintf(", %s %s", arg.VarName, templates.CurrentImports.LookupType(arg.TypeReference.GO))
9✔
542
        }
9✔
543

544
        result := templates.CurrentImports.LookupType(f.TypeReference.GO)
30✔
545
        if f.Object.Stream {
30✔
546
                result = "<-chan " + result
×
547
        }
×
548
        // Named return.
549
        var namedV, namedE string
30✔
550
        if ft != nil {
40✔
551
                if ft.Results != nil && len(ft.Results.List) > 0 && len(ft.Results.List[0].Names) > 0 {
11✔
552
                        namedV = ft.Results.List[0].Names[0].Name
1✔
553
                }
1✔
554
                if ft.Results != nil && len(ft.Results.List) > 1 && len(ft.Results.List[1].Names) > 0 {
11✔
555
                        namedE = ft.Results.List[1].Names[0].Name
1✔
556
                }
1✔
557
        }
558
        res += fmt.Sprintf(") (%s %s, %s error)", namedV, result, namedE)
30✔
559
        return res
30✔
560
}
561

562
func (f *Field) GoResultName() (string, bool) {
×
563
        name := fmt.Sprintf("%v", f.TypeReference.GO)
×
564
        splits := strings.Split(name, "/")
×
565

×
566
        return splits[len(splits)-1], strings.HasPrefix(name, "[]")
×
567
}
×
568

569
func (f *Field) ComplexitySignature() string {
52✔
570
        res := "func(childComplexity int"
52✔
571
        for _, arg := range f.Args {
58✔
572
                res += fmt.Sprintf(", %s %s", arg.VarName, templates.CurrentImports.LookupType(arg.TypeReference.GO))
6✔
573
        }
6✔
574
        res += ") int"
52✔
575
        return res
52✔
576
}
577

578
func (f *Field) ComplexityArgs() string {
6✔
579
        args := make([]string, len(f.Args))
6✔
580
        for i, arg := range f.Args {
12✔
581
                args[i] = "args[" + strconv.Quote(arg.Name) + "].(" + templates.CurrentImports.LookupType(arg.TypeReference.GO) + ")"
6✔
582
        }
6✔
583

584
        return strings.Join(args, ", ")
6✔
585
}
586

587
func (f *Field) CallArgs() string {
172✔
588
        args := make([]string, 0, len(f.Args)+2)
172✔
589

172✔
590
        if f.IsResolver {
185✔
591
                args = append(args, "rctx")
13✔
592

13✔
593
                if !f.Object.Root {
14✔
594
                        args = append(args, "obj")
1✔
595
                }
1✔
596
        } else if f.MethodHasContext {
162✔
597
                args = append(args, "ctx")
3✔
598
        }
3✔
599

600
        for _, arg := range f.Args {
200✔
601
                tmp := "fc.Args[" + strconv.Quote(arg.Name) + "].(" + templates.CurrentImports.LookupType(arg.TypeReference.GO) + ")"
28✔
602

28✔
603
                if iface, ok := arg.TypeReference.GO.(*types.Interface); ok && iface.Empty() {
29✔
604
                        tmp = fmt.Sprintf(`
1✔
605
                                func () interface{} {
1✔
606
                                        if fc.Args["%s"] == nil {
1✔
607
                                                return nil
1✔
608
                                        }
1✔
609
                                        return fc.Args["%s"].(interface{})
1✔
610
                                }()`, arg.Name, arg.Name,
1✔
611
                        )
1✔
612
                }
1✔
613

614
                args = append(args, tmp)
28✔
615
        }
616

617
        return strings.Join(args, ", ")
172✔
618
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc