diff --git a/graphql.go b/graphql.go index 0fe9f663cab..4541944468c 100644 --- a/graphql.go +++ b/graphql.go @@ -41,6 +41,12 @@ func exec(s *Schema, t schema.Type, sel *query.SelectionSet, resolver reflect.Va switch t := t.(type) { case *schema.Scalar: return resolver.Interface() + case *schema.Array: + a := make([]interface{}, resolver.Len()) + for i := range a { + a[i] = exec(s, t.Elem, sel, resolver.Index(i)) + } + return a case *schema.TypeName: return exec(s, s.Types[t.Name], sel, resolver) case *schema.Object: diff --git a/graphql_test.go b/graphql_test.go index a880e0ce883..b05c1236649 100644 --- a/graphql_test.go +++ b/graphql_test.go @@ -15,12 +15,21 @@ func (r *helloWorldResolver) Hello() string { type starWarsResolver struct{} func (r *starWarsResolver) Hero() *userResolver { - return &userResolver{id: "2001", name: "R2-D2"} + return &userResolver{ + id: "2001", + name: "R2-D2", + friends: []*userResolver{ + {name: "Luke Skywalker"}, + {name: "Han Solo"}, + {name: "Leia Organa"}, + }, + } } type userResolver struct { - id string - name string + id string + name string + friends []*userResolver } func (r *userResolver) ID() string { @@ -31,6 +40,10 @@ func (r *userResolver) Name() string { return r.name } +func (r *userResolver) Friends() []*userResolver { + return r.friends +} + var tests = []struct { name string schema string @@ -58,7 +71,7 @@ var tests = []struct { `, }, { - name: "User", + name: "StarWars", schema: ` type Query { hero: User @@ -67,6 +80,7 @@ var tests = []struct { type User { id: String name: String + friends: [User] } `, resolver: &starWarsResolver{}, @@ -75,6 +89,9 @@ var tests = []struct { hero { id name + friends { + name + } } } `, @@ -82,7 +99,18 @@ var tests = []struct { { "hero": { "id": "2001", - "name": "R2-D2" + "name": "R2-D2", + "friends": [ + { + "name": "Luke Skywalker" + }, + { + "name": "Han Solo" + }, + { + "name": "Leia Organa" + } + ] } } `, diff --git a/internal/schema/schema.go b/internal/schema/schema.go index a9ec0340559..188cfd0edc6 100644 --- a/internal/schema/schema.go +++ b/internal/schema/schema.go @@ -17,6 +17,10 @@ type Type interface{} type Scalar struct { } +type Array struct { + Elem Type +} + type TypeName struct { Name string } @@ -79,8 +83,10 @@ func parseTypeDecl(l *lexer.Lexer) (string, *Object) { } func parseType(l *lexer.Lexer) Type { - // TODO check args - // TODO check return type + if l.Peek() == '[' { + return parseArray(l) + } + name := l.ConsumeIdent() if name == "String" { return &Scalar{} @@ -89,3 +95,10 @@ func parseType(l *lexer.Lexer) Type { Name: name, } } + +func parseArray(l *lexer.Lexer) *Array { + l.ConsumeToken('[') + elem := parseType(l) + l.ConsumeToken(']') + return &Array{Elem: elem} +}