-
Notifications
You must be signed in to change notification settings - Fork 114
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for interfaces, part 2: list-of-interface #54
Conversation
a83f63c
to
6d13135
Compare
256aacc
to
2f03b6e
Compare
6d13135
to
1e265e6
Compare
2f03b6e
to
51efbc0
Compare
1e265e6
to
7496cbf
Compare
b5469dc
to
cc1942e
Compare
624c176
to
f8d359c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me. I mostly reviewed the generated code and not the template. As mentioned inline, only supporting a pointer for the inner-most type seems right. Also, it would be nice to have an integration test that exercises pointer handling.
@@ -111,6 +111,7 @@ type Query { | |||
getJunk: Junk | |||
getComplexJunk: ComplexJunk | |||
listOfListsOfLists: [[[String!]!]!]! | |||
listOfListsOfListsOfContent: [[[Content!]!]!]! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
listOfListsOfListsOfContent: [[[Content]!]!]!
is a type where one might want to use a pointer (though types like this usually seem to usually be accidental). Pointers to slices shouldn't be necessary, so it seems correct to only support pointers on the most-inner type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there are valid uses for required-list-of-optional-item, if you want the input in correspondence to the output. But I agree I can only see a reason to support it at the innermost point. Anyways, this is all mentioned at #16; my attitude is basically "if someone finds a legitimate reason to want it, we can implement it" :-) .
} | ||
|
||
// InterfaceListOfListOfListsFieldListOfListsOfListsOfContentArticle includes the requested fields of the GraphQL type Article. | ||
type InterfaceListOfListOfListsFieldListOfListsOfListsOfContentArticle struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whew. Hopefully no one would actually need to use a type named like this anywhere.
generate/types.go
Outdated
Unwrap() goType | ||
|
||
// Count the number of times Unwrap() will unwrap a slice type. For | ||
// example, given []*[]**[]MyStruct, return 3. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: this type isn't supported in the current design; it seems like it would be nice to use a valid example (even though the method could in principle support this type as well).
This gets a little complicated because we may have a slice field. | ||
So what we do is basically, for each field: | ||
|
||
target := &v.MyField // *[][]...[]MyType |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same nit here about this not being a supported type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is correct as-is -- target
has type *[][]...[]MyType
(or *[][]...[]*MyType
, because it's a pointer to the field-type, again because that simplifies the templating at the cost of making the generated code look a bit strange.
@@ -99,6 +99,36 @@ func TestInterfaceNoFragments(t *testing.T) { | |||
assert.Nil(t, resp.Being) | |||
} | |||
|
|||
func TestInterfaceListField(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you also add an integration test that uses @genqlient(pointer: true)
? I think such a test is the only place the generated code would be exercises (and where we'd suss out any issues). Is that right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My theory was that any issues there would show up at build-time. But it's probably better not to be lazy :-) .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LOL, you were right, the code is actually incorrect (crashes with a nil pointer dereference)! Thanks for the prod :-) .
e98a8ce
to
3073246
Compare
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
I was like "I don't need no stinkin' integration test, the compiler would catch any problems", but Mark asked for one anyway, and it turns out it caught a bug! Also some other minor fixes to documentation, from review comments.
f5e4166
to
9ffbc9f
Compare
Summary:
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 whyyou 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