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

99designs / gqlgen / 12985642426

27 Jan 2025 09:15AM UTC coverage: 73.926% (+0.04%) from 73.891%
12985642426

Pull #3501

github

web-flow
chore(deps-dev): bump vite from 6.0.9 to 6.0.11 in /integration

Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 6.0.9 to 6.0.11.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v6.0.11/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Pull Request #3501: chore(deps-dev): bump vite from 6.0.9 to 6.0.11 in /integration

8619 of 11659 relevant lines covered (73.93%)

532.02 hits per line

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

75.05
/codegen/config/binder.go
1
package config
2

3
import (
4
        "errors"
5
        "fmt"
6
        "go/token"
7
        "go/types"
8
        "strings"
9

10
        "github.com/vektah/gqlparser/v2/ast"
11
        "golang.org/x/tools/go/packages"
12

13
        "github.com/99designs/gqlgen/codegen/templates"
14
        "github.com/99designs/gqlgen/internal/code"
15
)
16

17
var ErrTypeNotFound = errors.New("unable to find type")
18

19
// Binder connects graphql types to golang types using static analysis
20
type Binder struct {
21
        pkgs        *code.Packages
22
        schema      *ast.Schema
23
        cfg         *Config
24
        tctx        *types.Context
25
        References  []*TypeReference
26
        SawInvalid  bool
27
        objectCache map[string]map[string]types.Object
28
}
29

30
func (c *Config) NewBinder() *Binder {
218✔
31
        return &Binder{
218✔
32
                pkgs:   c.Packages,
218✔
33
                schema: c.Schema,
218✔
34
                cfg:    c,
218✔
35
        }
218✔
36
}
218✔
37

38
func (b *Binder) TypePosition(typ types.Type) token.Position {
18✔
39
        named, isNamed := code.Unalias(typ).(*types.Named)
18✔
40
        if !isNamed {
18✔
41
                return token.Position{
×
42
                        Filename: "unknown",
×
43
                }
×
44
        }
×
45

46
        return b.ObjectPosition(named.Obj())
18✔
47
}
48

49
func (b *Binder) ObjectPosition(typ types.Object) token.Position {
511✔
50
        if typ == nil {
529✔
51
                return token.Position{
18✔
52
                        Filename: "unknown",
18✔
53
                }
18✔
54
        }
18✔
55
        pkg := b.pkgs.Load(typ.Pkg().Path())
493✔
56
        return pkg.Fset.Position(typ.Pos())
493✔
57
}
58

59
func (b *Binder) FindTypeFromName(name string) (types.Type, error) {
329✔
60
        pkgName, typeName := code.PkgAndType(name)
329✔
61
        return b.FindType(pkgName, typeName)
329✔
62
}
329✔
63

64
func (b *Binder) FindType(pkgName, typeName string) (types.Type, error) {
339✔
65
        if pkgName == "" {
339✔
66
                if typeName == "map[string]any" || typeName == "map[string]interface{}" {
×
67
                        return MapType, nil
×
68
                }
×
69

70
                if typeName == "any" || typeName == "interface{}" {
×
71
                        return InterfaceType, nil
×
72
                }
×
73
        }
74

75
        obj, err := b.FindObject(pkgName, typeName)
339✔
76
        if err != nil {
339✔
77
                return nil, err
×
78
        }
×
79

80
        t := code.Unalias(obj.Type())
339✔
81
        if _, isFunc := obj.(*types.Func); isFunc {
618✔
82
                return code.Unalias(t.(*types.Signature).Params().At(0).Type()), nil
279✔
83
        }
279✔
84
        return t, nil
60✔
85
}
86

87
func (b *Binder) InstantiateType(orig types.Type, targs []types.Type) (types.Type, error) {
29✔
88
        if b.tctx == nil {
42✔
89
                b.tctx = types.NewContext()
13✔
90
        }
13✔
91

92
        return types.Instantiate(b.tctx, orig, targs, false)
29✔
93
}
94

