Skip to content

Commit

Permalink
Add an error message when using types inside inputs
Browse files Browse the repository at this point in the history
  • Loading branch information
vektah committed Apr 26, 2018
1 parent a780ce6 commit e7539f1
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 27 deletions.
36 changes: 18 additions & 18 deletions codegen/codegen.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package codegen

import (
"bytes"
"fmt"
"go/build"
"io/ioutil"
Expand All @@ -21,15 +22,15 @@ type Config struct {

schema *schema.Schema

ExecFilename string
ExecPackageName string
execDir string
fullExecPackageName string
ExecFilename string
ExecPackageName string
execPackagePath string
execDir string

ModelFilename string
ModelPackageName string
modelDir string
fullModelPackageName string
ModelFilename string
ModelPackageName string
modelPackagePath string
modelDir string
}

func Generate(cfg Config) error {
Expand All @@ -46,8 +47,8 @@ func Generate(cfg Config) error {
}
if len(modelsBuild.Models) > 0 {
modelsBuild.PackageName = cfg.ModelPackageName

buf, err := templates.Run("models.gotpl", modelsBuild)
var buf *bytes.Buffer
buf, err = templates.Run("models.gotpl", modelsBuild)
if err != nil {
return errors.Wrap(err, "model generation failed")
}
Expand All @@ -56,11 +57,11 @@ func Generate(cfg Config) error {
return err
}
for _, model := range modelsBuild.Models {
cfg.Typemap[model.GQLType] = cfg.fullModelPackageName + "." + model.GoType
cfg.Typemap[model.GQLType] = cfg.modelPackagePath + "." + model.GoType
}

for _, enum := range modelsBuild.Enums {
cfg.Typemap[enum.GQLType] = cfg.fullModelPackageName + "." + enum.GoType
cfg.Typemap[enum.GQLType] = cfg.modelPackagePath + "." + enum.GoType
}
}

Expand All @@ -71,7 +72,8 @@ func Generate(cfg Config) error {
build.SchemaRaw = cfg.SchemaStr
build.PackageName = cfg.ExecPackageName

buf, err := templates.Run("generated.gotpl", build)
var buf *bytes.Buffer
buf, err = templates.Run("generated.gotpl", build)
if err != nil {
return errors.Wrap(err, "exec codegen failed")
}
Expand All @@ -91,7 +93,7 @@ func (cfg *Config) normalize() error {
if cfg.ModelPackageName == "" {
cfg.ModelPackageName = filepath.Base(cfg.modelDir)
}
cfg.fullModelPackageName = fullPackageName(cfg.modelDir, cfg.ModelPackageName)
cfg.modelPackagePath = fullPackageName(cfg.modelDir, cfg.ModelPackageName)

if cfg.ExecFilename == "" {
return errors.New("ModelFilename is required")
Expand All @@ -101,7 +103,7 @@ func (cfg *Config) normalize() error {
if cfg.ExecPackageName == "" {
cfg.ExecPackageName = filepath.Base(cfg.execDir)
}
cfg.fullExecPackageName = fullPackageName(cfg.execDir, cfg.ExecPackageName)
cfg.execPackagePath = fullPackageName(cfg.execDir, cfg.ExecPackageName)

builtins := map[string]string{
"__Directive": "github.com/vektah/gqlgen/neelance/introspection.Directive",
Expand Down Expand Up @@ -145,9 +147,7 @@ func fullPackageName(dir string, pkgName string) string {

for _, gopath := range filepath.SplitList(build.Default.GOPATH) {
gopath = filepath.Join(gopath, "src") + string(os.PathSeparator)
if strings.HasPrefix(fullPkgName, gopath) {
fullPkgName = fullPkgName[len(gopath):]
}
fullPkgName = strings.TrimPrefix(fullPkgName, gopath)
}
return filepath.ToSlash(fullPkgName)
}
Expand Down
25 changes: 19 additions & 6 deletions codegen/input_build.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,21 @@ func (cfg *Config) buildInputs(namedTypes NamedTypes, prog *loader.Program, impo
for _, typ := range cfg.schema.Types {
switch typ := typ.(type) {
case *schema.InputObject:
input := buildInput(namedTypes, typ)
input, err := buildInput(namedTypes, typ)
if err != nil {
return nil, err
}

def, err := findGoType(prog, input.Package, input.GoType)
if err != nil {
return nil, errors.Wrap(err, "cannot find type")
}
if def != nil {
input.Marshaler = buildInputMarshaler(typ, def)
bindObject(def.Type(), input, imports)
err = bindObject(def.Type(), input, imports)
if err != nil {
return nil, err
}
}

inputs = append(inputs, input)
Expand All @@ -38,17 +44,24 @@ func (cfg *Config) buildInputs(namedTypes NamedTypes, prog *loader.Program, impo
return inputs, nil
}

func buildInput(types NamedTypes, typ *schema.InputObject) *Object {
func buildInput(types NamedTypes, typ *schema.InputObject) (*Object, error) {
obj := &Object{NamedType: types[typ.TypeName()]}

for _, field := range typ.Values {
obj.Fields = append(obj.Fields, Field{
newField := Field{
GQLName: field.Name.Name,
Type: types.getType(field.Type),
Object: obj,
})
}

if !newField.Type.IsInput && !newField.Type.IsScalar {
return nil, errors.Errorf("%s cannot be used as a field of %s. only input and scalar types are allowed", newField.GQLType, obj.GQLType)
}

obj.Fields = append(obj.Fields, newField)

}
return obj
return obj, nil
}

// if user has implemented an UnmarshalGQL method on the input type manually, use it
Expand Down
5 changes: 4 additions & 1 deletion codegen/models_build.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ func (cfg *Config) buildModels(types NamedTypes, prog *loader.Program) ([]Model,
}
model = cfg.obj2Model(obj)
case *schema.InputObject:
obj := buildInput(types, typ)
obj, err := buildInput(types, typ)
if err != nil {
return nil, err
}
if obj.IsUserDefined {
continue
}
Expand Down
5 changes: 4 additions & 1 deletion codegen/object_build.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ func (cfg *Config) buildObjects(types NamedTypes, prog *loader.Program, imports
return nil, err
}
if def != nil {
bindObject(def.Type(), obj, imports)
err = bindObject(def.Type(), obj, imports)
if err != nil {
return nil, err
}
}

objects = append(objects, obj)
Expand Down
20 changes: 19 additions & 1 deletion codegen/tests/input_union_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"github.com/vektah/gqlgen/codegen"
)

func TestInputUnion(t *testing.T) {
func TestTypeUnionAsInput(t *testing.T) {
err := codegen.Generate(codegen.Config{
SchemaStr: `
type Query {
Expand All @@ -22,3 +22,21 @@ func TestInputUnion(t *testing.T) {

require.EqualError(t, err, "model plan failed: Bookmarkable! cannot be used as argument of Query.addBookmark. only input and scalar types are allowed")
}

func TestTypeInInput(t *testing.T) {
err := codegen.Generate(codegen.Config{
SchemaStr: `
type Query {
addBookmark(b: BookmarkableInput!): Boolean!
}
type Item {}
input BookmarkableInput {
item: Item
}
`,
ExecFilename: "gen/typeinput/exec.go",
ModelFilename: "gen/typeinput/model.go",
})

require.EqualError(t, err, "model plan failed: Item cannot be used as a field of BookmarkableInput. only input and scalar types are allowed")
}

0 comments on commit e7539f1

Please sign in to comment.