Skip to content

Commit

Permalink
graphiql autocomplete working
Browse files Browse the repository at this point in the history
  • Loading branch information
vektah committed Feb 4, 2018
1 parent 2e2c313 commit 2f358e7
Show file tree
Hide file tree
Showing 3 changed files with 286 additions and 67 deletions.
25 changes: 19 additions & 6 deletions cmd/ggraphqlc/dumper.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,11 @@ func (w *writer) writeObjectResolver(object object) {
w.line("type %sType struct {}", lcFirst(object.Type.GraphQLName))
w.lf()

w.begin("func (%sType) accepts(name string) bool {", lcFirst(object.Type.GraphQLName))
w.line("return true")
w.end("}")
w.lf()

w.begin("func (%sType) resolve(ec *executionContext, %s interface{}, field string, arguments map[string]interface{}, sels []query.Selection) jsonw.Encodable {", lcFirst(object.Type.GraphQLName), objectName)
if object.Type.Name != "interface{}" {
w.line("it := object.(*%s)", object.Type.Local())
Expand Down Expand Up @@ -164,13 +169,13 @@ func (w *writer) writeMethodResolver(object object, field Field) {
w.line("}")
}

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

w.line("return json")
}

func (w *writer) writeVarResolver(field Field) {
w.writeJsonType("res", field.Type, field.Type.Modifiers, field.VarName)
w.writeJsonType("res", field.Type, field.VarName)
w.line("return res")
}

Expand All @@ -189,20 +194,28 @@ func (w *writer) writeFuncArgs(field Field) {
}
}

func (w *writer) writeJsonType(result string, t Type, remainingMods []string, val string) {
isPtr := false
func (w *writer) writeJsonType(result string, t Type, val string) {
w.doWriteJsonType(result, t, val, t.Modifiers, false)
}

func (w *writer) doWriteJsonType(result string, t Type, val string, remainingMods []string, isPtr bool) {
for i := 0; i < len(remainingMods); i++ {
switch remainingMods[i] {
case modPtr:
isPtr = true
w.line("var %s jsonw.Encodable = jsonw.Null", result)
w.begin("if %s != nil {", val)
w.doWriteJsonType(result+"1", t, val, remainingMods[i+1:], true)
w.line("%s = %s", result, result+"1")
w.end("}")
return
case modList:
if isPtr {
val = "*" + val
}
w.line("%s := jsonw.Array{}", result)
w.begin("for _, val := range %s {", val)

w.writeJsonType(result+"1", t, remainingMods[i+1:], "val")
w.doWriteJsonType(result+"1", t, "val", remainingMods[i+1:], false)
w.line("%s = append(%s, %s)", result, result, result+"1")
w.end("}")
return
Expand Down
70 changes: 54 additions & 16 deletions example/todo/gen/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ func NewResolver(resolvers Resolvers) relay.Resolver {
c := executionContext{
resolvers: resolvers,
variables: variables,
doc: doc,
}

var rootType resolvedType
Expand Down Expand Up @@ -59,17 +60,19 @@ type executionContext struct {
errors.Builder
resolvers Resolvers
variables map[string]interface{}
doc *query.Document
}

type resolvedType interface {
resolve(ec *executionContext, it interface{}, field string, arguments map[string]interface{}, sels []query.Selection) jsonw.Encodable
accepts(name string) bool
}

func (c *executionContext) executeSelectionSet(sel []query.Selection, resolver resolvedType, objectValue interface{}) jsonw.Encodable {
if objectValue == nil {
return jsonw.Null
}
groupedFieldSet := c.collectFields(sel, map[string]interface{}{})
groupedFieldSet := c.collectFields(sel, resolver, map[string]bool{})

resultMap := jsonw.Map{}
for _, collectedField := range groupedFieldSet {
Expand All @@ -91,15 +94,59 @@ func (c *executionContext) introspectType(name string) *introspection.Type {
return introspection.WrapType(t)
}

func (c *executionContext) collectFields(selSet []query.Selection, visited map[string]interface{}) []collectedField {
func (c *executionContext) collectFields(selSet []query.Selection, resolver resolvedType, visited map[string]bool) []collectedField {
var groupedFields []collectedField

// TODO: Basically everything.
for _, sel := range selSet {
switch sel := sel.(type) {
case *query.Field:
f := findField(&groupedFields, sel, c.variables)
f := getOrCreateField(&groupedFields, sel.Name.Name, func() collectedField {
f := collectedField{
Alias: sel.Alias.Name,
Name: sel.Name.Name,
}
if len(sel.Arguments) > 0 {
f.Args = map[string]interface{}{}
for _, arg := range sel.Arguments {
f.Args[arg.Name.Name] = arg.Value.Value(c.variables)
}
}
return f
})

f.Selections = append(f.Selections, sel.Selections...)
case *query.InlineFragment:
if !resolver.accepts(sel.On.Ident.Name) {
continue
}

for _, childField := range c.collectFields(sel.Selections, resolver, visited) {
f := getOrCreateField(&groupedFields, childField.Name, func() collectedField { return childField })
f.Selections = append(f.Selections, childField.Selections...)
}

case *query.FragmentSpread:
fragmentName := sel.Name.Name
if _, seen := visited[fragmentName]; seen {
continue
}
visited[fragmentName] = true

fragment := c.doc.Fragments.Get(fragmentName)
if fragment == nil {
c.Errorf("missing fragment %s", fragmentName)
continue
}

if !resolver.accepts(fragment.On.Name) {
continue
}

for _, childField := range c.collectFields(fragment.Selections, resolver, visited) {
f := getOrCreateField(&groupedFields, childField.Name, func() collectedField { return childField })
f.Selections = append(f.Selections, childField.Selections...)
}

default:
panic(fmt.Errorf("unsupported %T", sel))
}
Expand All @@ -115,23 +162,14 @@ type collectedField struct {
Selections []query.Selection
}

func findField(c *[]collectedField, field *query.Field, vars map[string]interface{}) *collectedField {
func getOrCreateField(c *[]collectedField, name string, creator func() collectedField) *collectedField {
for i, cf := range *c {
if cf.Alias == field.Alias.Name {
if cf.Alias == name {
return &(*c)[i]
}
}

f := collectedField{
Alias: field.Alias.Name,
Name: field.Name.Name,
}
if len(field.Arguments) > 0 {
f.Args = map[string]interface{}{}
for _, arg := range field.Arguments {
f.Args[arg.Name.Name] = arg.Value.Value(vars)
}
}
f := creator()

*c = append(*c, f)
return &(*c)[len(*c)-1]
Expand Down
Loading

0 comments on commit 2f358e7

Please sign in to comment.