95
var (
96
        MapType       = types.NewMap(types.Typ[types.String], types.NewInterfaceType(nil, nil).Complete())
97
        InterfaceType = types.NewInterfaceType(nil, nil)
98
)
99

100
func (b *Binder) DefaultUserObject(name string) (types.Type, error) {
118✔
101
        models := b.cfg.Models[name].Model
118✔
102
        if len(models) == 0 {
118✔
103
                return nil, fmt.Errorf("%s not found in typemap", name)
×
104
        }
×
105

106
        if models[0] == "map[string]any" || models[0] == "map[string]interface{}" {
118✔
107
                return MapType, nil
×
108
        }
×
109

110
        if models[0] == "any" || models[0] == "interface{}" {
118✔
111
                return InterfaceType, nil
×
112
        }
×
113

114
        pkgName, typeName := code.PkgAndType(models[0])
118✔
115
        if pkgName == "" {
118✔
116
                return nil, fmt.Errorf("missing package name for %s", name)
×
117
        }
×
118

119
        obj, err := b.FindObject(pkgName, typeName)
118✔
120
        if err != nil {
118✔
121
                return nil, err
×
122
        }
×
123

124
        return code.Unalias(obj.Type()), nil
118✔
125
}
126

127
func (b *Binder) FindObject(pkgName, typeName string) (types.Object, error) {
1,207✔
128
        if pkgName == "" {
1,207✔
129
                return nil, fmt.Errorf("package cannot be nil in FindObject for type: %s", typeName)
×
130
        }
×
131

132
        pkg := b.pkgs.LoadWithTypes(pkgName)
1,207✔
133
        if pkg == nil {
1,207✔
134
                err := b.pkgs.Errors()
×
135
                if err != nil {
×
136
                        return nil, fmt.Errorf("package could not be loaded: %s.%s: %w", pkgName, typeName, err)
×
137
                }
×
138
                return nil, fmt.Errorf("required package was not loaded: %s.%s", pkgName, typeName)
×
139
        }
140

141
        if b.objectCache == nil {
1,399✔
142
                b.objectCache = make(map[string]map[string]types.Object, b.pkgs.Count())
192✔
143
        }
192✔
144

145
        defsIndex, ok := b.objectCache[pkgName]
1,207✔
146
        if !ok {
1,459✔
147
                defsIndex = indexDefs(pkg)
252✔
148
                b.objectCache[pkgName] = defsIndex
252✔
149
        }
252✔
150

151
        // function based marshalers take precedence
152
        if val, ok := defsIndex["Marshal"+typeName]; ok {
1,960✔
153
                return val, nil
753✔
154
        }
753✔
155

156
        if val, ok := defsIndex[typeName]; ok {
907✔
157
                return val, nil
453✔
158
        }
453✔
159

160
        return nil, fmt.Errorf("%w: %s.%s", ErrTypeNotFound, pkgName, typeName)
1✔
161
}
162

163
func indexDefs(pkg *packages.Package) map[string]types.Object {
252✔
164
        res := make(map[string]types.Object)
252✔
165

252✔
166
        scope := pkg.Types.Scope()
252✔
167
        for astNode, def := range pkg.TypesInfo.Defs {
186,937✔
168
                // only look at defs in the top scope
186,685✔
169
                if def == nil {
197,669✔
170
                        continue
10,984✔
171
                }
172
                parent := def.Parent()
175,701✔
173
                if parent == nil || parent != scope {
315,792✔
174
                        continue
140,091✔
175
                }
176

177
                if _, ok := res[astNode.Name]; !ok {
71,220✔
178
                        // The above check may not be really needed, it is only here to have a consistent behavior with
35,610✔
179
                        // previous implementation of FindObject() function which only honored the first inclusion of a def.
35,610✔
180
                        // If this is still needed, we can consider something like sync.Map.LoadOrStore() to avoid two lookups.
35,610✔
181
                        res[astNode.Name] = def
35,610✔
182
                }
35,610✔
183
        }
184

185
        return res
252✔
186
}
187

