Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

introduce ast.Path type #117

Merged
merged 5 commits into from
Feb 9, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 {
Copy link
Owner

@vektah vektah Feb 7, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bug if path starts with number?

eg .[0].foo.bar?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected is [0].foo.bar ? 🤔
I think number is not coming at head of path.
so, this PR can't validate element value.

  1. don't place number at head
  2. don't contains nil value

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