diff options
Diffstat (limited to 'vendor/github.com/vektah/gqlgen/codegen/interface_build.go')
-rw-r--r-- | vendor/github.com/vektah/gqlgen/codegen/interface_build.go | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/vendor/github.com/vektah/gqlgen/codegen/interface_build.go b/vendor/github.com/vektah/gqlgen/codegen/interface_build.go new file mode 100644 index 00000000..cdf0f597 --- /dev/null +++ b/vendor/github.com/vektah/gqlgen/codegen/interface_build.go @@ -0,0 +1,94 @@ +package codegen + +import ( + "fmt" + "go/types" + "os" + "sort" + "strings" + + "github.com/vektah/gqlgen/neelance/schema" + "golang.org/x/tools/go/loader" +) + +func (cfg *Config) buildInterfaces(types NamedTypes, prog *loader.Program) []*Interface { + var interfaces []*Interface + for _, typ := range cfg.schema.Types { + switch typ := typ.(type) { + case *schema.Union, *schema.Interface: + interfaces = append(interfaces, cfg.buildInterface(types, typ, prog)) + default: + continue + } + } + + sort.Slice(interfaces, func(i, j int) bool { + return strings.Compare(interfaces[i].GQLType, interfaces[j].GQLType) == -1 + }) + + return interfaces +} + +func (cfg *Config) buildInterface(types NamedTypes, typ schema.NamedType, prog *loader.Program) *Interface { + switch typ := typ.(type) { + + case *schema.Union: + i := &Interface{NamedType: types[typ.TypeName()]} + + for _, implementor := range typ.PossibleTypes { + t := types[implementor.TypeName()] + + i.Implementors = append(i.Implementors, InterfaceImplementor{ + NamedType: t, + ValueReceiver: cfg.isValueReceiver(types[typ.Name], t, prog), + }) + } + + return i + + case *schema.Interface: + i := &Interface{NamedType: types[typ.TypeName()]} + + for _, implementor := range typ.PossibleTypes { + t := types[implementor.TypeName()] + + i.Implementors = append(i.Implementors, InterfaceImplementor{ + NamedType: t, + ValueReceiver: cfg.isValueReceiver(types[typ.Name], t, prog), + }) + } + + return i + default: + panic(fmt.Errorf("unknown interface %#v", typ)) + } +} + +func (cfg *Config) isValueReceiver(intf *NamedType, implementor *NamedType, prog *loader.Program) bool { + interfaceType, err := findGoInterface(prog, intf.Package, intf.GoType) + if interfaceType == nil || err != nil { + return true + } + + implementorType, err := findGoNamedType(prog, implementor.Package, implementor.GoType) + if implementorType == nil || err != nil { + return true + } + + for i := 0; i < interfaceType.NumMethods(); i++ { + intfMethod := interfaceType.Method(i) + + implMethod := findMethod(implementorType, intfMethod.Name()) + if implMethod == nil { + fmt.Fprintf(os.Stderr, "missing method %s on %s\n", intfMethod.Name(), implementor.GoType) + return false + } + + sig := implMethod.Type().(*types.Signature) + if _, isPtr := sig.Recv().Type().(*types.Pointer); isPtr { + return false + } + } + + return true +} |