188
func (b *Binder) PointerTo(ref *TypeReference) *TypeReference {
20✔
189
        newRef := *ref
20✔
190
        newRef.GO = types.NewPointer(ref.GO)
20✔
191
        b.References = append(b.References, &newRef)
20✔
192
        return &newRef
20✔
193
}
20✔
194

195
// TypeReference is used by args and field types. The Definition can refer to both input and output types.
196
type TypeReference struct {
197
        Definition               *ast.Definition
198
        GQL                      *ast.Type
199
        GO                       types.Type  // Type of the field being bound. Could be a pointer or a value type of Target.
200
        Target                   types.Type  // The actual type that we know how to bind to. May require pointer juggling when traversing to fields.
201
        CastType                 types.Type  // Before calling marshalling functions cast from/to this base type
202
        Marshaler                *types.Func // When using external marshalling functions this will point to the Marshal function
203
        Unmarshaler              *types.Func // When using external marshalling functions this will point to the Unmarshal function
204
        IsMarshaler              bool        // Does the type implement graphql.Marshaler and graphql.Unmarshaler
205
        IsOmittable              bool        // Is the type wrapped with Omittable
206
        IsContext                bool        // Is the Marshaler/Unmarshaller the context version; applies to either the method or interface variety.
207
        PointersInUnmarshalInput bool        // Inverse values and pointers in return.
208
        IsRoot                   bool        // Is the type a root level definition such as Query, Mutation or Subscription
209
        EnumValues               []EnumValueReference
210
}
211

212
func (ref *TypeReference) Elem() *TypeReference {
215✔
213
        if p, isPtr := ref.GO.(*types.Pointer); isPtr {
215✔
214
                newRef := *ref
×
215
                newRef.GO = p.Elem()
×
216
                return &newRef
×
217
        }
×
218

219
        if ref.IsSlice() {
430✔
220
                newRef := *ref
215✔
221
                newRef.GO = ref.GO.(*types.Slice).Elem()
215✔
222
                newRef.GQL = ref.GQL.Elem
215✔
223
                return &newRef
215✔
224
        }
215✔
225
        return nil
×
226
}
227

228
func (ref *TypeReference) IsPtr() bool {
1,776✔
229
        _, isPtr := ref.GO.(*types.Pointer)
1,776✔
230
        return isPtr
1,776✔
231
}
1,776✔
232

233
// fix for https://github.com/golang/go/issues/31103 may make it possible to remove this (may still be useful)
234
func (ref *TypeReference) IsPtrToPtr() bool {
837✔
235
        if p, isPtr := ref.GO.(*types.Pointer); isPtr {
1,207✔
236
                _, isPtr := p.Elem().(*types.Pointer)
370✔
237
                return isPtr
370✔
238
        }
370✔
239
        return false
467✔
240
}
241

242
func (ref *TypeReference) IsNilable() bool {
197✔
243
        return IsNilable(ref.GO)
197✔
244
}
197✔
245

246
func (ref *TypeReference) IsSlice() bool {
1,228✔
247
        _, isSlice := ref.GO.(*types.Slice)
1,228✔
248
        return ref.GQL.Elem != nil && isSlice
1,228✔
249
}
1,228✔
250

251
func (ref *TypeReference) IsPtrToSlice() bool {
870✔
252
        if ref.IsPtr() {
1,234✔
253
                _, isPointerToSlice := ref.GO.(*types.Pointer).Elem().(*types.Slice)
364✔
254
                return isPointerToSlice
364✔
255
        }
364✔
256
        return false
506✔
257
}
258

259
func (ref *TypeReference) IsPtrToIntf() bool {
870✔
260
        if ref.IsPtr() {
1,234✔
261
                _, isPointerToInterface := types.Unalias(ref.GO.(*types.Pointer).Elem()).(*types.Interface)
364✔
262
                return isPointerToInterface
364✔
263
        }
364✔
264
        return false
506✔
265
}
266

267
func (ref *TypeReference) IsNamed() bool {
×
268
        _, ok := ref.GO.(*types.Named)
×
269
        return ok
×
270
}
×
271

