From 1d86f9883da24d175611d2268b1ecf4485030a85 Mon Sep 17 00:00:00 2001 From: Adam Scarr Date: Wed, 9 Jan 2019 15:42:25 +1100 Subject: [PATCH] extract argument construction --- codegen/generate.go | 2 +- codegen/unified/build.go | 2 +- codegen/unified/build_bind.go | 4 +-- codegen/unified/build_object.go | 64 ++++++++++++++++++++------------- codegen/unified/object.go | 20 +++++------ codegen/unified/schema_test.go | 4 +-- 6 files changed, 56 insertions(+), 40 deletions(-) diff --git a/codegen/generate.go b/codegen/generate.go index 36b8e211d63..2e91c0dbf77 100644 --- a/codegen/generate.go +++ b/codegen/generate.go @@ -18,7 +18,7 @@ func Generate(cfg *config.Config) error { return errors.Wrap(err, "merging failed") } - if err := buildModels(schema); err != nil { + if err = buildModels(schema); err != nil { return errors.Wrap(err, "generating models failed") } diff --git a/codegen/unified/build.go b/codegen/unified/build.go index 5fd008cc745..6803c02fa83 100644 --- a/codegen/unified/build.go +++ b/codegen/unified/build.go @@ -114,7 +114,7 @@ func (g *Schema) injectIntrospectionRoots() error { GoFieldType: GoFieldMethod, GoReceiverName: "ec", GoFieldName: "introspectType", - Args: []FieldArgument{ + Args: []*FieldArgument{ { GQLName: "name", TypeReference: &TypeReference{ diff --git a/codegen/unified/build_bind.go b/codegen/unified/build_bind.go index fdc83b9a35e..6d4779100bb 100644 --- a/codegen/unified/build_bind.go +++ b/codegen/unified/build_bind.go @@ -146,8 +146,8 @@ func bindVar(t types.Type, field *Field, structTag string) error { return nil } -func matchArgs(field *Field, params *types.Tuple) ([]FieldArgument, error) { - var newArgs []FieldArgument +func matchArgs(field *Field, params *types.Tuple) ([]*FieldArgument, error) { + var newArgs []*FieldArgument nextArg: for j := 0; j < params.Len(); j++ { diff --git a/codegen/unified/build_object.go b/codegen/unified/build_object.go index de42da4339d..48298a62ccb 100644 --- a/codegen/unified/build_object.go +++ b/codegen/unified/build_object.go @@ -12,7 +12,7 @@ import ( func (g *Schema) buildObject(typ *ast.Definition) (*Object, error) { dirs, err := g.getDirectives(typ.Directives) if err != nil { - return nil, err + return nil, errors.Wrap(err, typ.Name) } isRoot := typ == g.Schema.Query || typ == g.Schema.Mutation || typ == g.Schema.Subscription @@ -42,14 +42,16 @@ func (g *Schema) buildObject(typ *ast.Definition) (*Object, error) { f, err := g.buildField(obj, field) if err != nil { - return nil, err + return nil, errors.Wrap(err, typ.Name+"."+field.Name) } if typ.Kind == ast.InputObject && !f.TypeReference.Definition.GQLDefinition.IsInputType() { return nil, errors.Errorf( - "%s cannot be used as a field of %s. only input and scalar types are allowed", + "%s.%s: cannot use %s because %s is not a valid input type", + typ.Name, + field.Name, f.Definition.GQLDefinition.Name, - obj.Definition.GQLDefinition.Name, + f.TypeReference.Definition.GQLDefinition.Kind, ) } @@ -86,7 +88,7 @@ func (g *Schema) buildField(obj *Object, field *ast.FieldDefinition) (*Field, er var err error f.Default, err = field.DefaultValue.Value(nil) if err != nil { - return nil, errors.Errorf("default value for %s.%s is not valid: %s", obj.Definition.GQLDefinition.Name, field.Name, err.Error()) + return nil, errors.Errorf("default value %s is not valid: %s", field.Name, err.Error()) } } @@ -103,30 +105,44 @@ func (g *Schema) buildField(obj *Object, field *ast.FieldDefinition) (*Field, er } for _, arg := range field.Arguments { - argDirs, err := g.getDirectives(arg.Directives) + newArg, err := g.buildArg(obj, arg) if err != nil { return nil, err } - newArg := FieldArgument{ - GQLName: arg.Name, - TypeReference: g.NamedTypes.getType(arg.Type), - Object: obj, - GoVarName: sanitizeArgName(arg.Name), - Directives: argDirs, - } + f.Args = append(f.Args, newArg) + } + return &f, nil +} - if !newArg.TypeReference.Definition.GQLDefinition.IsInputType() { - return nil, errors.Errorf("%s cannot be used as argument of %s.%s. only input and scalar types are allowed", arg.Type, obj.Definition.GQLDefinition.Name, field.Name) - } +func (g *Schema) buildArg(obj *Object, arg *ast.ArgumentDefinition) (*FieldArgument, error) { + argDirs, err := g.getDirectives(arg.Directives) + if err != nil { + return nil, err + } + newArg := FieldArgument{ + GQLName: arg.Name, + TypeReference: g.NamedTypes.getType(arg.Type), + Object: obj, + GoVarName: sanitizeArgName(arg.Name), + Directives: argDirs, + } - if arg.DefaultValue != nil { - var err error - newArg.Default, err = arg.DefaultValue.Value(nil) - if err != nil { - return nil, errors.Errorf("default value for %s.%s is not valid: %s", obj.Definition.GQLDefinition.Name, field.Name, err.Error()) - } + if !newArg.TypeReference.Definition.GQLDefinition.IsInputType() { + return nil, errors.Errorf( + "cannot use %s as argument %s because %s is not a valid input type", + newArg.Definition.GQLDefinition.Name, + arg.Name, + newArg.TypeReference.Definition.GQLDefinition.Kind, + ) + } + + if arg.DefaultValue != nil { + var err error + newArg.Default, err = arg.DefaultValue.Value(nil) + if err != nil { + return nil, errors.Errorf("default value is not valid: %s", err.Error()) } - f.Args = append(f.Args, newArg) } - return &f, nil + + return &newArg, nil } diff --git a/codegen/unified/object.go b/codegen/unified/object.go index 3deaf8e930e..46598d2d3e2 100644 --- a/codegen/unified/object.go +++ b/codegen/unified/object.go @@ -36,16 +36,16 @@ type Object struct { type Field struct { *TypeReference - GQLName string // The name of the field in graphql - GoFieldType GoFieldType // The field type in go, if any - GoReceiverName string // The name of method & var receiver in go, if any - GoFieldName string // The name of the method or var in go, if any - IsResolver bool // Does this field need a resolver - Args []FieldArgument // A list of arguments to be passed to this field - MethodHasContext bool // If this is bound to a go method, does the method also take a context - NoErr bool // If this is bound to a go method, does that method have an error as the second argument - Object *Object // A link back to the parent object - Default interface{} // The default value + GQLName string // The name of the field in graphql + GoFieldType GoFieldType // The field type in go, if any + GoReceiverName string // The name of method & var receiver in go, if any + GoFieldName string // The name of the method or var in go, if any + IsResolver bool // Does this field need a resolver + Args []*FieldArgument // A list of arguments to be passed to this field + MethodHasContext bool // If this is bound to a go method, does the method also take a context + NoErr bool // If this is bound to a go method, does that method have an error as the second argument + Object *Object // A link back to the parent object + Default interface{} // The default value Directives []*Directive } diff --git a/codegen/unified/schema_test.go b/codegen/unified/schema_test.go index 599c485fa3e..fd2f6aeb4fd 100644 --- a/codegen/unified/schema_test.go +++ b/codegen/unified/schema_test.go @@ -10,13 +10,13 @@ import ( func TestTypeUnionAsInput(t *testing.T) { err := generate("inputunion", `testdata/unioninput.graphqls`) - require.EqualError(t, err, "unable to build object definition: Bookmarkable! cannot be used as argument of Query.addBookmark. only input and scalar types are allowed") + require.EqualError(t, err, "unable to build object definition: Query.addBookmark: cannot use Bookmarkable as argument b because UNION is not a valid input type") } func TestTypeInInput(t *testing.T) { err := generate("typeinput", `testdata/typeinput.graphqls`) - require.EqualError(t, err, "unable to build input definition: Item cannot be used as a field of BookmarkableInput. only input and scalar types are allowed") + require.EqualError(t, err, "unable to build input definition: BookmarkableInput.item: cannot use Item because OBJECT is not a valid input type") } func generate(name string, schemaFilename string) error {