diff --git a/internal/common/lexer.go b/internal/common/lexer.go index ec348745b56..42b0bcd520b 100644 --- a/internal/common/lexer.go +++ b/internal/common/lexer.go @@ -15,11 +15,6 @@ type Lexer struct { descComment string } -type BasicLit struct { - Type rune - Text string -} - type Ident struct { Name string Loc errors.Location diff --git a/internal/common/literals.go b/internal/common/literals.go new file mode 100644 index 00000000000..5440b2452bc --- /dev/null +++ b/internal/common/literals.go @@ -0,0 +1,46 @@ +package common + +import ( + "strconv" + "text/scanner" +) + +type Literal interface { + Value() interface{} +} + +type BasicLit struct { + Type rune + Text string +} + +func (lit *BasicLit) Value() interface{} { + switch lit.Type { + case scanner.Int, scanner.Float: + value, err := strconv.ParseFloat(lit.Text, 64) + if err != nil { + panic(err) + } + return value + + case scanner.String: + value, err := strconv.Unquote(lit.Text) + if err != nil { + panic(err) + } + return value + + case scanner.Ident: + switch lit.Text { + case "true": + return true + case "false": + return false + default: + return lit.Text + } + + default: + panic("invalid literal") + } +} diff --git a/internal/common/values.go b/internal/common/values.go index e3a0ad542a0..ef587cf8f7b 100644 --- a/internal/common/values.go +++ b/internal/common/values.go @@ -1,7 +1,6 @@ package common import ( - "strconv" "text/scanner" "github.com/neelance/graphql-go/errors" @@ -125,34 +124,3 @@ func parseValue(l *Lexer, constOnly bool) interface{} { panic("unreachable") } } - -func UnmarshalLiteral(lit *BasicLit) interface{} { - switch lit.Type { - case scanner.Int, scanner.Float: - value, err := strconv.ParseFloat(lit.Text, 64) - if err != nil { - panic(err) - } - return value - - case scanner.String: - value, err := strconv.Unquote(lit.Text) - if err != nil { - panic(err) - } - return value - - case scanner.Ident: - switch lit.Text { - case "true": - return true - case "false": - return false - default: - return lit.Text - } - - default: - panic("invalid literal") - } -} diff --git a/internal/exec/resolvable/packer.go b/internal/exec/resolvable/packer.go index d1c3d516674..ffd92dc0681 100644 --- a/internal/exec/resolvable/packer.go +++ b/internal/exec/resolvable/packer.go @@ -261,8 +261,8 @@ func (p *ValuePacker) Pack(r *Request, value interface{}) (reflect.Value, error) return reflect.Value{}, errors.Errorf("got null for non-null") } - if lit, ok := value.(*common.BasicLit); ok { - value = common.UnmarshalLiteral(lit) + if lit, ok := value.(common.Literal); ok { + value = lit.Value() } coerced, err := unmarshalInput(p.ValueType, value) @@ -281,8 +281,8 @@ func (p *unmarshalerPacker) Pack(r *Request, value interface{}) (reflect.Value, return reflect.Value{}, errors.Errorf("got null for non-null") } - if lit, ok := value.(*common.BasicLit); ok { - value = common.UnmarshalLiteral(lit) + if lit, ok := value.(common.Literal); ok { + value = lit.Value() } v := reflect.New(p.ValueType) diff --git a/internal/validation/validation.go b/internal/validation/validation.go index 3d970d30503..2046090190c 100644 --- a/internal/validation/validation.go +++ b/internal/validation/validation.go @@ -410,35 +410,31 @@ func validateValue(v interface{}, t common.Type) (bool, string) { return true, "" } - if l, ok := t.(*common.List); ok { - if _, ok := v.([]interface{}); !ok { - return validateValue(v, l.OfType) - } - } - if _, ok := v.(common.Variable); ok { // TODO return true, "" } - if v, ok := v.(*common.BasicLit); ok { - if validateLiteral(v, t) { - return true, "" + switch t := t.(type) { + case *schema.Scalar, *schema.Enum: + if lit, ok := v.(*common.BasicLit); ok { + if validateBasicLit(lit, t) { + return true, "" + } } - } - switch t := t.(type) { case *common.List: - v, ok := v.([]interface{}) + list, ok := v.([]interface{}) if !ok { - return false, fmt.Sprintf("Expected %q, found not a list.", t) + return validateValue(v, t.OfType) // single value instead of list } - for i, entry := range v { + for i, entry := range list { if ok, reason := validateValue(entry, t.OfType); !ok { return false, fmt.Sprintf("In element #%d: %s", i, reason) } } return true, "" + case *schema.InputObject: v, ok := v.(map[string]interface{}) if !ok { @@ -466,7 +462,7 @@ func validateValue(v interface{}, t common.Type) (bool, string) { return false, fmt.Sprintf("Expected type %q, found %s.", t, common.Stringify(v)) } -func validateLiteral(v *common.BasicLit, t common.Type) bool { +func validateBasicLit(v *common.BasicLit, t common.Type) bool { switch t := t.(type) { case *schema.Scalar: switch t.Name { diff --git a/introspection/introspection.go b/introspection/introspection.go index fabcd9a2dc9..87327b18536 100644 --- a/introspection/introspection.go +++ b/introspection/introspection.go @@ -226,7 +226,7 @@ func (r *Field) DeprecationReason() *string { if d == nil { return nil } - reason := common.UnmarshalLiteral(d.Args.MustGet("reason").Value.(*common.BasicLit)).(string) + reason := d.Args.MustGet("reason").Value.(*common.BasicLit).Value().(string) return &reason } @@ -281,7 +281,7 @@ func (r *EnumValue) DeprecationReason() *string { if d == nil { return nil } - reason := common.UnmarshalLiteral(d.Args.MustGet("reason").Value.(*common.BasicLit)).(string) + reason := d.Args.MustGet("reason").Value.(*common.BasicLit).Value().(string) return &reason }