272
func (ref *TypeReference) IsStruct() bool {
36✔
273
        _, ok := ref.GO.Underlying().(*types.Struct)
36✔
274
        return ok
36✔
275
}
36✔
276

277
func (ref *TypeReference) IsScalar() bool {
96✔
278
        return ref.Definition.Kind == ast.Scalar
96✔
279
}
96✔
280

281
func (ref *TypeReference) IsMap() bool {
×
282
        return ref.GO == MapType
×
283
}
×
284

285
func (ref *TypeReference) UniquenessKey() string {
1,224✔
286
        nullability := "O"
1,224✔
287
        if ref.GQL.NonNull {
1,969✔
288
                nullability = "N"
745✔
289
        }
745✔
290

291
        elemNullability := ""
1,224✔
292
        if ref.GQL.Elem != nil && ref.GQL.Elem.NonNull {
1,436✔
293
                // Fix for #896
212✔
294
                elemNullability = "áš„"
212✔
295
        }
212✔
296
        return nullability + ref.Definition.Name + "2" + templates.TypeIdentifier(ref.GO) + elemNullability
1,224✔
297
}
298

299
func (ref *TypeReference) MarshalFunc() string {
266✔
300
        if ref.Definition == nil {
266✔
301
                panic(errors.New("Definition missing for " + ref.GQL.Name()))
×
302
        }
303

304
        if ref.Definition.Kind == ast.InputObject {
269✔
305
                return ""
3✔
306
        }
3✔
307

308
        return "marshal" + ref.UniquenessKey()
263✔
309
}
310

311
func (ref *TypeReference) UnmarshalFunc() string {
139✔
312
        if ref.Definition == nil {
139✔
313
                panic(errors.New("Definition missing for " + ref.GQL.Name()))
×
314
        }
315

316
        if !ref.Definition.IsInputType() {
197✔
317
                return ""
58✔
318
        }
58✔
319

320
        return "unmarshal" + ref.UniquenessKey()
81✔
321
}
322

323
func (ref *TypeReference) IsTargetNilable() bool {
112✔
324
        return IsNilable(ref.Target)
112✔
325
}
112✔
326

327
func (ref *TypeReference) HasEnumValues() bool {
155✔
328
        return len(ref.EnumValues) > 0
155✔
329
}
155✔
330

331
func (b *Binder) PushRef(ret *TypeReference) {
739✔
332
        b.References = append(b.References, ret)
739✔
333
}
739✔
334

335
func isMap(t types.Type) bool {
×
336
        if t == nil {
×
337
                return true
×
338
        }
×
339
        _, ok := t.(*types.Map)
×
340
        return ok
×
341
}
342

343
func isIntf(t types.Type) bool {
×
344
        if t == nil {
×
345
                return true
×
346
        }
×
347
        _, ok := types.Unalias(t).(*types.Interface)
×
348
        return ok
×
349
}
350

351
func unwrapOmittable(t types.Type) (types.Type, bool) {
749✔
352
        if t == nil {
988✔
353
                return nil, false
239✔
354
        }
239✔
355
        named, ok := t.(*types.Named)
510✔
356
        if !ok {
1,013✔
357
                return t, false
503✔
358
        }
503✔
359
        if named.Origin().String() != "github.com/99designs/gqlgen/graphql.Omittable[T any]" {
8✔
360
                return t, false
1✔
361
        }
1✔
362
        return named.TypeArgs().At(0), true
6✔
363
}
364

