Skip to content

Commit

Permalink
Add GQL and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
tonyhb committed Oct 21, 2019
1 parent d27f80a commit f5b8a01
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 12 deletions.
132 changes: 123 additions & 9 deletions golden_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ var goldenSQL = []Golden{
{"prime with SQL", primeSqlIn, primeSqlOut},
}

var goldenGQL = []Golden{
{"prime with GQL", primeGqlIn, primeGqlOut},
}

var goldenJSONAndSQL = []Golden{
{"prime with JSONAndSQL", primeJsonAndSqlIn, primeJsonAndSqlOut},
}
Expand Down Expand Up @@ -887,6 +891,113 @@ func (i *Prime) Scan(value interface{}) error {
return nil
}
`
const primeGqlIn = `type Prime int
const (
p2 Prime = 2
p3 Prime = 3
p5 Prime = 5
p7 Prime = 7
p77 Prime = 7 // Duplicate; note that p77 doesn't appear below.
p11 Prime = 11
p13 Prime = 13
p17 Prime = 17
p19 Prime = 19
p23 Prime = 23
p29 Prime = 29
p37 Prime = 31
p41 Prime = 41
p43 Prime = 43
)
`

const primeGqlOut = `
const _PrimeName = "p2p3p5p7p11p13p17p19p23p29p37p41p43"
var _PrimeMap = map[Prime]string{
2: _PrimeName[0:2],
3: _PrimeName[2:4],
5: _PrimeName[4:6],
7: _PrimeName[6:8],
11: _PrimeName[8:11],
13: _PrimeName[11:14],
17: _PrimeName[14:17],
19: _PrimeName[17:20],
23: _PrimeName[20:23],
29: _PrimeName[23:26],
31: _PrimeName[26:29],
41: _PrimeName[29:32],
43: _PrimeName[32:35],
}
func (i Prime) String() string {
if str, ok := _PrimeMap[i]; ok {
return str
}
return fmt.Sprintf("Prime(%d)", i)
}
var _PrimeValues = []Prime{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 41, 43}
var _PrimeNameToValueMap = map[string]Prime{
_PrimeName[0:2]: 2,
_PrimeName[2:4]: 3,
_PrimeName[4:6]: 5,
_PrimeName[6:8]: 7,
_PrimeName[8:11]: 11,
_PrimeName[11:14]: 13,
_PrimeName[14:17]: 17,
_PrimeName[17:20]: 19,
_PrimeName[20:23]: 23,
_PrimeName[23:26]: 29,
_PrimeName[26:29]: 31,
_PrimeName[29:32]: 41,
_PrimeName[32:35]: 43,
}
// PrimeString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func PrimeString(s string) (Prime, error) {
if val, ok := _PrimeNameToValueMap[s]; ok {
return val, nil
}
return 0, fmt.Errorf("%s does not belong to Prime values", s)
}
// PrimeValues returns all values of the enum
func PrimeValues() []Prime {
return _PrimeValues
}
// IsAPrime returns "true" if the value is listed in the enum definition. "false" otherwise
func (i Prime) IsAPrime() bool {
_, ok := _PrimeMap[i]
return ok
}
func (i *Prime) UnmarshalGQL(v interface{}) error {
str, ok := v.(string)
if !ok {
bytes, ok := v.([]byte)
if !ok {
return fmt.Errorf("value is not a byte slice")
}
str = string(bytes[:])
}
val, err := PrimeString(str)
if err != nil {
return err
}
*i = val
return nil
}
func (i Prime) MarshalGQL(w io.Writer) {
_, _ = w.Write([]byte(strconv.Quote(f.String())))
}
`

const primeJsonAndSqlIn = `type Prime int
const (
Expand Down Expand Up @@ -1115,29 +1226,32 @@ func (i Prime) IsAPrime() bool {

func TestGolden(t *testing.T) {
for _, test := range golden {
runGoldenTest(t, test, false, false, false, false, "")
runGoldenTest(t, test, false, false, false, false, false, "")
}
for _, test := range goldenJSON {
runGoldenTest(t, test, true, false, false, false, "")
runGoldenTest(t, test, true, false, false, false, false, "")
}
for _, test := range goldenText {
runGoldenTest(t, test, false, false, false, true, "")
runGoldenTest(t, test, false, false, false, false, true, "")
}
for _, test := range goldenYAML {
runGoldenTest(t, test, false, true, false, false, "")
runGoldenTest(t, test, false, true, false, false, false, "")
}
for _, test := range goldenSQL {
runGoldenTest(t, test, false, false, true, false, "")
runGoldenTest(t, test, false, false, true, false, false, "")
}
for _, test := range goldenGQL {
runGoldenTest(t, test, false, false, false, true, false, "")
}
for _, test := range goldenJSONAndSQL {
runGoldenTest(t, test, true, false, true, false, "")
runGoldenTest(t, test, true, false, true, false, false, "")
}
for _, test := range goldenPrefix {
runGoldenTest(t, test, false, false, false, false, "Day")
runGoldenTest(t, test, false, false, false, false, false, "Day")
}
}

func runGoldenTest(t *testing.T, test Golden, generateJSON, generateYAML, generateSQL, generateText bool, prefix string) {
func runGoldenTest(t *testing.T, test Golden, generateJSON, generateYAML, generateSQL, generateGQL, generateText bool, prefix string) {
var g Generator
input := "package test\n" + test.input
file := test.name + ".go"
Expand All @@ -1164,7 +1278,7 @@ func runGoldenTest(t *testing.T, test Golden, generateJSON, generateYAML, genera
if len(tokens) != 3 {
t.Fatalf("%s: need type declaration on first line", test.name)
}
g.generate(tokens[1], generateJSON, generateYAML, generateSQL, generateText, "noop", prefix, false)
g.generate(tokens[1], generateJSON, generateYAML, generateSQL, generateGQL, generateText, "noop", prefix, false)
got := string(g.format())
if got != test.output {
t.Errorf("%s: got\n====\n%s====\nexpected\n====%s", test.name, got, test.output)
Expand Down
36 changes: 36 additions & 0 deletions gql.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package main

// Arguments to format are:
// [1]: type name
const unmarshalGqlMethod = `func (i *%[1]s) UnmarshalGQL(v interface{}) error {
str, ok := v.(string)
if !ok {
bytes, ok := v.([]byte)
if !ok {
return fmt.Errorf("value is not a byte slice")
}
str = string(bytes[:])
}
val, err := %[1]sString(str)
if err != nil {
return err
}
*i = val
return nil
}
`

const marshalGqlMethod = `func (i %[1]s) MarshalGQL(w io.Writer) {
_, _ = w.Write([]byte(strconv.Quote(f.String())))
}
`

func (g *Generator) addGqlMethods(typeName string) {
g.Printf("\n")
g.Printf(unmarshalGqlMethod, typeName)
g.Printf("\n\n")
g.Printf(marshalGqlMethod, typeName)
}
14 changes: 11 additions & 3 deletions stringer.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@ import (
"go/importer"
"go/token"
"go/types"
"golang.org/x/tools/go/packages"
"io/ioutil"
"log"
"os"
"path/filepath"
"sort"
"strings"

"golang.org/x/tools/go/packages"

"github.com/pascaldekloe/name"
)

Expand All @@ -44,6 +45,7 @@ func (af *arrayFlags) Set(value string) error {

var (
typeNames = flag.String("type", "", "comma-separated list of type names; must be set")
gql = flag.Bool("gql", false, "if true, the MarshalGQL and UnmarshalGQL interface of GQLGen will be implemented.")
sql = flag.Bool("sql", false, "if true, the Scanner and Valuer interface will be implemented.")
json = flag.Bool("json", false, "if true, json marshaling methods will be generated. Default: false")
yaml = flag.Bool("yaml", false, "if true, yaml marshaling methods will be generated. Default: false")
Expand Down Expand Up @@ -117,11 +119,14 @@ func main() {
if *json {
g.Printf("\t\"encoding/json\"\n")
}
if *gql {
g.Printf("\t\"strconv\"\n")
}
g.Printf(")\n")

// Run generate for each type.
for _, typeName := range types {
g.generate(typeName, *json, *yaml, *sql, *text, *transformMethod, *trimPrefix, *lineComment)
g.generate(typeName, *json, *yaml, *sql, *gql, *text, *transformMethod, *trimPrefix, *lineComment)
}

// Format the output.
Expand Down Expand Up @@ -341,7 +346,7 @@ func (g *Generator) replaceValuesWithLineComment(values []Value) {
}

// generate produces the String method for the named type.
func (g *Generator) generate(typeName string, includeJSON, includeYAML, includeSQL, includeText bool, transformMethod string, trimPrefix string, lineComment bool) {
func (g *Generator) generate(typeName string, includeJSON, includeYAML, includeSQL, includeGQL, includeText bool, transformMethod string, trimPrefix string, lineComment bool) {
values := make([]Value, 0, 100)
for _, file := range g.pkg.files {
// Set the state for this run of the walker.
Expand Down Expand Up @@ -401,6 +406,9 @@ func (g *Generator) generate(typeName string, includeJSON, includeYAML, includeS
if includeSQL {
g.addValueAndScanMethod(typeName)
}
if includeGQL {
g.addGqlMethods(typeName)
}
}

// splitIntoRuns breaks the values into runs of contiguous sequences.
Expand Down

0 comments on commit f5b8a01

Please sign in to comment.