Skip to content

Commit

Permalink
Add support for interfaces, part 2: list-of-interface
Browse files Browse the repository at this point in the history
In this commit I remove one of the limitations of our support for
interfaces, from #52, by adding support for list-of-interface fields.
This was surprisingly complex!  The issue is that, as before, it's the
containing type that has to do all the glue work -- and it's that glue
work that is complicated by list-of-interface fields.

All in all, it's not that much new code, and by far the hard part is
just 20 lines in the UnmarshalJSON template (which come with almost
twice as many lines of comments to explain them).  It may be easiest to
start by reading some of the generated code, and then read the template.

I also added support for such fields with `pointer: true` specified,
such that the type is `[][]...[]*MyInterface`, although I don't know why
you would want that.  This does *not* allow e.g. `*[]*[][]*MyInterface`;
that would require a way to specify it (see #16) but also add some extra
complexity (as we'd have to actually walk the type-unwrap chain
properly, instead of just counting the number of slices and whether
there's a pointer).

Issue: #8

Test plan:
make check

Reviewers: marksandstrom, miguel, csilvers, adam
  • Loading branch information
benjaminjkraft committed Aug 23, 2021
1 parent 7496cbf commit cc1942e
Show file tree
Hide file tree
Showing 21 changed files with 1,142 additions and 72 deletions.
1 change: 0 additions & 1 deletion generate/generate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ func TestGenerate(t *testing.T) {
if testing.Short() {
t.Skip("skipping build due to -short")
} else if sourceFilename == "InterfaceNesting.graphql" || // #8
sourceFilename == "InterfaceListField.graphql" || // #8
sourceFilename == "Omitempty.graphql" { // #43
t.Skip("TODO: enable these once they build")
}
Expand Down
24 changes: 23 additions & 1 deletion generate/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"io"
"path/filepath"
"runtime"
"strings"
"text/template"
)

Expand All @@ -12,13 +13,34 @@ var (
thisDir = filepath.Dir(thisFilename)
)

func repeat(n int, s string) string {
var builder strings.Builder
for i := 0; i < n; i++ {
builder.WriteString(s)
}
return builder.String()
}

func intRange(n int) []int {
ret := make([]int, n)
for i := 0; i < n; i++ {
ret[i] = i
}
return ret
}

func sub(x, y int) int { return x - y }

// execute executes the given template with the funcs from this generator.
func (g *generator) execute(tmplRelFilename string, w io.Writer, data interface{}) error {
tmpl := g.templateCache[tmplRelFilename]
if tmpl == nil {
absFilename := filepath.Join(thisDir, tmplRelFilename)
funcMap := template.FuncMap{
"ref": g.ref,
"ref": g.ref,
"repeat": repeat,
"intRange": intRange,
"sub": sub,
}
var err error
tmpl, err = template.New(tmplRelFilename).Funcs(funcMap).ParseFiles(absFilename)
Expand Down
12 changes: 11 additions & 1 deletion generate/testdata/queries/InterfaceListField.graphql
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
query InterfaceNoFragmentsQuery {
query InterfaceListField {
root {
id
name
Expand All @@ -8,4 +8,14 @@ query InterfaceNoFragmentsQuery {
name
}
}
# @genqlient(pointer: true)
withPointer: root {
id
name
children {
__typename
id
name
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
query InterfaceListOfListOfListsField {
listOfListsOfListsOfContent { __typename id name }
# @genqlient(pointer: true)
withPointer: listOfListsOfListsOfContent { __typename id name }
}
2 changes: 2 additions & 0 deletions generate/testdata/queries/InterfaceNoFragments.graphql
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
query InterfaceNoFragmentsQuery {
root { id name } # (make sure sibling fields work)
randomItem { __typename id name }
# @genqlient(pointer: true)
withPointer: randomItem { __typename id name }
}
1 change: 1 addition & 0 deletions generate/testdata/queries/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ type Query {
getJunk: Junk
getComplexJunk: ComplexJunk
listOfListsOfLists: [[[String!]!]!]!
listOfListsOfListsOfContent: [[[Content!]!]!]!
}

type Mutation {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"operations": [
{
"operationName": "InterfaceNoFragmentsQuery",
"query": "\nquery InterfaceNoFragmentsQuery {\n\troot {\n\t\tid\n\t\tname\n\t\tchildren {\n\t\t\t__typename\n\t\t\tid\n\t\t\tname\n\t\t}\n\t}\n}\n",
"operationName": "InterfaceListField",
"query": "\nquery InterfaceListField {\n\troot {\n\t\tid\n\t\tname\n\t\tchildren {\n\t\t\t__typename\n\t\t\tid\n\t\t\tname\n\t\t}\n\t}\n\twithPointer: root {\n\t\tid\n\t\tname\n\t\tchildren {\n\t\t\t__typename\n\t\t\tid\n\t\t\tname\n\t\t}\n\t}\n}\n",
"sourceLocation": "testdata/queries/InterfaceListField.graphql"
}
]
Expand Down
Loading

0 comments on commit cc1942e

Please sign in to comment.