365
func (b *Binder) TypeReference(schemaType *ast.Type, bindTarget types.Type) (ret *TypeReference, err error) {
749✔
366
        if bindTarget != nil {
1,259✔
367
                bindTarget = code.Unalias(bindTarget)
510✔
368
        }
510✔
369
        if innerType, ok := unwrapOmittable(bindTarget); ok {
755✔
370
                if schemaType.NonNull {
8✔
371
                        return nil, fmt.Errorf("%s is wrapped with Omittable but non-null", schemaType.Name())
2✔
372
                }
2✔
373

374
                ref, err := b.TypeReference(schemaType, innerType)
4✔
375
                if err != nil {
4✔
376
                        return nil, err
×
377
                }
×
378

379
                ref.IsOmittable = true
4✔
380
                return ref, err
4✔
381
        }
382

383
        if !isValid(bindTarget) {
744✔
384
                b.SawInvalid = true
1✔
385
                return nil, fmt.Errorf("%s has an invalid type", schemaType.Name())
1✔
386
        }
1✔
387

388
        var pkgName, typeName string
742✔
389
        def := b.schema.Types[schemaType.Name()]
742✔
390
        defer func() {
1,484✔
391
                if err == nil && ret != nil {
1,481✔
392
                        b.PushRef(ret)
739✔
393
                }
739✔
394
        }()
395

396
        if len(b.cfg.Models[schemaType.Name()].Model) == 0 {
742✔
397
                return nil, fmt.Errorf("%s was not found", schemaType.Name())
×
398
        }
×
399

400
        for _, model := range b.cfg.Models[schemaType.Name()].Model {
1,484✔
401
                if model == "map[string]any" || model == "map[string]interface{}" {
742✔
402
                        if !isMap(bindTarget) {
×
403
                                continue
×
404
                        }
405
                        return &TypeReference{
×
406
                                Definition: def,
×
407
                                GQL:        schemaType,
×
408
                                GO:         MapType,
×
409
                                IsRoot:     b.cfg.IsRoot(def),
×
410
                        }, nil
×
411
                }
412

413
                if model == "any" || model == "interface{}" {
742✔
414
                        if !isIntf(bindTarget) {
×
415
                                continue
×
416
                        }
417
                        return &TypeReference{
×
418
                                Definition: def,
×
419
                                GQL:        schemaType,
×
420
                                GO:         InterfaceType,
×
421
                                IsRoot:     b.cfg.IsRoot(def),
×
422
                        }, nil
×
423
                }
424

425
                pkgName, typeName = code.PkgAndType(model)
742✔
426
                if pkgName == "" {
742✔
427
                        return nil, fmt.Errorf("missing package name for %s", schemaType.Name())
×
428
                }
×
429

430
                ref := &TypeReference{
742✔
431
                        Definition: def,
742✔
432
                        GQL:        schemaType,
742✔
433
                        IsRoot:     b.cfg.IsRoot(def),
742✔
434
                }
742✔
435

742✔
436
                obj, err := b.FindObject(pkgName, typeName)
742✔
437
                if err != nil {
743✔
438
                        return nil, err
1✔
439
                }
1✔
440
                t := code.Unalias(obj.Type())
741✔
441
                if values := b.enumValues(def); len(values) > 0 {
743✔
442
                        err = b.enumReference(ref, obj, values)
2✔
443
                        if err != nil {
2✔
444
                                return nil, err
×
445
                        }
×
446
                } else if fun, isFunc := obj.(*types.Func); isFunc {
1,212✔
447
                        ref.GO = code.Unalias(t.(*types.Signature).Params().At(0).Type())
473✔
448
                        ref.IsContext = code.Unalias(t.(*types.Signature).Results().At(0).Type()).String() == "github.com/99designs/gqlgen/graphql.ContextMarshaler"
473✔
449
                        ref.Marshaler = fun
473✔
450
                        ref.Unmarshaler = types.NewFunc(0, fun.Pkg(), "Unmarshal"+typeName, nil)
473✔
451
                } else if hasMethod(t, "MarshalGQLContext") && hasMethod(t, "UnmarshalGQLContext") {
739✔
452
                        ref.GO = t
×
453
                        ref.IsContext = true
×
454
                        ref.IsMarshaler = true
×
455
                } else if hasMethod(t, "MarshalGQL") && hasMethod(t, "UnmarshalGQL") {
266✔
456
                        ref.GO = t
×
457
                        ref.IsMarshaler = true
×
458
                } else if underlying := basicUnderlying(t); def.IsLeafType() && underlying != nil && underlying.Kind() == types.String {
272✔
459
                        // TODO delete before v1. Backwards compatibility case for named types wrapping strings (see #595)
6✔
460

6✔
461
                        ref.GO = t
6✔
462
                        ref.CastType = underlying
6✔
463

6✔
464
                        underlyingRef, err := b.TypeReference(&ast.Type{NamedType: "String"}, nil)
6✔
465
                        if err != nil {
6✔
466
                                return nil, err
×
467
                        }
×
468

469
                        ref.Marshaler = underlyingRef.Marshaler
6✔
470
                        ref.Unmarshaler = underlyingRef.Unmarshaler
6✔
471
                } else {
260✔
472
                        ref.GO = t
260✔
473
                }
260✔
474

475
                ref.Target = ref.GO
741✔
476
                ref.GO = b.CopyModifiersFromAst(schemaType, ref.GO)
741✔
477

741✔
478
                if bindTarget != nil {
1,244✔
479
                        if err = code.CompatibleTypes(ref.GO, bindTarget); err != nil {
505✔
480
                                continue
2✔
481
                        }
482
                        ref.GO = bindTarget
501✔
483
                }
484

485
                ref.PointersInUnmarshalInput = b.cfg.ReturnPointersInUnmarshalInput
739✔
486

739✔
487
                return ref, nil
739✔
488
        }
489

490
        return nil, fmt.Errorf("%s is incompatible with %s", schemaType.Name(), bindTarget.String())
2✔
491
}
492

