Skip to content

Commit

Permalink
Support interface unexported methods
Browse files Browse the repository at this point in the history
  • Loading branch information
dvic committed Jul 28, 2018
1 parent 7226e57 commit 64ec6b8
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 9 deletions.
8 changes: 6 additions & 2 deletions codegen/codegen.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package codegen

import (
"bytes"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"regexp"
Expand Down Expand Up @@ -140,7 +140,7 @@ func write(filename string, b []byte) error {

formatted, err := gofmt(filename, b)
if err != nil {
fmt.Fprintf(os.Stderr, "gofmt failed: %s\n", err.Error())
stdErrLog.Printf("gofmt failed: %s\n", err.Error())
formatted = b
}

Expand All @@ -151,3 +151,7 @@ func write(filename string, b []byte) error {

return nil
}

var (
stdErrLog = log.New(os.Stderr, "", log.LstdFlags)
)
5 changes: 2 additions & 3 deletions codegen/interface_build.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package codegen
import (
"fmt"
"go/types"
"os"
"sort"
"strings"

Expand Down Expand Up @@ -78,9 +77,9 @@ func (cfg *Config) isValueReceiver(intf *NamedType, implementor *NamedType, prog
for i := 0; i < interfaceType.NumMethods(); i++ {
intfMethod := interfaceType.Method(i)

implMethod := findMethod(implementorType, intfMethod.Name())
implMethod := findMethod(implementorType, intfMethod.Name(), false)
if implMethod == nil {
fmt.Fprintf(os.Stderr, "missing method %s on %s\n", intfMethod.Name(), implementor.GoType)
stdErrLog.Printf("missing method %s on %s\n", intfMethod.Name(), implementor.GoType)
return false
}

Expand Down
36 changes: 36 additions & 0 deletions codegen/interface_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package codegen

import (
"strings"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/tools/go/loader"
)
Expand Down Expand Up @@ -36,6 +38,40 @@ func TestShapes(t *testing.T) {

}

func TestInterfaceUnexportedMethods(t *testing.T) {
var buf strings.Builder
stdErrLog.SetOutput(&buf)
err := generate("recursiveinput", `
schema {
query: Query
}
type Query {
entities: [Entity!]
}
interface Entity {
id: ID!
}
type Foo implements Entity {
id: ID!
x: String!
}
type Bar implements Entity {
id: ID!
y: String!
}
`, TypeMap{
"Bar": {Model: "github.com/vektah/gqlgen/codegen/testdata.IfaceBar"},
"Entity": {Model: "github.com/vektah/gqlgen/codegen/testdata.IfaceEntity"},
"Foo": {Model: "github.com/vektah/gqlgen/codegen/testdata.IfaceFoo"},
})
require.NoError(t, err)
assert.Equal(t, "", buf.String(), "using an interface with unexported methods should not emit warnings")
}

func generate(name string, schema string, typemap ...TypeMap) error {
cfg := Config{
SchemaStr: schema,
Expand Down
19 changes: 19 additions & 0 deletions codegen/testdata/iface_models.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package testdata

type IfaceBar struct {
ID string `json:"id"`
Y string `json:"y"`
}

func (IfaceBar) isEntity() {}

type IfaceEntity interface {
isEntity() // nolint: megacheck
}

type IfaceFoo struct {
ID string `json:"id"`
X string `json:"x"`
}

func (IfaceFoo) isEntity() {}
8 changes: 4 additions & 4 deletions codegen/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,10 @@ func findGoInterface(prog *loader.Program, pkgName string, typeName string) (*ty
return underlying, nil
}

func findMethod(typ *types.Named, name string) *types.Func {
func findMethod(typ *types.Named, name string, onlyExported bool) *types.Func {
for i := 0; i < typ.NumMethods(); i++ {
method := typ.Method(i)
if !method.Exported() {
if !method.Exported() && onlyExported {
continue
}

Expand All @@ -94,7 +94,7 @@ func findMethod(typ *types.Named, name string) *types.Func {
}

if named, ok := field.Type().(*types.Named); ok {
if f := findMethod(named, name); f != nil {
if f := findMethod(named, name, onlyExported); f != nil {
return f
}
}
Expand Down Expand Up @@ -194,7 +194,7 @@ func bindMethod(imports *Imports, t types.Type, field *Field) error {
return fmt.Errorf("not a named type")
}

method := findMethod(namedType, field.GQLName)
method := findMethod(namedType, field.GQLName, true)
if method == nil {
return fmt.Errorf("no method named %s", field.GQLName)
}
Expand Down

0 comments on commit 64ec6b8

Please sign in to comment.