Add support for interfaces, part 2: list-of-interface (#54)
## 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 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: https://github.com/Khan/genqlient/issues/8 ## Test plan: make check Author: benjaminjkraft Reviewers: dnerdy, benjaminjkraft, aberkan, csilvers, MiguelCastillo Required Reviewers: Approved by: dnerdy Checks: ⌛ Test (1.17), ⌛ Test (1.16), ⌛ Test (1.15), ⌛ Test (1.14), ⌛ Test (1.13), ⌛ Lint, ⌛ Lint, ⌛ Test (1.17), ⌛ Test (1.16), ⌛ Test (1.15), ⌛ Test (1.14), ⌛ Test (1.13) Pull request URL: https://github.com/Khan/genqlient/pull/54
This commit is contained in:
Vendored
+136
-4
@@ -19,7 +19,40 @@ type InterfaceNestingResponse struct {
|
||||
type InterfaceNestingRootTopic struct {
|
||||
// ID is documented in the Content interface.
|
||||
Id testutil.ID `json:"id"`
|
||||
Children []InterfaceNestingRootTopicChildrenContent `json:"children"`
|
||||
Children []InterfaceNestingRootTopicChildrenContent `json:"-"`
|
||||
}
|
||||
|
||||
func (v *InterfaceNestingRootTopic) UnmarshalJSON(b []byte) error {
|
||||
|
||||
type InterfaceNestingRootTopicWrapper InterfaceNestingRootTopic
|
||||
|
||||
var firstPass struct {
|
||||
*InterfaceNestingRootTopicWrapper
|
||||
Children []json.RawMessage `json:"children"`
|
||||
}
|
||||
firstPass.InterfaceNestingRootTopicWrapper = (*InterfaceNestingRootTopicWrapper)(v)
|
||||
|
||||
err := json.Unmarshal(b, &firstPass)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{
|
||||
target := &v.Children
|
||||
raw := firstPass.Children
|
||||
*target = make(
|
||||
[]InterfaceNestingRootTopicChildrenContent,
|
||||
len(raw))
|
||||
for i, raw := range raw {
|
||||
target := &(*target)[i]
|
||||
err = __unmarshalInterfaceNestingRootTopicChildrenContent(
|
||||
target, raw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// InterfaceNestingRootTopicChildrenArticle includes the requested fields of the GraphQL type Article.
|
||||
@@ -35,7 +68,40 @@ type InterfaceNestingRootTopicChildrenArticleParentTopic struct {
|
||||
Typename string `json:"__typename"`
|
||||
// ID is documented in the Content interface.
|
||||
Id testutil.ID `json:"id"`
|
||||
Children []InterfaceNestingRootTopicChildrenArticleParentTopicChildrenContent `json:"children"`
|
||||
Children []InterfaceNestingRootTopicChildrenArticleParentTopicChildrenContent `json:"-"`
|
||||
}
|
||||
|
||||
func (v *InterfaceNestingRootTopicChildrenArticleParentTopic) UnmarshalJSON(b []byte) error {
|
||||
|
||||
type InterfaceNestingRootTopicChildrenArticleParentTopicWrapper InterfaceNestingRootTopicChildrenArticleParentTopic
|
||||
|
||||
var firstPass struct {
|
||||
*InterfaceNestingRootTopicChildrenArticleParentTopicWrapper
|
||||
Children []json.RawMessage `json:"children"`
|
||||
}
|
||||
firstPass.InterfaceNestingRootTopicChildrenArticleParentTopicWrapper = (*InterfaceNestingRootTopicChildrenArticleParentTopicWrapper)(v)
|
||||
|
||||
err := json.Unmarshal(b, &firstPass)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{
|
||||
target := &v.Children
|
||||
raw := firstPass.Children
|
||||
*target = make(
|
||||
[]InterfaceNestingRootTopicChildrenArticleParentTopicChildrenContent,
|
||||
len(raw))
|
||||
for i, raw := range raw {
|
||||
target := &(*target)[i]
|
||||
err = __unmarshalInterfaceNestingRootTopicChildrenArticleParentTopicChildrenContent(
|
||||
target, raw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// InterfaceNestingRootTopicChildrenArticleParentTopicChildrenArticle includes the requested fields of the GraphQL type Article.
|
||||
@@ -160,7 +226,40 @@ type InterfaceNestingRootTopicChildrenTopicParentTopic struct {
|
||||
Typename string `json:"__typename"`
|
||||
// ID is documented in the Content interface.
|
||||
Id testutil.ID `json:"id"`
|
||||
Children []InterfaceNestingRootTopicChildrenTopicParentTopicChildrenContent `json:"children"`
|
||||
Children []InterfaceNestingRootTopicChildrenTopicParentTopicChildrenContent `json:"-"`
|
||||
}
|
||||
|
||||
func (v *InterfaceNestingRootTopicChildrenTopicParentTopic) UnmarshalJSON(b []byte) error {
|
||||
|
||||
type InterfaceNestingRootTopicChildrenTopicParentTopicWrapper InterfaceNestingRootTopicChildrenTopicParentTopic
|
||||
|
||||
var firstPass struct {
|
||||
*InterfaceNestingRootTopicChildrenTopicParentTopicWrapper
|
||||
Children []json.RawMessage `json:"children"`
|
||||
}
|
||||
firstPass.InterfaceNestingRootTopicChildrenTopicParentTopicWrapper = (*InterfaceNestingRootTopicChildrenTopicParentTopicWrapper)(v)
|
||||
|
||||
err := json.Unmarshal(b, &firstPass)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{
|
||||
target := &v.Children
|
||||
raw := firstPass.Children
|
||||
*target = make(
|
||||
[]InterfaceNestingRootTopicChildrenTopicParentTopicChildrenContent,
|
||||
len(raw))
|
||||
for i, raw := range raw {
|
||||
target := &(*target)[i]
|
||||
err = __unmarshalInterfaceNestingRootTopicChildrenTopicParentTopicChildrenContent(
|
||||
target, raw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// InterfaceNestingRootTopicChildrenTopicParentTopicChildrenArticle includes the requested fields of the GraphQL type Article.
|
||||
@@ -241,7 +340,40 @@ type InterfaceNestingRootTopicChildrenVideoParentTopic struct {
|
||||
Typename string `json:"__typename"`
|
||||
// ID is documented in the Content interface.
|
||||
Id testutil.ID `json:"id"`
|
||||
Children []InterfaceNestingRootTopicChildrenVideoParentTopicChildrenContent `json:"children"`
|
||||
Children []InterfaceNestingRootTopicChildrenVideoParentTopicChildrenContent `json:"-"`
|
||||
}
|
||||
|
||||
func (v *InterfaceNestingRootTopicChildrenVideoParentTopic) UnmarshalJSON(b []byte) error {
|
||||
|
||||
type InterfaceNestingRootTopicChildrenVideoParentTopicWrapper InterfaceNestingRootTopicChildrenVideoParentTopic
|
||||
|
||||
var firstPass struct {
|
||||
*InterfaceNestingRootTopicChildrenVideoParentTopicWrapper
|
||||
Children []json.RawMessage `json:"children"`
|
||||
}
|
||||
firstPass.InterfaceNestingRootTopicChildrenVideoParentTopicWrapper = (*InterfaceNestingRootTopicChildrenVideoParentTopicWrapper)(v)
|
||||
|
||||
err := json.Unmarshal(b, &firstPass)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{
|
||||
target := &v.Children
|
||||
raw := firstPass.Children
|
||||
*target = make(
|
||||
[]InterfaceNestingRootTopicChildrenVideoParentTopicChildrenContent,
|
||||
len(raw))
|
||||
for i, raw := range raw {
|
||||
target := &(*target)[i]
|
||||
err = __unmarshalInterfaceNestingRootTopicChildrenVideoParentTopicChildrenContent(
|
||||
target, raw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// InterfaceNestingRootTopicChildrenVideoParentTopicChildrenArticle includes the requested fields of the GraphQL type Article.
|
||||
|
||||
Reference in New Issue
Block a user