Skip to content

Commit

Permalink
Implement scalar leafs validator
Browse files Browse the repository at this point in the history
  • Loading branch information
Adam Scarr committed Jul 11, 2018
1 parent 5f29b46 commit 923c6ed
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 3 deletions.
9 changes: 9 additions & 0 deletions ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,12 +172,17 @@ type Directive struct {

type Type interface {
Name() string
String() string
}

func (t NamedType) Name() string { return string(t) }
func (t ListType) Name() string { return t.Type.Name() }
func (t NonNullType) Name() string { return t.Type.Name() }

func (t NamedType) String() string { return string(t) }
func (t ListType) String() string { return "[" + t.Type.Name() + "]" }
func (t NonNullType) String() string { return t.Type.Name() + "!" }

type NamedType string

type ListType struct {
Expand Down Expand Up @@ -238,6 +243,10 @@ func (d *Definition) Field(name string) *FieldDefinition {
return nil
}

func (d *Definition) IsLeafType() bool {
return d.Kind == Enum || d.Kind == Scalar
}

func (d *Definition) IsAbstractType() bool {
return d.Kind == Interface || d.Kind == Union
}
Expand Down
8 changes: 7 additions & 1 deletion validator/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,17 @@ func Message(msg string, args ...interface{}) Option {
}
}

func Suggest(typed string, suggestions []string) Option {
func SuggestList(typed string, suggestions []string) Option {
suggested := suggestionList(typed, suggestions)
return func(err *errors.Validation) {
if len(suggested) > 0 {
err.Message += " Did you mean " + quotedOrList(suggested...) + "?"
}
}
}

func Suggestf(suggestion string, args ...interface{}) Option {
return func(err *errors.Validation) {
err.Message += " Did you mean " + fmt.Sprintf(suggestion, args...) + "?"
}
}
4 changes: 2 additions & 2 deletions validator/known_argument_names.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func knownFieldArgumentNames(ctx *vctx, parentDef *gqlparser.Definition, fieldDe
ctx.errors = append(ctx.errors, Error(
Rule("KnownArgumentNames"),
Message(`Unknown argument "%s" on field "%s" of type "%s".`, arg.Name, field.Name, parentDef.Name),
Suggest(arg.Name, suggestions),
SuggestList(arg.Name, suggestions),
))
}
}
Expand All @@ -51,7 +51,7 @@ func knowDirectiveArgumentNames(ctx *vctx, parentDef *gqlparser.Definition, dire
ctx.errors = append(ctx.errors, Error(
Rule("KnownArgumentNames"),
Message(`Unknown argument "%s" on directive "@%s".`, arg.Name, directive.Name),
Suggest(arg.Name, suggestions),
SuggestList(arg.Name, suggestions),
))
}
}
33 changes: 33 additions & 0 deletions validator/scalar_leafs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package validator

import "github.com/vektah/gqlparser"

func init() {
fieldVisitors = append(fieldVisitors, scalarLeafs)
}

func scalarLeafs(ctx *vctx, parentDef *gqlparser.Definition, fieldDef *gqlparser.FieldDefinition, field *gqlparser.Field) {
if fieldDef == nil {
return
}

fieldType := ctx.schema.Types[fieldDef.Type.Name()]
if fieldType == nil {
return
}

if fieldType.IsLeafType() && len(field.SelectionSet) > 0 {
ctx.errors = append(ctx.errors, Error(
Rule("ScalarLeafs"),
Message(`Field "%s" must not have a selection since type "%s" has no subfields.`, field.Name, fieldType.Name),
))
}

if !fieldType.IsLeafType() && len(field.SelectionSet) == 0 {
ctx.errors = append(ctx.errors, Error(
Rule("ScalarLeafs"),
Message(`Field "%s" of type "%s" must have a selection of subfields.`, field.Name, fieldDef.Type.String()),
Suggestf(`"%s { ... }"`, field.Name),
))
}
}
2 changes: 2 additions & 0 deletions validator/validate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ func TestSpec(t *testing.T) {
t.Run("FragmentsOnCompositeTypes", runSpec(schemas, deviations, "../spec/validation/FragmentsOnCompositeTypes.yml"))
t.Run("KnownArgumentNames", runSpec(schemas, deviations, "../spec/validation/KnownArgumentNames.yml"))
t.Run("KnownDirectives", runSpec(schemas, deviations, "../spec/validation/KnownDirectives.yml"))

t.Run("ScalarLeafs", runSpec(schemas, deviations, "../spec/validation/ScalarLeafs.yml"))
}

func runSpec(schemas []*gqlparser.Schema, deviations map[string]*Spec, filename string) func(t *testing.T) {
Expand Down

0 comments on commit 923c6ed

Please sign in to comment.