Add support for specifying type-names, and conflict-detection (#94)
## Summary: In this commit I add two related features to genqlient: conflict-detection to avoid generating two distinct types with the same name, and an option to specify the type-name genqlient should use for some type. The conflict-detection was pretty simple once I realized I had already written all the code to do it in #70. There was a bunch of wiring, since we now need to keep track of the GraphQL type/selection-set that each type corresponds to, but it was pretty straightforward. This allows us to: - detect and reject if you have really sneaky type-names (there are some examples documented in `names.go`) - more clearly crash if genqlient accidentally generates two conflicting types, and - avoid stack-overflow when handing recursive (input) types (although sadly the poor support for options on input types (#14) makes them difficult to use in many cases; you really need to be able to set `pointer: true`) And with that all set up, the type-naming was also easy! (It doesn't have to get into the core of the type-generator, just plug in where we choose names. The desire for conflict detection was the main reason I hadn't set it up already.) Note that the existing limitation of #70 that the fields have to be in exactly the same order remains (and is now documented as #93); it's not deeply hard to fix but it's surprisingly much work. Issue: https://github.com/Khan/genqlient/issues/60 Issue: https://github.com/Khan/genqlient/issues/12 ## Test plan: make check Author: benjaminjkraft Reviewers: StevenACoffman, jvoll, benjaminjkraft, aberkan, csilvers, dnerdy, mahtabsabet, MiguelCastillo Required Reviewers: Approved By: StevenACoffman, jvoll Checks: ✅ Test (1.17), ✅ Test (1.16), ✅ Test (1.15), ✅ Test (1.14), ✅ Lint, ✅ Test (1.17), ✅ Test (1.16), ✅ Test (1.15), ✅ Test (1.14), ✅ Lint Pull Request URL: https://github.com/Khan/genqlient/pull/94
This commit is contained in:
@@ -16,6 +16,7 @@ type genqlientDirective struct {
|
||||
Pointer *bool
|
||||
Struct *bool
|
||||
Bind string
|
||||
TypeName string
|
||||
}
|
||||
|
||||
func (dir *genqlientDirective) GetOmitempty() bool { return dir.Omitempty != nil && *dir.Omitempty }
|
||||
@@ -68,6 +69,8 @@ func fromGraphQL(dir *ast.Directive, pos *ast.Position) (*genqlientDirective, er
|
||||
err = setBool(&retval.Struct, arg.Value)
|
||||
case "bind":
|
||||
err = setString(&retval.Bind, arg.Value)
|
||||
case "typename":
|
||||
err = setString(&retval.TypeName, arg.Value)
|
||||
default:
|
||||
return nil, errorf(pos, "unknown argument %v for @genqlient", arg.Name)
|
||||
}
|
||||
@@ -157,6 +160,10 @@ func validateStructOption(
|
||||
return nil
|
||||
}
|
||||
|
||||
// merge joins the directive applied to this node (the argument) and the one
|
||||
// applied to the entire operation (the receiver) and returns a new
|
||||
// directive-object representing the options to apply to this node (where in
|
||||
// general we take the node's option, then the operation's, then the default).
|
||||
func (dir *genqlientDirective) merge(other *genqlientDirective) *genqlientDirective {
|
||||
retval := *dir
|
||||
if other.Omitempty != nil {
|
||||
@@ -171,6 +178,10 @@ func (dir *genqlientDirective) merge(other *genqlientDirective) *genqlientDirect
|
||||
if other.Bind != "" {
|
||||
retval.Bind = other.Bind
|
||||
}
|
||||
// For typename, the local directive always wins: when specified on the query
|
||||
// options typename applies to the response-struct, not to all parts of the
|
||||
// query.
|
||||
retval.TypeName = other.TypeName
|
||||
return &retval
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user