diff --git a/generate/convert.go b/generate/convert.go index 3b1f750a..d3a9f8d3 100644 --- a/generate/convert.go +++ b/generate/convert.go @@ -701,6 +701,17 @@ func fragmentMatches(containingTypedef, fragmentTypedef *ast.Definition) bool { return true } } + + // Handle the special case where the fragment is on a union, then the + // fragment can match any of the types in the union. + if fragmentTypedef.Kind == ast.Union { + for _, typeName := range fragmentTypedef.Types { + if typeName == containingTypedef.Name { + return true + } + } + } + return false } diff --git a/generate/testdata/snapshots/TestGenerate-ComplexNamedFragments.graphql-ComplexNamedFragments.graphql.go b/generate/testdata/snapshots/TestGenerate-ComplexNamedFragments.graphql-ComplexNamedFragments.graphql.go index 3a9096a5..7888b2e8 100644 --- a/generate/testdata/snapshots/TestGenerate-ComplexNamedFragments.graphql-ComplexNamedFragments.graphql.go +++ b/generate/testdata/snapshots/TestGenerate-ComplexNamedFragments.graphql-ComplexNamedFragments.graphql.go @@ -875,13 +875,10 @@ type InnerQueryFragmentRandomItemContent interface { func (v *InnerQueryFragmentRandomItemArticle) implementsGraphQLInterfaceInnerQueryFragmentRandomItemContent() { } -func (v *InnerQueryFragmentRandomItemArticle) implementsGraphQLInterfaceContentFields() {} func (v *InnerQueryFragmentRandomItemTopic) implementsGraphQLInterfaceInnerQueryFragmentRandomItemContent() { } -func (v *InnerQueryFragmentRandomItemTopic) implementsGraphQLInterfaceContentFields() {} func (v *InnerQueryFragmentRandomItemVideo) implementsGraphQLInterfaceInnerQueryFragmentRandomItemContent() { } -func (v *InnerQueryFragmentRandomItemVideo) implementsGraphQLInterfaceContentFields() {} func __unmarshalInnerQueryFragmentRandomItemContent(b []byte, v *InnerQueryFragmentRandomItemContent) error { if string(b) == "null" { @@ -1967,12 +1964,65 @@ func (v *TopicNewestContent) __premarshalJSON() (*__premarshalTopicNewestContent // TopicNewestContentNewestContentArticle includes the requested fields of the GraphQL type Article. type TopicNewestContentNewestContentArticle struct { - Typename string `json:"__typename"` + Typename string `json:"__typename"` + SimpleLeafContentArticle `json:"-"` } // GetTypename returns TopicNewestContentNewestContentArticle.Typename, and is useful for accessing the field via an interface. func (v *TopicNewestContentNewestContentArticle) GetTypename() string { return v.Typename } +// GetId returns TopicNewestContentNewestContentArticle.Id, and is useful for accessing the field via an interface. +func (v *TopicNewestContentNewestContentArticle) GetId() testutil.ID { + return v.SimpleLeafContentArticle.Id +} + +func (v *TopicNewestContentNewestContentArticle) UnmarshalJSON(b []byte) error { + + if string(b) == "null" { + return nil + } + + var firstPass struct { + *TopicNewestContentNewestContentArticle + graphql.NoUnmarshalJSON + } + firstPass.TopicNewestContentNewestContentArticle = v + + err := json.Unmarshal(b, &firstPass) + if err != nil { + return err + } + + err = json.Unmarshal( + b, &v.SimpleLeafContentArticle) + if err != nil { + return err + } + return nil +} + +type __premarshalTopicNewestContentNewestContentArticle struct { + Typename string `json:"__typename"` + + Id testutil.ID `json:"id"` +} + +func (v *TopicNewestContentNewestContentArticle) MarshalJSON() ([]byte, error) { + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + return json.Marshal(premarshaled) +} + +func (v *TopicNewestContentNewestContentArticle) __premarshalJSON() (*__premarshalTopicNewestContentNewestContentArticle, error) { + var retval __premarshalTopicNewestContentNewestContentArticle + + retval.Typename = v.Typename + retval.Id = v.SimpleLeafContentArticle.Id + return &retval, nil +} + // TopicNewestContentNewestContentLeafContent includes the requested fields of the GraphQL interface LeafContent. // // TopicNewestContentNewestContentLeafContent is implemented by the following types: @@ -1990,10 +2040,8 @@ type TopicNewestContentNewestContentLeafContent interface { func (v *TopicNewestContentNewestContentArticle) implementsGraphQLInterfaceTopicNewestContentNewestContentLeafContent() { } -func (v *TopicNewestContentNewestContentArticle) implementsGraphQLInterfaceSimpleLeafContent() {} func (v *TopicNewestContentNewestContentVideo) implementsGraphQLInterfaceTopicNewestContentNewestContentLeafContent() { } -func (v *TopicNewestContentNewestContentVideo) implementsGraphQLInterfaceSimpleLeafContent() {} func __unmarshalTopicNewestContentNewestContentLeafContent(b []byte, v *TopicNewestContentNewestContentLeafContent) error { if string(b) == "null" { @@ -2031,18 +2079,26 @@ func __marshalTopicNewestContentNewestContentLeafContent(v *TopicNewestContentNe case *TopicNewestContentNewestContentArticle: typename = "Article" + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } result := struct { TypeName string `json:"__typename"` - *TopicNewestContentNewestContentArticle - }{typename, v} + *__premarshalTopicNewestContentNewestContentArticle + }{typename, premarshaled} return json.Marshal(result) case *TopicNewestContentNewestContentVideo: typename = "Video" + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } result := struct { TypeName string `json:"__typename"` - *TopicNewestContentNewestContentVideo - }{typename, v} + *__premarshalTopicNewestContentNewestContentVideo + }{typename, premarshaled} return json.Marshal(result) case nil: return []byte("null"), nil @@ -2054,12 +2110,65 @@ func __marshalTopicNewestContentNewestContentLeafContent(v *TopicNewestContentNe // TopicNewestContentNewestContentVideo includes the requested fields of the GraphQL type Video. type TopicNewestContentNewestContentVideo struct { - Typename string `json:"__typename"` + Typename string `json:"__typename"` + SimpleLeafContentVideo `json:"-"` } // GetTypename returns TopicNewestContentNewestContentVideo.Typename, and is useful for accessing the field via an interface. func (v *TopicNewestContentNewestContentVideo) GetTypename() string { return v.Typename } +// GetId returns TopicNewestContentNewestContentVideo.Id, and is useful for accessing the field via an interface. +func (v *TopicNewestContentNewestContentVideo) GetId() testutil.ID { + return v.SimpleLeafContentVideo.Id +} + +func (v *TopicNewestContentNewestContentVideo) UnmarshalJSON(b []byte) error { + + if string(b) == "null" { + return nil + } + + var firstPass struct { + *TopicNewestContentNewestContentVideo + graphql.NoUnmarshalJSON + } + firstPass.TopicNewestContentNewestContentVideo = v + + err := json.Unmarshal(b, &firstPass) + if err != nil { + return err + } + + err = json.Unmarshal( + b, &v.SimpleLeafContentVideo) + if err != nil { + return err + } + return nil +} + +type __premarshalTopicNewestContentNewestContentVideo struct { + Typename string `json:"__typename"` + + Id testutil.ID `json:"id"` +} + +func (v *TopicNewestContentNewestContentVideo) MarshalJSON() ([]byte, error) { + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + return json.Marshal(premarshaled) +} + +func (v *TopicNewestContentNewestContentVideo) __premarshalJSON() (*__premarshalTopicNewestContentNewestContentVideo, error) { + var retval __premarshalTopicNewestContentNewestContentVideo + + retval.Typename = v.Typename + retval.Id = v.SimpleLeafContentVideo.Id + return &retval, nil +} + // UserLastContent includes the GraphQL fields of User requested by the fragment UserLastContent. // The GraphQL type's documentation follows. // @@ -2138,12 +2247,63 @@ func (v *UserLastContent) __premarshalJSON() (*__premarshalUserLastContent, erro // UserLastContentLastContentArticle includes the requested fields of the GraphQL type Article. type UserLastContentLastContentArticle struct { - Typename string `json:"__typename"` + Typename string `json:"__typename"` + SimpleLeafContentArticle `json:"-"` } // GetTypename returns UserLastContentLastContentArticle.Typename, and is useful for accessing the field via an interface. func (v *UserLastContentLastContentArticle) GetTypename() string { return v.Typename } +// GetId returns UserLastContentLastContentArticle.Id, and is useful for accessing the field via an interface. +func (v *UserLastContentLastContentArticle) GetId() testutil.ID { return v.SimpleLeafContentArticle.Id } + +func (v *UserLastContentLastContentArticle) UnmarshalJSON(b []byte) error { + + if string(b) == "null" { + return nil + } + + var firstPass struct { + *UserLastContentLastContentArticle + graphql.NoUnmarshalJSON + } + firstPass.UserLastContentLastContentArticle = v + + err := json.Unmarshal(b, &firstPass) + if err != nil { + return err + } + + err = json.Unmarshal( + b, &v.SimpleLeafContentArticle) + if err != nil { + return err + } + return nil +} + +type __premarshalUserLastContentLastContentArticle struct { + Typename string `json:"__typename"` + + Id testutil.ID `json:"id"` +} + +func (v *UserLastContentLastContentArticle) MarshalJSON() ([]byte, error) { + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + return json.Marshal(premarshaled) +} + +func (v *UserLastContentLastContentArticle) __premarshalJSON() (*__premarshalUserLastContentLastContentArticle, error) { + var retval __premarshalUserLastContentLastContentArticle + + retval.Typename = v.Typename + retval.Id = v.SimpleLeafContentArticle.Id + return &retval, nil +} + // UserLastContentLastContentLeafContent includes the requested fields of the GraphQL interface LeafContent. // // UserLastContentLastContentLeafContent is implemented by the following types: @@ -2161,10 +2321,8 @@ type UserLastContentLastContentLeafContent interface { func (v *UserLastContentLastContentArticle) implementsGraphQLInterfaceUserLastContentLastContentLeafContent() { } -func (v *UserLastContentLastContentArticle) implementsGraphQLInterfaceSimpleLeafContent() {} func (v *UserLastContentLastContentVideo) implementsGraphQLInterfaceUserLastContentLastContentLeafContent() { } -func (v *UserLastContentLastContentVideo) implementsGraphQLInterfaceSimpleLeafContent() {} func __unmarshalUserLastContentLastContentLeafContent(b []byte, v *UserLastContentLastContentLeafContent) error { if string(b) == "null" { @@ -2202,18 +2360,26 @@ func __marshalUserLastContentLastContentLeafContent(v *UserLastContentLastConten case *UserLastContentLastContentArticle: typename = "Article" + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } result := struct { TypeName string `json:"__typename"` - *UserLastContentLastContentArticle - }{typename, v} + *__premarshalUserLastContentLastContentArticle + }{typename, premarshaled} return json.Marshal(result) case *UserLastContentLastContentVideo: typename = "Video" + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } result := struct { TypeName string `json:"__typename"` - *UserLastContentLastContentVideo - }{typename, v} + *__premarshalUserLastContentLastContentVideo + }{typename, premarshaled} return json.Marshal(result) case nil: return []byte("null"), nil @@ -2225,12 +2391,63 @@ func __marshalUserLastContentLastContentLeafContent(v *UserLastContentLastConten // UserLastContentLastContentVideo includes the requested fields of the GraphQL type Video. type UserLastContentLastContentVideo struct { - Typename string `json:"__typename"` + Typename string `json:"__typename"` + SimpleLeafContentVideo `json:"-"` } // GetTypename returns UserLastContentLastContentVideo.Typename, and is useful for accessing the field via an interface. func (v *UserLastContentLastContentVideo) GetTypename() string { return v.Typename } +// GetId returns UserLastContentLastContentVideo.Id, and is useful for accessing the field via an interface. +func (v *UserLastContentLastContentVideo) GetId() testutil.ID { return v.SimpleLeafContentVideo.Id } + +func (v *UserLastContentLastContentVideo) UnmarshalJSON(b []byte) error { + + if string(b) == "null" { + return nil + } + + var firstPass struct { + *UserLastContentLastContentVideo + graphql.NoUnmarshalJSON + } + firstPass.UserLastContentLastContentVideo = v + + err := json.Unmarshal(b, &firstPass) + if err != nil { + return err + } + + err = json.Unmarshal( + b, &v.SimpleLeafContentVideo) + if err != nil { + return err + } + return nil +} + +type __premarshalUserLastContentLastContentVideo struct { + Typename string `json:"__typename"` + + Id testutil.ID `json:"id"` +} + +func (v *UserLastContentLastContentVideo) MarshalJSON() ([]byte, error) { + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + return json.Marshal(premarshaled) +} + +func (v *UserLastContentLastContentVideo) __premarshalJSON() (*__premarshalUserLastContentLastContentVideo, error) { + var retval __premarshalUserLastContentLastContentVideo + + retval.Typename = v.Typename + retval.Id = v.SimpleLeafContentVideo.Id + return &retval, nil +} + // VideoFields includes the GraphQL fields of Video requested by the fragment VideoFields. type VideoFields struct { // ID is documented in the Content interface. diff --git a/generate/testdata/snapshots/TestGenerate-CovariantInterfaceImplementation.graphql-CovariantInterfaceImplementation.graphql.go b/generate/testdata/snapshots/TestGenerate-CovariantInterfaceImplementation.graphql-CovariantInterfaceImplementation.graphql.go index 47213148..74aa5774 100644 --- a/generate/testdata/snapshots/TestGenerate-CovariantInterfaceImplementation.graphql-CovariantInterfaceImplementation.graphql.go +++ b/generate/testdata/snapshots/TestGenerate-CovariantInterfaceImplementation.graphql-CovariantInterfaceImplementation.graphql.go @@ -1089,16 +1089,10 @@ type CovariantInterfaceImplementationRandomItemContentNextContent interface { func (v *CovariantInterfaceImplementationRandomItemContentNextArticle) implementsGraphQLInterfaceCovariantInterfaceImplementationRandomItemContentNextContent() { } -func (v *CovariantInterfaceImplementationRandomItemContentNextArticle) implementsGraphQLInterfaceContentFields() { -} func (v *CovariantInterfaceImplementationRandomItemContentNextTopic) implementsGraphQLInterfaceCovariantInterfaceImplementationRandomItemContentNextContent() { } -func (v *CovariantInterfaceImplementationRandomItemContentNextTopic) implementsGraphQLInterfaceContentFields() { -} func (v *CovariantInterfaceImplementationRandomItemContentNextVideo) implementsGraphQLInterfaceCovariantInterfaceImplementationRandomItemContentNextContent() { } -func (v *CovariantInterfaceImplementationRandomItemContentNextVideo) implementsGraphQLInterfaceContentFields() { -} func __unmarshalCovariantInterfaceImplementationRandomItemContentNextContent(b []byte, v *CovariantInterfaceImplementationRandomItemContentNextContent) error { if string(b) == "null" { @@ -1495,16 +1489,10 @@ type CovariantInterfaceImplementationRandomItemContentRelatedContent interface { func (v *CovariantInterfaceImplementationRandomItemContentRelatedArticle) implementsGraphQLInterfaceCovariantInterfaceImplementationRandomItemContentRelatedContent() { } -func (v *CovariantInterfaceImplementationRandomItemContentRelatedArticle) implementsGraphQLInterfaceContentFields() { -} func (v *CovariantInterfaceImplementationRandomItemContentRelatedTopic) implementsGraphQLInterfaceCovariantInterfaceImplementationRandomItemContentRelatedContent() { } -func (v *CovariantInterfaceImplementationRandomItemContentRelatedTopic) implementsGraphQLInterfaceContentFields() { -} func (v *CovariantInterfaceImplementationRandomItemContentRelatedVideo) implementsGraphQLInterfaceCovariantInterfaceImplementationRandomItemContentRelatedContent() { } -func (v *CovariantInterfaceImplementationRandomItemContentRelatedVideo) implementsGraphQLInterfaceContentFields() { -} func __unmarshalCovariantInterfaceImplementationRandomItemContentRelatedContent(b []byte, v *CovariantInterfaceImplementationRandomItemContentRelatedContent) error { if string(b) == "null" { diff --git a/generate/types.go b/generate/types.go index 7641d9b1..01f619f5 100644 --- a/generate/types.go +++ b/generate/types.go @@ -522,17 +522,6 @@ func (typ *goInterfaceType) WriteDefinition(w io.Writer, g *generator) error { for _, impl := range typ.Implementations { fmt.Fprintf(w, "func (v *%s) %s() {}\n", impl.Reference(), implementsMethodName) - - // implement nested interface union type - for _, sharedField := range typ.SharedFields { - if sharedField.IsAbstract() { - // embedded type - if sharedField.GoName == "" { - fmt.Fprintf(w, "func (v *%s) %s() {}\n", - impl.Reference(), fmt.Sprintf("implementsGraphQLInterface%s", sharedField.GoType.Reference())) - } - } - } } // Finally, write the marshal- and unmarshal-helpers, which