493
func isValid(t types.Type) bool {
743✔
494
        basic, isBasic := t.(*types.Basic)
743✔
495
        if !isBasic {
1,326✔
496
                return true
583✔
497
        }
583✔
498
        return basic.Kind() != types.Invalid
160✔
499
}
500

501
func (b *Binder) CopyModifiersFromAst(t *ast.Type, base types.Type) types.Type {
1,383✔
502
        base = types.Unalias(base)
1,383✔
503
        if t.Elem != nil {
1,557✔
504
                child := b.CopyModifiersFromAst(t.Elem, base)
174✔
505
                if _, isStruct := child.Underlying().(*types.Struct); isStruct && !b.cfg.OmitSliceElementPointers {
295✔
506
                        child = types.NewPointer(child)
121✔
507
                }
121✔
508
                return types.NewSlice(child)
174✔
509
        }
510

511
        var isInterface bool
1,209✔
512
        if named, ok := base.(*types.Named); ok {
1,666✔
513
                _, isInterface = named.Underlying().(*types.Interface)
457✔
514
        }
457✔
515

516
        if !isInterface && !IsNilable(base) && !t.NonNull {
1,710✔
517
                return types.NewPointer(base)
501✔
518
        }
501✔
519

520
        return base
708✔
521
}
522

523
func IsNilable(t types.Type) bool {
2,293✔
524
        // Note that we use types.Unalias rather than code.Unalias here
2,293✔
525
        // because we want to always check the underlying type.
2,293✔
526
        // code.Unalias only unwraps aliases in Go 1.23
2,293✔
527
        t = types.Unalias(t)
2,293✔
528
        if namedType, isNamed := t.(*types.Named); isNamed {
2,925✔
529
                return IsNilable(namedType.Underlying())
632✔
530
        }
632✔
531
        _, isPtr := t.(*types.Pointer)
1,661✔
532
        _, isNilableMap := t.(*types.Map)
1,661✔
533
        _, isInterface := t.(*types.Interface)
1,661✔
534
        _, isSlice := t.(*types.Slice)
1,661✔
535
        _, isChan := t.(*types.Chan)
1,661✔
536
        return isPtr || isNilableMap || isInterface || isSlice || isChan
1,661✔
537
}
538

539
func hasMethod(it types.Type, name string) bool {
532✔
540
        if ptr, isPtr := it.(*types.Pointer); isPtr {
532✔
541
                it = ptr.Elem()
×
542
        }
×
543
        namedType, ok := it.(*types.Named)
532✔
544
        if !ok {
532✔
545
                return false
×
546
        }
×
547

548
        for i := 0; i < namedType.NumMethods(); i++ {
3,464✔
549
                if namedType.Method(i).Name() == name {
2,932✔
550
                        return true
×
551
                }
×
552
        }
553
        return false
532✔
554
}
555

