Skip to content

Commit

Permalink
introduce ast.Path type
Browse files Browse the repository at this point in the history
  • Loading branch information
vvakame committed Feb 7, 2020
1 parent c07bed4 commit bc3e688
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 27 deletions.
42 changes: 42 additions & 0 deletions ast/path.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package ast

import (
"bytes"
"fmt"
)

type Path []PathElement

type PathElement interface {
isPathElement()
}

var _ PathElement = PathIndex(0)
var _ PathElement = PathName("")

func (path Path) String() string {
var str bytes.Buffer
for i, v := range path {

switch v := v.(type) {
case PathIndex:
str.WriteString(fmt.Sprintf("[%d]", v))
case PathName:
if i != 0 {
str.WriteByte('.')
}
str.WriteString(string(v))
default:
panic(fmt.Sprintf("unknown type: %T", v))
}
}
return str.String()
}

type PathIndex int

func (_ PathIndex) isPathElement() {}

type PathName string

func (_ PathName) isPathElement() {}
6 changes: 3 additions & 3 deletions ast/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ package ast
// Source covers a single *.graphql file
type Source struct {
// Name is the filename of the source
Name string
Name string
// Input is the actual contents of the source file
Input string
Input string
// BuiltIn indicate whether the source is a part of the specification
BuiltIn bool
}

type Position struct {
Start int // The starting position, in runes, of this token in the input.
End int // The end position, in runes, of this token in the input.
Expand Down
21 changes: 4 additions & 17 deletions gqlerror/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
// Error is the standard graphql error type described in https://facebook.github.io/graphql/draft/#sec-Errors
type Error struct {
Message string `json:"message"`
Path []interface{} `json:"path,omitempty"`
Path ast.Path `json:"path,omitempty"`
Locations []Location `json:"locations,omitempty"`
Extensions map[string]interface{} `json:"extensions,omitempty"`
Rule string `json:"-"`
Expand Down Expand Up @@ -63,20 +63,7 @@ func (err *Error) Error() string {
}

func (err Error) pathString() string {
var str bytes.Buffer
for i, v := range err.Path {

switch v := v.(type) {
case int, int64:
str.WriteString(fmt.Sprintf("[%d]", v))
default:
if i != 0 {
str.WriteByte('.')
}
str.WriteString(fmt.Sprint(v))
}
}
return str.String()
return err.Path.String()
}

func (errs List) Error() string {
Expand All @@ -88,7 +75,7 @@ func (errs List) Error() string {
return buf.String()
}

func WrapPath(path []interface{}, err error) *Error {
func WrapPath(path ast.Path, err error) *Error {
return &Error{
Message: err.Error(),
Path: path,
Expand All @@ -101,7 +88,7 @@ func Errorf(message string, args ...interface{}) *Error {
}
}

func ErrorPathf(path []interface{}, message string, args ...interface{}) *Error {
func ErrorPathf(path ast.Path, message string, args ...interface{}) *Error {
return &Error{
Message: fmt.Sprintf(message, args...),
Path: path,
Expand Down
3 changes: 2 additions & 1 deletion gqlerror/error_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"testing"

"github.com/stretchr/testify/require"
"github.com/vektah/gqlparser/ast"
)

func TestErrorFormatting(t *testing.T) {
Expand All @@ -22,7 +23,7 @@ func TestErrorFormatting(t *testing.T) {
})

t.Run("with path", func(t *testing.T) {
err := ErrorPathf([]interface{}{"a", 1, "b"}, "kabloom")
err := ErrorPathf(ast.Path{ast.PathName("a"), ast.PathIndex(1), ast.PathName("b")}, "kabloom")

require.Equal(t, `input: a[1].b kabloom`, err.Error())
})
Expand Down
12 changes: 6 additions & 6 deletions validator/vars.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ func VariableValues(schema *ast.Schema, op *ast.OperationDefinition, variables m
coercedVars := map[string]interface{}{}

validator := varValidator{
path: []interface{}{"variable"},
path: ast.Path{ast.PathName("variable")},
schema: schema,
}

for _, v := range op.VariableDefinitions {
validator.path = append(validator.path, v.Variable)
validator.path = append(validator.path, ast.PathName(v.Variable))

if !v.Definition.IsInputType() {
return nil, gqlerror.ErrorPathf(validator.path, "must an input type")
Expand Down Expand Up @@ -69,7 +69,7 @@ func VariableValues(schema *ast.Schema, op *ast.OperationDefinition, variables m
}

type varValidator struct {
path []interface{}
path ast.Path
schema *ast.Schema
}

Expand All @@ -87,7 +87,7 @@ func (v *varValidator) validateVarType(typ *ast.Type, val reflect.Value) *gqlerr

for i := 0; i < val.Len(); i++ {
resetPath()
v.path = append(v.path, i)
v.path = append(v.path, ast.PathIndex(i))
field := val.Index(i)

if field.Kind() == reflect.Ptr || field.Kind() == reflect.Interface {
Expand Down Expand Up @@ -171,7 +171,7 @@ func (v *varValidator) validateVarType(typ *ast.Type, val reflect.Value) *gqlerr
val.MapIndex(name)
fieldDef := def.Fields.ForName(name.String())
resetPath()
v.path = append(v.path, name.String())
v.path = append(v.path, ast.PathName(name.String()))

if fieldDef == nil {
return gqlerror.ErrorPathf(v.path, "unknown field")
Expand All @@ -180,7 +180,7 @@ func (v *varValidator) validateVarType(typ *ast.Type, val reflect.Value) *gqlerr

for _, fieldDef := range def.Fields {
resetPath()
v.path = append(v.path, fieldDef.Name)
v.path = append(v.path, ast.PathName(fieldDef.Name))

field := val.MapIndex(reflect.ValueOf(fieldDef.Name))
if !field.IsValid() {
Expand Down

0 comments on commit bc3e688

Please sign in to comment.