Skip to content

Commit

Permalink
Interfaces and starwars example
Browse files Browse the repository at this point in the history
  • Loading branch information
Adam Scarr committed Feb 5, 2018
1 parent 29110e7 commit 6a76bbf
Show file tree
Hide file tree
Showing 14 changed files with 1,789 additions and 682 deletions.
66 changes: 44 additions & 22 deletions cmd/ggraphqlc/dumper.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ func write(extractor extractor, out io.Writer) {
wr.writeObjectResolver(object)
}
wr.writeSchema()
wr.importHack()
}

func (w *writer) emit(format string, args ...interface{}) {
Expand Down Expand Up @@ -89,13 +90,12 @@ func (w *writer) writeInterface() {
w.emitIndent()
w.emit("%s_%s(", o.Name, f.GraphQLName)

first := true
w.emit("ctx context.Context")
if o.Type.Name != "interface{}" {
w.emit(", it *%s", o.Type.Local())
}
for _, arg := range f.Args {
if !first {
w.emit(",")
}
first = false
w.emit("%s %s", arg.Name, arg.Type.Local())
w.emit(", %s %s", arg.Name, arg.Type.Local())
}
w.emit(") (%s, error)", f.Type.Local())
w.lf()
Expand Down Expand Up @@ -124,10 +124,14 @@ func (w *writer) writeObjectResolver(object object) {
w.begin("case %s:", strconv.Quote(field.GraphQLName))

if field.VarName != "" {
w.writeVarResolver(field)
w.writeEvaluateVar(field)
} else {
w.writeMethodResolver(object, field)
w.writeEvaluateMethod(object, field)
}

w.writeJsonType("json", field.Type, "res")
w.line("resultMap.Set(field.Alias, json)")

w.line("continue")
w.end("")
}
Expand All @@ -140,7 +144,11 @@ func (w *writer) writeObjectResolver(object object) {
w.lf()
}

func (w *writer) writeMethodResolver(object object, field Field) {
func (w *writer) writeEvaluateVar(field Field) {
w.line("res := %s", field.VarName)
}

func (w *writer) writeEvaluateMethod(object object, field Field) {
var methodName string
if field.MethodName != "" {
methodName = field.MethodName
Expand All @@ -151,35 +159,32 @@ func (w *writer) writeMethodResolver(object object, field Field) {
if field.NoErr {
w.emitIndent()
w.emit("res := %s", methodName)
w.writeFuncArgs(field)
w.writeFuncArgs(object, field)
} else {
w.emitIndent()
w.emit("res, err := %s", methodName)
w.writeFuncArgs(field)
w.writeFuncArgs(object, field)
w.line("if err != nil {")
w.line(" ec.Error(err)")
w.line(" continue")
w.line("}")
}

w.writeJsonType("json", field.Type, "res")

w.line("resultMap.Set(field.Alias, json)")
}

func (w *writer) writeVarResolver(field Field) {
w.writeJsonType("res", field.Type, field.VarName)
w.line("resultMap.Set(field.Alias, res)")
}

func (w *writer) writeFuncArgs(field Field) {
if len(field.Args) == 0 {
func (w *writer) writeFuncArgs(object object, field Field) {
if len(field.Args) == 0 && field.MethodName != "" {
w.emit("()")
w.lf()
} else {
w.indent++
w.emit("(")
w.lf()
if field.MethodName == "" {
w.line("ec.ctx,")
if object.Type.Name != "interface{}" {
w.line("it,")
}
}
for _, arg := range field.Args {
w.line("field.Args[%s].(%s),", strconv.Quote(arg.Name), arg.Type.Local())
}
Expand Down Expand Up @@ -220,6 +225,19 @@ func (w *writer) doWriteJsonType(result string, t Type, val string, remainingMod
val = "*" + val
}
w.line("%s := jsonw.%s(%s)", result, ucFirst(t.Name), val)
} else if len(t.Implementors) > 0 {
w.line("var %s jsonw.Encodable = jsonw.Null", result)
w.line("switch it := %s.(type) {", val)
for _, implementor := range t.Implementors {
w.line("case %s:", implementor.Local())
w.line(" %s = %sType{}.executeSelectionSet(ec, field.Selections, &it)", result, lcFirst(implementor.GraphQLName))
w.line("case *%s:", implementor.Local())
w.line(" %s = %sType{}.executeSelectionSet(ec, field.Selections, it)", result, lcFirst(implementor.GraphQLName))
}

w.line("default:")
w.line(` panic(fmt.Errorf("unexpected type %%T", it))`)
w.line("}")
} else {
if !isPtr {
val = "&" + val
Expand All @@ -243,3 +261,7 @@ func lcFirst(s string) string {
func (w *writer) writeSchema() {
w.line("var parsedSchema = schema.MustParse(%s)", strconv.Quote(w.schemaRaw))
}

func (w *writer) importHack() {
w.line("var _ = fmt.Print")
}
44 changes: 36 additions & 8 deletions cmd/ggraphqlc/extractor.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ import (
"go/types"
"os"
"path/filepath"
"sort"
"strconv"
"strings"

"sort"

"github.com/vektah/graphql-go/common"
"github.com/vektah/graphql-go/schema"
"golang.org/x/tools/go/loader"
Expand Down Expand Up @@ -61,6 +60,7 @@ func (e *extractor) getType(name string) Type {
}
}
fmt.Fprintf(os.Stderr, "unknown go type for %s, using interface{}. you should add it to types.json\n", name)
e.goTypeMap[name] = "interface{}"
return Type{
GraphQLName: name,
Name: "interface{}",
Expand Down Expand Up @@ -100,6 +100,8 @@ func (e *extractor) buildType(t common.Type) Type {
goType = "bool"
case "Int":
goType = "int"
case "Float":
goType = "float64"
default:
panic(fmt.Errorf("unknown scalar %s", val.Name))
}
Expand All @@ -117,6 +119,31 @@ func (e *extractor) buildType(t common.Type) Type {
t := e.getType(val.Name)
t.Modifiers = modifiers
return t
case *schema.Interface:
t := e.getType(val.Name)
t.Modifiers = modifiers
if t.Modifiers[len(t.Modifiers)-1] == modPtr {
t.Modifiers = t.Modifiers[0 : len(t.Modifiers)-1]
}

for _, implementor := range val.PossibleTypes {
t.Implementors = append(t.Implementors, e.getType(implementor.Name))
}

return t
case *schema.Union:
t := e.getType(val.Name)
t.Modifiers = modifiers

for _, implementor := range val.PossibleTypes {
t.Implementors = append(t.Implementors, e.getType(implementor.Name))
}

return t
case *schema.InputObject:
t := e.getType(val.Name)
t.Modifiers = modifiers
return t
case *schema.Enum:
return Type{
Basic: true,
Expand Down Expand Up @@ -279,12 +306,13 @@ const (
)

type Type struct {
GraphQLName string
Name string
Package string
ImportedAs string
Modifiers []string
Basic bool
GraphQLName string
Name string
Package string
ImportedAs string
Modifiers []string
Basic bool
Implementors []Type
}

func (t Type) Local() string {
Expand Down
52 changes: 28 additions & 24 deletions cmd/ggraphqlc/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ import (
"encoding/json"
"flag"
"fmt"
"io"
"io/ioutil"
"os"

"io"

"github.com/vektah/graphql-go/schema"
)

Expand Down Expand Up @@ -43,33 +42,14 @@ func main() {
os.Exit(1)
}

b, err := ioutil.ReadFile(*typemap)
if err != nil {
fmt.Fprintln(os.Stderr, "unable to open typemap: "+err.Error())
os.Exit(1)
}

goTypes := map[string]string{
"__Directive": "github.com/vektah/graphql-go/introspection.Directive",
"__Type": "github.com/vektah/graphql-go/introspection.Type",
"__Field": "github.com/vektah/graphql-go/introspection.Field",
"__EnumValue": "github.com/vektah/graphql-go/introspection.EnumValue",
"__InputValue": "github.com/vektah/graphql-go/introspection.InputValue",
"__Schema": "github.com/vektah/graphql-go/introspection.Schema",
"Query": "interface{}",
"Mutation": "interface{}",
}
if err = json.Unmarshal(b, &goTypes); err != nil {
fmt.Fprintln(os.Stderr, "unable to parse typemap: "+err.Error())
os.Exit(1)
}

e := extractor{
PackageName: *packageName,
goTypeMap: goTypes,
goTypeMap: loadTypeMap(),
schemaRaw: string(schemaRaw),
Imports: map[string]string{
"strconv": "strconv",
"fmt": "fmt",
"context": "context",
"jsonw": "github.com/vektah/graphql-go/jsonw",
"query": "github.com/vektah/graphql-go/query",
"schema": "github.com/vektah/graphql-go/schema",
Expand Down Expand Up @@ -118,3 +98,27 @@ func main() {

write(e, out)
}

func loadTypeMap() map[string]string {
goTypes := map[string]string{
"__Directive": "github.com/vektah/graphql-go/introspection.Directive",
"__Type": "github.com/vektah/graphql-go/introspection.Type",
"__Field": "github.com/vektah/graphql-go/introspection.Field",
"__EnumValue": "github.com/vektah/graphql-go/introspection.EnumValue",
"__InputValue": "github.com/vektah/graphql-go/introspection.InputValue",
"__Schema": "github.com/vektah/graphql-go/introspection.Schema",
"Query": "interface{}",
"Mutation": "interface{}",
}
b, err := ioutil.ReadFile(*typemap)
if err != nil {
fmt.Fprintln(os.Stderr, "unable to open typemap: "+err.Error()+" creating it.")
return goTypes
}
if err = json.Unmarshal(b, &goTypes); err != nil {
fmt.Fprintln(os.Stderr, "unable to parse typemap: "+err.Error())
os.Exit(1)
}

return goTypes
}
Loading

0 comments on commit 6a76bbf

Please sign in to comment.