556
func basicUnderlying(it types.Type) *types.Basic {
266✔
557
        it = types.Unalias(it)
266✔
558
        if ptr, isPtr := it.(*types.Pointer); isPtr {
266✔
559
                it = types.Unalias(ptr.Elem())
×
560
        }
×
561
        namedType, ok := it.(*types.Named)
266✔
562
        if !ok {
266✔
563
                return nil
×
564
        }
×
565

566
        if basic, ok := namedType.Underlying().(*types.Basic); ok {
272✔
567
                return basic
6✔
568
        }
6✔
569

570
        return nil
260✔
571
}
572

573
type EnumValueReference struct {
574
        Definition *ast.EnumValueDefinition
575
        Object     types.Object
576
}
577

578
func (b *Binder) enumValues(def *ast.Definition) map[string]EnumValue {
741✔
579
        if def.Kind != ast.Enum {
1,456✔
580
                return nil
715✔
581
        }
715✔
582

583
        if strings.HasPrefix(def.Name, "__") {
50✔
584
                return nil
24✔
585
        }
24✔
586

587
        model, ok := b.cfg.Models[def.Name]
2✔
588
        if !ok {
2✔
589
                return nil
×
590
        }
×
591

592
        return model.EnumValues
2✔
593
}
594

595
func (b *Binder) enumReference(ref *TypeReference, obj types.Object, values map[string]EnumValue) error {
2✔
596
        if len(ref.Definition.EnumValues) != len(values) {
2✔
597
                return fmt.Errorf("not all enum values are binded for %v", ref.Definition.Name)
×
598
        }
×
599

600
        t := code.Unalias(obj.Type())
2✔
601
        if fn, ok := t.(*types.Signature); ok {
3✔
602
                ref.GO = code.Unalias(fn.Params().At(0).Type())
1✔
603
        } else {
2✔
604
                ref.GO = t
1✔
605
        }
1✔
606

607
        str, err := b.TypeReference(&ast.Type{NamedType: "String"}, nil)
2✔
608
        if err != nil {
2✔
609
                return err
×
610
        }
×
611

612
        ref.Marshaler = str.Marshaler
2✔
613
        ref.Unmarshaler = str.Unmarshaler
2✔
614
        ref.EnumValues = make([]EnumValueReference, 0, len(values))
2✔
615

2✔
616
        for _, value := range ref.Definition.EnumValues {
6✔
617
                v, ok := values[value.Name]
4✔
618
                if !ok {
4✔
619
                        return fmt.Errorf("enum value not found for: %v, of enum: %v", value.Name, ref.Definition.Name)
×
620
                }
×
621

622
                pkgName, typeName := code.PkgAndType(v.Value)
4✔
623
                if pkgName == "" {
4✔
624
                        return fmt.Errorf("missing package name for %v", value.Name)
×
625
                }
×
626

627
                valueObj, err := b.FindObject(pkgName, typeName)
4✔
628
                if err != nil {
4✔
629
                        return err
×
630
                }
×
631

632
                valueTyp := code.Unalias(valueObj.Type())
4✔
633
                if !types.AssignableTo(valueTyp, ref.GO) {
4✔
634
                        return fmt.Errorf("wrong type: %v, for enum value: %v, expected type: %v, of enum: %v",
×
635
                                valueTyp, value.Name, ref.GO, ref.Definition.Name)
×
636
                }
×
637

638
                switch valueObj.(type) {
4✔
639
                case *types.Const, *types.Var:
4✔
640
                        ref.EnumValues = append(ref.EnumValues, EnumValueReference{
4✔
641
                                Definition: value,
4✔
642
                                Object:     valueObj,
4✔
643
                        })
4✔
644
                default:
×
645
                        return fmt.Errorf("unsupported enum value for: %v, of enum: %v, only const and var allowed",
×
646
                                value.Name, ref.Definition.Name)
×
647
                }
648
        }
649

650
        return nil
2✔
651
}
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