Skip to content

Commit

Permalink
support to generate model for intermediate interface (#1982)
Browse files Browse the repository at this point in the history
* support to generate model for intermediate interface

* go generate ./... in example

* fixed filepath generation
  • Loading branch information
Code-Hex authored Feb 28, 2022
1 parent 3ec8363 commit 82fefdb
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 1 deletion.
2 changes: 1 addition & 1 deletion _examples/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.16
replace github.com/99designs/gqlgen => ../

require (
github.com/99designs/gqlgen v0.0.0-00010101000000-000000000000
github.com/99designs/gqlgen v0.16.0
github.com/gorilla/websocket v1.4.2
github.com/mitchellh/mapstructure v1.4.1
github.com/opentracing/opentracing-go v1.2.0
Expand Down
2 changes: 2 additions & 0 deletions plugin/modelgen/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type ModelBuild struct {
type Interface struct {
Description string
Name string
Implements []string
}

type Object struct {
Expand Down Expand Up @@ -97,6 +98,7 @@ func (m *Plugin) MutateConfig(cfg *config.Config) error {
it := &Interface{
Description: schemaType.Description,
Name: schemaType.Name,
Implements: schemaType.Interfaces,
}

b.Interfaces = append(b.Interfaces, it)
Expand Down
3 changes: 3 additions & 0 deletions plugin/modelgen/models.gotpl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
{{- range $model := .Interfaces }}
{{ with .Description }} {{.|prefixLines "// "}} {{ end }}
type {{.Name|go }} interface {
{{- range $impl := .Implements }}
{{ $impl|go }}
{{- end }}
Is{{.Name|go }}()
}
{{- end }}
Expand Down
100 changes: 100 additions & 0 deletions plugin/modelgen/models_test.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package modelgen

import (
"go/ast"
"go/parser"
"go/token"
"io/ioutil"
"path/filepath"
"strings"
"testing"

"github.com/99designs/gqlgen/codegen/config"
"github.com/99designs/gqlgen/plugin/modelgen/out"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -87,6 +90,93 @@ func TestModelGeneration(t *testing.T) {
t.Run("concrete types implement interface", func(t *testing.T) {
var _ out.FooBarer = out.FooBarr{}
})

t.Run("implemented interfaces", func(t *testing.T) {
pkg, err := parseAst("out")
require.NoError(t, err)

path := filepath.Join("out", "generated.go")
generated := pkg.Files[path]

type field struct {
typ string
name string
}
cases := []struct {
name string
wantFields []field
}{
{
name: "A",
wantFields: []field{
{
typ: "method",
name: "IsA",
},
},
},
{
name: "B",
wantFields: []field{
{
typ: "method",
name: "IsB",
},
},
},
{
name: "C",
wantFields: []field{
{
typ: "ident",
name: "A",
},
{
typ: "method",
name: "IsC",
},
},
},
{
name: "D",
wantFields: []field{
{
typ: "ident",
name: "A",
},
{
typ: "ident",
name: "B",
},
{
typ: "method",
name: "IsD",
},
},
},
}
for _, tc := range cases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
typeSpec, ok := generated.Scope.Lookup(tc.name).Decl.(*ast.TypeSpec)
require.True(t, ok)

fields := typeSpec.Type.(*ast.InterfaceType).Methods.List
for i, want := range tc.wantFields {
if want.typ == "ident" {
ident, ok := fields[i].Type.(*ast.Ident)
require.True(t, ok)
assert.Equal(t, want.name, ident.Name)
}
if want.typ == "method" {
require.GreaterOrEqual(t, 1, len(fields[i].Names))
name := fields[i].Names[0].Name
assert.Equal(t, want.name, name)
}
}
})
}
})
}

func mutateHook(b *ModelBuild) *ModelBuild {
Expand All @@ -98,3 +188,13 @@ func mutateHook(b *ModelBuild) *ModelBuild {

return b
}

func parseAst(path string) (*ast.Package, error) {
// test setup to parse the types
fset := token.NewFileSet()
pkgs, err := parser.ParseDir(fset, path, nil, parser.AllErrors)
if err != nil {
return nil, err
}
return pkgs["out"], nil
}
19 changes: 19 additions & 0 deletions plugin/modelgen/out/generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions plugin/modelgen/testdata/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,23 @@ interface Foo_Barer {
type _Foo_Barr implements Foo_Barer {
name: String!
}

# https://spec.graphql.org/October2021/#sec-Interfaces
interface A {
a: String!
}

interface B {
b: Int!
}

interface C implements A {
a: String!
c: Boolean!
}

interface D implements A & B {
a: String!
b: Int!
d: String
}

0 comments on commit 82fefdb

Please sign in to comment.