-
Notifications
You must be signed in to change notification settings - Fork 115
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for concrete-typed named fragments
In previous commits I added support to genqlient for interfaces, inline fragments, and, most recently, named fragments of concrete (object) type. This leaves only named fragments of interface type! Like other named fragments, these are useful for code-sharing, especially if you want some code that can handle the same fields of several different types. As seems to be inevitable with genqlient, this was mostly pretty straightforward, although there turned out to be surprisingly many places we needed to add some handling; almost anywhere that touches interfaces *or* named fragments needed some updates. But it's all hopefully fairly clear code. As a part of this change I made three semi-related improvements: 1. I refactored the handling of descriptions (i.e. GoDoc), because it was getting more and more confusing and duplicative. I'm still not sure how much of it it makes sense to inline vs. separate, but I think this is better than it was. This resulted in some minor changes to descriptions, generally in the direction of making things more consistent. 2. I bumped the minimum Go version to 1.14 so we can guarantee support for duplicate interface methods. These are useful for abstract-in-absstract spreads; we generate an interface for the fragment, and (if the fragment-type implements the scope-type) we embed it into the interface we generate for its spread-context, and if the two have a duplicated field we thus duplicate the method. It wouldn't be impossible to support this on 1.13 (maybe just by omitting said embed) but it didn't seem worth it. This also removes a few special-cases in tests. 3. I added a bunch of code to better format syntax errors in the generated code (which we see from `gofmt`). This is mostly just an internal improvement; I wrote it because I got annoyed while hunting down a few such errors.. Fixes, at last, #8. Issue: #8 Test plan: make check Reviewers: marksandstrom, miguel, adam
- Loading branch information
1 parent
f99c10d
commit 7923723
Showing
22 changed files
with
704 additions
and
228 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package generate | ||
|
||
// Code relating to generating GoDoc from GraphQL descriptions. | ||
// | ||
// For fields, and types where we just copy the "whole" type (enum and | ||
// input-object), this is easy: we just use the GraphQL description. But for | ||
// struct types, there are often more useful things we can say. | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
) | ||
|
||
// descriptionInfo is embedded in types whose descriptions may be more complex | ||
// than just a copy of the GraphQL doc. | ||
type descriptionInfo struct { | ||
// user-specified comment for this type | ||
Comment string | ||
// name of the corresponding GraphQL type | ||
GraphQLName string | ||
// GraphQL description of the type .GraphQLName, if any | ||
Description string | ||
// name of the corresponding GraphQL fragment (on .GraphQLName), if any | ||
FragmentName string | ||
} | ||
|
||
func maybeAddTypeDescription(info descriptionInfo, description string) string { | ||
if info.Description == "" { | ||
return description | ||
} | ||
return fmt.Sprintf( | ||
"%v\nThe GraphQL type's documentation follows.\n\n%v", | ||
description, info.Description) | ||
} | ||
|
||
func fragmentDescription(info descriptionInfo) string { | ||
return maybeAddTypeDescription(info, fmt.Sprintf( | ||
"%v includes the GraphQL fields of %v requested by the fragment %v.", | ||
info.FragmentName, info.GraphQLName, info.FragmentName)) | ||
} | ||
|
||
func structDescription(typ *goStructType) string { | ||
switch { | ||
case typ.Comment != "": | ||
return typ.Comment | ||
case typ.IsInput: | ||
// Input types have all their fields, just use the GraphQL description. | ||
return typ.Description | ||
case typ.FragmentName != "": | ||
return fragmentDescription(typ.descriptionInfo) | ||
default: | ||
// For types where we only have some fields, note that, along with | ||
// the GraphQL documentation (if any). We don't want to just use | ||
// the GraphQL documentation, since it may refer to fields we | ||
// haven't selected, say. | ||
return maybeAddTypeDescription(typ.descriptionInfo, fmt.Sprintf( | ||
"%v includes the requested fields of the GraphQL type %v.", | ||
typ.GoName, typ.GraphQLName)) | ||
} | ||
} | ||
|
||
func interfaceDescription(typ *goInterfaceType) string { | ||
goImplNames := make([]string, len(typ.Implementations)) | ||
for i, impl := range typ.Implementations { | ||
goImplNames[i] = impl.Reference() | ||
} | ||
implementationList := fmt.Sprintf( | ||
"\n\n%v is implemented by the following types:\n\t%v", | ||
typ.GoName, strings.Join(goImplNames, "\n\t")) | ||
|
||
switch { | ||
case typ.Comment != "": | ||
return typ.Comment + implementationList | ||
case typ.FragmentName != "": | ||
return fragmentDescription(typ.descriptionInfo) + implementationList | ||
default: | ||
return maybeAddTypeDescription(typ.descriptionInfo, fmt.Sprintf( | ||
"%v includes the requested fields of the GraphQL interface %v.%v", | ||
typ.GoName, typ.GraphQLName, implementationList)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.