Allow creating aliases for builtin types, using typename. (#133)

## Summary:
This lets you write code like:
```
query x {
   # @genqlient(typename: "MyString")
   someStringField
}
```
and genqlient will do
```
typename MyString string
type x struct {
   someStringField MyString
}
```

This was not difficult to implement, though it required introducing a
new identifier type.  The main difficulty I had was weird test
failures, that it turns out was due to the tests putting a bunch of
fields on the same line, so that the genqlient directive on the
previous line applied to all of them, accidentally.  This became a
problem when `typename` suddenly started being respected for builtin
types!  I fixed it by just spreading out the queries a bit.

Fixes #130

## Test plan:
make check

Author: csilvers

Reviewers: dnerdy, StevenACoffman, benjaminjkraft

Required Reviewers:

Approved By: StevenACoffman

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/133
This commit is contained in:
Craig Silverstein
2021-10-05 08:49:50 -07:00
committed by GitHub
parent 59b6df6aab
commit a52e55632f
8 changed files with 121 additions and 46 deletions
+2
View File
@@ -26,6 +26,8 @@ When releasing a new version:
- genqlient now generates getter methods for all fields, even those which do not implement a genqlient-generated interface; this can be useful for callers who wish to define their own interface and have several unrelated genqlient types which have the same fields implement it.
- genqlient config now accepts either a single or multiple schema files for the `schema` field.
- The `typename` option can now be used on basic types (string, int, etc) as well as structs; this can be useful to have genqlient define new types like `type Language string` and use that type for specified fields.
### Bug fixes:
- In certain very rare cases involving duplicate fields in fragment spreads, genqlient would generate code that failed to compile due to duplicate methods not getting promoted; genqlient now generates correct types. (See #126 for a more complete description.)
+7 -5
View File
@@ -76,11 +76,13 @@ client_getter: "github.com/you/yourpkg.GetClient"
# A map from GraphQL type name to Go fully-qualified type name to override
# the Go type genqlient will use for this GraphQL type.
#
# This is primarily used for custom scalars, or to map builtin scalars to
# a nonstandard type. By default, builtin scalars are mapped to the
# obvious Go types (String and ID to string, Int to int, Float to float64,
# and Boolean to bool), but this setting will extend or override those
# mappings.
# This is primarily used for custom scalars, or to map builtin scalars
# to a nonstandard type that is defined elsewhere. By default,
# builtin scalars are mapped to the obvious Go types (String and ID to
# string, Int to int, Float to float64, and Boolean to bool), but this
# setting will extend or override those mappings. (See also
# @genqlient(typename: ...), which can be used to map builtin scalars
# to a nonstandard type that genqlient defines for you.)
#
# genqlient does not validate these types in any way; they must define
# whatever logic is needed (MarshalJSON/UnmarshalJSON or JSON tags) to
+24
View File
@@ -164,6 +164,10 @@ directive genqlient(
# you can do that, as long as its UnmarshalJSON method can accept a list
# of datetimes.)
#
# Note that the type you bind to must be defined elsewhere in your code.
# If you want genqlient to create the type definition, use "typename"
# instead.
#
# See bindings in genqlient.yaml for more details; this is effectively to a
# local version of that global setting and should be used with similar care.
# If set to "-", overrides any such global setting and uses a
@@ -189,6 +193,26 @@ directive genqlient(
# }
# instead of its usual, more verbose type names.
#
# You may also use "typename" on basic types, and Go will create a
# type definition for that basic type. For instance:
# query MyQuery {
# user {
# # @genqlient(typename: "NameType")
# name
# }
# }
# will cause gnqlient to generate:
# type Resp struct {
# User User
# }
# type NameType string
# type User struct {
# Name NameType
# }
# (Compare this to @genqlient(bind: "path/to/pkg.NameType"), which does
# something similar but depends on "NameType" being defined in some
# other package, rather than having genqlient define it for you.)
#
# With great power comes great responsibility: when using typename you'll
# need to avoid comments; genqlient will complain if you use the same
# type-name in multiple places unless they request the exact same fields, or