Commit Graph

266 Commits

Author SHA1 Message Date
Ben Kraft b1adeca6da Automatically update generated files if UPDATE_SNAPSHOTS=1 (#243)
If you do `UPDATE_SNAPSHOTS=1 go test ./...` that will:
1. run the snapshot tests, updating any changed snapshots
2. run the integration tests and (if you have tokens) example tests
3. check that the code for the integration tests and example tests is
up-to-date

Step 3 is not strictly a snapshot test; the generated code is actually
checked in and used. But, I mean, it's basically the same! So now, we
also update it if you asked to update snapshots, which is hopefully a
little more convenient.

Fixes #212.

Test plan:
Make a trivial change to `example/generated.go`; `go test ./...` should
now fail. `UPDATE_SNAPSHOTS=1 go test ./...` should also fail, but say
it updated the snapshot, and the change should be reverted. Run `go test
./...` again; it should pass again.
2022-12-21 23:19:20 -08:00
Craig Silverstein e3227388fe Rename the query constant to have an underscore in it. (#241)
We got reports of conflicts with the old constant-name and symbols that
people were defining in their app.
2022-11-22 14:12:38 -08:00
Craig Silverstein 587f77046b Expose the graphql operation as a constant in the generated genqlient file (#238)
This allows client code to see the operation (query or mutation) exactly
as genqlient sends it over the wire. This data was already available in
the generated safelist.json file, but now it's easily available from Go
code as well.
    
Fixes #236

I have:
- [x] Written a clear PR title and description (above)
- [x] Signed the [Khan Academy CLA](https://www.khanacademy.org/r/cla)
- [x] Added tests covering my changes, if applicable
- [x] Included a link to the issue fixed, if applicable
- [x] Included documentation, for new features
- [x] Added an entry to the changelog
2022-11-21 08:35:09 -08:00
Matúš Bafrnec 00f27609f0 fixed "for" directive documentation (#235)
This PR is addressing the behavior described in #151.
The former version of `for` directive example usage ended in:
```
genqlient.graphql:<line>: for is only applicable to operations and arguments
```


I have:
- [x] Written a clear PR title and description (above)
- [x] Signed the [Khan Academy CLA](https://www.khanacademy.org/r/cla)
- [x] Added tests covering my changes, if applicable
- [x] Included a link to the issue fixed, if applicable
- [x] Included documentation, for new features
- [x] Added an entry to the changelog

Signed-off-by: Matúš Bafrnec <matus.bafrnec@gmail.com>
2022-11-17 18:19:35 -05:00
Ben Kraft 80687e7336 Support package-names with dashes in them (#232)
Support package-names with dashes in them

We were smart about aliasing if you have name-collisions, but not if
your package name is something that's not a valid identifier, like
`"path/to/my-package"`, which Go for better or worse allows. Now we
remove all the invalid characters (in practice mainly dashes, dots, and
leading digits).

Fixes #231.

Test plan: make check
2022-11-09 09:43:04 -08:00
Ben Kraft 1d71fffcb6 Fix documentation for optional: value (#229)
A couple people noticed the documentation didn't match
the actual option syntax we settled on. Now it does.

Fixes #226, replaces #222 (closed due to CLA issues).
2022-10-23 21:20:10 -07:00
Ben Kraft 85e2e8dffd Move changelog entry to the right version (#217)
Thanks to `git merge` being clever, this got put in `v0.5.0` even
though it was added after `v0.5.0` was released. Now it's in `vNext`
(perhaps soon to become `v0.5.1`).
2022-08-15 15:08:26 -07:00
Ben Kraft 16a17f2eef Give a better error if package_bindings is a file (#221)
The entries under the new `package_bindings` field should be packages,
but it's an easy mistake to put a file path instead (most of the other
fields in `genqlient.yaml` are files). Due to some bizzare behavior from
`go/packages` (described in #220), if you do that you get weird broken
code that gives you no clue what is wrong. Instead, let's guess if what
you gave us looks like a filename, and report a nice error if so.

Test plan: crossed fingers
2022-08-15 15:08:15 -07:00
Ben Kraft f600b6e5d3 Bump golangci-lint and (max) Go versions (#219)
Lint is failing with some inscrutable panic (on a commit with no code
changes). Let's try bumping the version in case they fixed it.

Additionally, the new version's github action uses Go 1.19, which means
it pulls in gofmt updates to match the new [doc-comment formatting rules][1].
So I added Go 1.19 to our list of versions to test (fixes #216)
and updated some of our doc-comments to format better in the
new world (mostly using the new link syntax).

[1]: https://go.dev/doc/comment

Test plan: make lint
2022-08-15 15:05:36 -07:00
Lucas Bremgartner c0510ff54a Fix incorrectly formatted error string (#213)
Follow best practices from Go Review Comments:
https://github.com/golang/go/wiki/CodeReviewComments#error-strings

Closes: #202
2022-08-04 14:57:45 -07:00
Ben Kraft 046f531314 Add more information about updating snapshots (#211)
The generated files for integration tests aren't strictly snapshots and so
`UPDATE_SNAPSHOTS=1` won't work (maybe we should make it work?).
Instead you also need to `go generate ./...`. This came up in #209.
2022-07-28 16:31:55 -07:00
Viktor Stanchev 2ae8ea42e5 Make output deterministic for graphql interfaces (#209)
We noticed that the output from genqlient can be non-deterministic
when a graphql query queries a field that's an interface. This PR
fixes that by sorting the types as soon as we extract them from
the schema.
2022-07-28 16:19:53 -07:00
Ben Kraft 03b6b6b5d1 Mention how to update the snapshot tests (#210)
Frequent contributors and those adding significant new functionality
will want to read all the comments in `generate_test.go`, but people
making a small fix just want to update the snapshots. So it makes
sense to put the formula for doing so directly in the contributor docs.
2022-07-28 12:52:16 -07:00
NuVivo314 093054ef32 Add new package bindings option (#169)
Add new package bindings option

This commit adds list of packages for which genqlient should automatically
generate bindings; it's equivalent to adding all the exported types in the
package to `bindings` explicitly. This can be useful when you're both a client
and a server of the same schema and want to share types. We don't recommend
doing things that way, but the feature isn't too invasive and may be useful for
other purposes.

Co-authored-by: Ben Kraft <ben@benkraft.org>
2022-06-17 11:42:49 -07:00
Ben Kraft 1f44dc6db3 Release v0.5.0 (#208)
It feels like just yesterday, but it's been over four months since our
last release! So it's as good a time as any; while there are quite a few
changes they're individually mostly small. As usual, this updates the
changelog, and I'll tag it with the release once it lands.

Test plan: no relevant bug reports lately
2022-06-16 16:22:12 -07:00
Ben Kraft e38a212de2 Be more precise in deciding whether to add the schema prelude (#205)
GraphQL schemas have some builtin types, like `String`. The spec says
your SDL must not include those, but in practice some schemas do. (This
is probably because introspection must include them, and some tools that
create SDL from introspection don't know they're supposed to filter them
out.) Anyway, we've since #145 had logic to handle this; we just parse
with and without the prelude that defines them and see which works.

The problem is that this makes for very confusing error messages if you
have an invalid schema. (Or if you have a schema that you think is valid
but gqlparser doesn't, which is the more common case in the wild; see
for example #200.) Right now if both ways error we take the
without-prelude error, which if you didn't define the builtins is just
`undefined type String`; if we took the with-prelude error then if you
did define the builtins you'd just get `type String defined twice`. So
we actually have to be smart if we want good error messages for
everyone.

So in this commit we are smart: we check if your schema defines
`String`, and include the prelude only if it does not. To do this I
basically inlined `gqlparser.LoadSchema` (twice), so that in between
parsing and validation we can check if you have `String` and if not add
the prelude. This should in theory be both more efficient (we don't
have to do everything twice) and give better error messages,
although it's a bit more code.

Fixes #175.

Test plan: make check
2022-06-06 16:50:16 -07:00
Ben Kraft 520532eb65 Add tests to check that genqlient handles covariance (#203)
I didn't realize until today that implementations of GraphQL interfaces
are actually allowed to be covariant: if the interface has a field
`f: T`, then the implementations may have fields `f: U` where `U` is a
subtype of `T` (for example `U` may be an implementation of the
interface `T`, or `U` may be `T!` if `T` is non-nullable. (I thought it
had to be `f: T` exactly.) So I figured I'd add a test and see what
breaks.

Surprisingly, and despite the fact that Go interfaces do *not* allow
covariance, everything... worked? There's at least one place where it's
possible we could ideally use a more specific type [1], but for now I
just wanted to make sure we at least write something that builds and is
vaguely reasonable. Of course I'm not sure if there's anything I've
missed (some day I need to find a fuzzing engine that can fuzz GraphQL).

[1] Specifically, the field
`CovariantInterfaceImplementationRandomItemTopic.Next` might ideally
have type `...NextContentTopic`, not `...NextContent`; we know it's a
topic. This doesn't directly cause covariance problems in Go: the method
`GetNext` still returns `...NextContent` so the interface matches. But
that trick doesn't work for the sibling field `.Related` which is
slice-typed: or rather, we'd need the method to copy the slice to the
correct type. (Not to mention the implemention of any change here would
require a bunch of plumbing because the AST doesn't quite have what we
want.) So it's probably best to just keep this as-is for simplicity and
consistency.

Test plan: make check
2022-06-03 22:53:44 -07:00
Chris Connelly 37fa3d6e7c Add support for mapping all nullable types as pointers (#198)
This implements the approach suggested in
https://github.com/Khan/genqlient/issues/178#issuecomment-1077559343.
See the added documentation for the full behavior.
2022-05-24 12:24:06 -07:00
Ben Kraft 3685f3f66b Validate against a case gqlparser doesn't catch (#197)
While writing tests at some point I came across an invalid query that
gqlparser doesn't catch, and which causes a panic for us.  Now we
validate for it and return a nice error instead of panicing.

Fixes #176.

Test plan: make check
2022-05-18 13:21:30 -07:00
Ben Kraft d4ec64fef1 Simplify errors tests a bit so they don't all have to write a schema (#196)
Some of the errors tests need to have their own schema, so the schema
can do something weird (or even be entirely invalid!).  But most can
still share a schema.  In this commit I have those indeed share a
schema, to avoid having to have a bunch of copies of mostly the same
schema.  While doing so I noticed one error whose location wasn't very
useful, and fixed it.

Test plan: make check
2022-05-15 12:20:18 -07:00
Ben Kraft 39cd158d33 Reject operation or argument names that are Go keywords (#195)
GraphQL is pretty restrictive about its identifiers, so for the most
part we can and do safely use GraphQL identifiers in the Go we generate
with attention only to conflicts with other such identifiers. But we do
need to check one thing, which is that the identifier isn't a Go
keyword. (If it is, the generated code will almost certainly fail to
compile, but often with a confusing error message.) In this commit I add
such checks.

The most likely place to run into trouble here is argument names, which
are often one word and are used as-is.  Operation names, if unexported,
can also be keywords, although in practice they're usually multiword.
Field names are always exported, thus safe.  Generated type names are
always prefixed, camel-cased, with the operation name, so they always
contain an uppercase letter (even if the operation name is lowercase),
but type-names specified by `typename` may collide, so we check those.
In theory we could check type-names specified by `bind`, but these must
be defined by the user, so their code will already fail to compile, so I
didn't bother.  I think that's all the places to consider, although it's
hard to be sure.  In summary, we check argument names, operation names,
and user-specified type names.

Test plan: make check
2022-05-12 15:00:55 -07:00
Craig Silverstein 482a59b802 Allow absolute paths in schema files. (#192)
* Allow absolute paths in schema files.

Thsi is useful for some out-of-tree testing I want to do.  It's
unfortunate (imo) that filepath.join doesn't have this behavior by
default.

Test plan:
go test ./...

* run gofmt

* one more change to use pathJoin
2022-05-12 14:04:04 -07:00
Ben Kraft c8cbe805eb Add mention of tools.go to FAQ (#189)
This came up in #160, and will surely come up again. I hope the Go
folks figure out something better here, but until such time...
2022-04-29 13:26:32 -07:00
salman-rb 39a980ab4e Add support for client that uses GET as transport mechanism (#186)
Current implementation always uses POST as the transport mechanism. Adding GET support enables usage of GET queries for caching simply via URL.

Some notes:
- I left the existing API for creating a new client as is, but the implementation could be much cleaner by introducing some sort of configuration struct when creating a new client
- The construction of the query parameters follows the logic from Apollo's client implementation, which can be found here https://github.com/apollographql/apollo-client/blob/8beb4820edc6352996e08f7f73bde3573f1eb666/src/link/http/rewriteURIForGET.ts
- Updated integration tests to use both sets of clients. Updating the tests to use a test suite would be cleaner
2022-04-13 16:16:27 -07:00
Jan-Hendrik Boll b2422452a1 Add GraphQL Extensions (#184)
This enables accessing the Extensions field, as defined in the response
format: https://spec.graphql.org/October2021/#sec-Response-Format

Extensions can be enabled using configuration option use_extensions.
This will change the return parameters of the generated client
functions. Making it a breaking change if enabled.

Since extensions are untyped as defined in the spec, the Client will
return an interface of type map[string]interface{}.
2022-03-30 13:48:01 -07:00
Ben Kraft e81d19c8be Upgrade golangci-lint (#182)
1.42 seems to be having some problems with Go 1.18 (see #2649), so let's
just upgrade to latest.  There was one new error, suggesting to use `%q`
rather than `"%s"`, since the former does escapes properly.  It doesn't
really matter for us -- the string should be an identifier -- but it
doesn't hurt.  (Plus it wanted us to upgrade from ioutil, which I did
in #181.)

Test plan: make check
2022-03-22 12:25:47 -07:00
Ben Kraft 000f311254 Remove ioutil (#181)
In 1.16, it's now deprecated and replaced by `io` and `os`.  Let's
upgrade!

Test plan:
- make check
- git grep ioutil
2022-03-22 12:10:24 -07:00
Ben Kraft 36e86cf97f Embed data files in the binary (#180)
Now that we're on Go 1.16+ we can do this easily! The main advantage is
it means users can build a genqlient binary and use that portably (or we
could distribute one, or whatever). Plus the code is marginally simpler;
the `embed` API is really quite nice.

Fixes #9.

Test plan:
```
make check
go build .
rm -rf generate               # pretend we have no checkout
./genqlient ./internal/integration/genqlient.yaml
./genqlient --init            # fails after generating a default config
```
2022-03-22 12:00:56 -07:00
Ben Kraft 13094c3e58 Update tested Go versions (and deps) (#179)
Go 1.18 is out! So we should run tests on it.

Additionally, gqlgen had some issues with it (see 99designs/gqlgen#1961
and golang/go#45584) so I updated that too, which updated some other
things.

Finally, latest gqlgen requires 1.16+, and it's time for us to do the
same anyway, so we can use `embed` and other newer goodies.  So I
dropped running tests for 1.14 and 1.15, and bumped the module language
version.

Test plan: make check
2022-03-22 11:36:26 -07:00
Ben Kraft 8e8a632c21 Release v0.4.0 (#174)
It's been a while, time for a release! This commit updates the
changelog including a few missing entries, and I'll tag it with
the release once it lands.

Fixes #163 

Test plan: Craig tested a fairly recent main branch in webapp.
2022-02-10 15:17:36 -08:00
Ben Kraft 49a26aff9b Reject a glob that matches no files (#173)
The most important case here is if your glob isn't even a glob, it's
just a filename.  But even if it was a glob, it's probably a mistake;
you'll probably end up with a confusing error due to an empty schema, or
a slightly less confusing error due to not having any operations.
Instead, let's just say outright that your glob didn't match any files.

Fixes #146.

Test plan:
This was a bit annoying to test via snapshot, so I just tested it
manually by modifying the example to use a glob that didn't match any
files, first for the schema then for the operations, and got errors like
```
bogus*.graphql did not match any files
exit status 1
example/main.go:68: running "go": exit status 1
```
2022-02-09 16:55:20 -08:00
Ben Kraft 67f2575cae Reject the use of both typename and bind (#172)
In #133, Craig added support for a new use of typename, where it applies
to a scalar and means that genqlient should generate a named type, e.g.
`# @genqlient(typename: "MyString")` on a node of type string will
generate and use `type MyString string`.  But this gets a bit confusing
if you mix it with `bind`; should
`typename: "MyString", bind: "int32"` generate `type MyString int32`, or
should one override the other, or what?  Of course in practice you're
not likely to write that all in one place, but you could via a global
binding, or a `for` directive, and in that case probably it was a
mistake.  In #138, we looked at making them work together correctly, but
it added complexity and got even more confusing.

So instead, here, we just ban it; we can always add it back if it proves
useful.  (Or, you can make the `typename` win over a global binding by
locally unbinding it via `bind: "-"`.)  This required changes in
surprisingly many places; I already knew the directive-validation code
was due for a refactor but that will happen some other day.  The tests
show that it works, in any case.

Interestingly, this problem actually could have arisen for a struct
binding already, before #133.  But all the same reasons it's confusing
seem to apply, so I just banned it there too.  This is technically a
breaking change although I doubt anyone will hit it.

Test plan: make check
2022-02-09 16:54:31 -08:00
Ben Kraft 8aa56aacf1 Add a PR template (#171)
This is just what's already in the contributing docs, and is just to help both reviewers and authors remember to add changelog entries, check for tests, etc.
2022-02-09 13:00:28 -08:00
Steve Coffman 6bedb6660a Update gqlparser to v2.3.1 (#166)
gqlparser v2.3.1 appears to work ok, but v2.3.0 gqlparser had a PR that needed to be reverted.
2022-01-27 15:31:46 -08:00
Adam Babik 9fbb6b87aa Avoid capitalized error strings in generated code (#162)
Error strings should follow established guidelines
to ensure good composability and uniformity.
A mention of this particular guideline can be found
in Go Code Review Comments:
https://github.com/golang/go/wiki/CodeReviewComments#error-strings
2022-01-13 11:01:33 -08:00
Adam Babik f0c2ac17a9 Move 'Code generated by' disclaimer up (#161)
`Code generated by` disclaimer should be at the top of the file, as it is demonstrated in [this article](https://go.dev/blog/generate) on The Go Blog.

The current placing breaks integration with some code formatters and linters which do no skip files generated by `genqlient`.
2021-12-20 10:04:13 -05:00
Nikolay Edigaryev f80df6d4f1 Sort operations to guarantee a stable order (#156)
Problem: currently when using a wildcard that covers multiple files in `operations:` YAML directive the generator emits functions in a non-stable ordering due to the use of map for storing file names:

https://github.com/Khan/genqlient/blob/e0accbded177db9143314911bacedf61b2cda656/generate/parse.go#L68-L84

Solution: sort the operations before emitting them.
2021-11-26 12:32:03 -08:00
Nathan Stitt 2fdbb629be Add "struct_references" configuration (#155)
Adds a "struct_references" configuration that will:

* Use a pointer type for struct fields that are a complex type
* The behaviour can be overridden by setting "pointer: false" in the
  proceeding comment blocks
* Sets the "omitempty: true" flag on fields matching the criteria.
  This can also be overriden by setting "omitempty: false"

Although we'd debated not setting the pointer for array elements, it did turn out to be simpler to set them everywhere and also made the documentation cleaner to have a single rule to explain.

Fixes #149.
2021-11-12 19:53:19 -08:00
Hasibul Hasan 5401a62dcb TYPO: Fixed variable name and position in interface definition. (#154)
I was also confused about the variable names (#153). But in this [commit](https://github.com/Khan/genqlient/commit/5995653583af6e8d42477652f7d51ac4201b9fe6) it is clear that the first var is output, second var is input. In this commit I have fixed the issue. Fixes #153
2021-11-05 09:21:45 -07:00
Florian Suess e0accbded1 Allow compatibility when using introspection derived client schema's (#145)
During generation we parse the schema using [`gqlparser.LoadSchema`](https://github.com/vektah/gqlparser/blob/2a3d320c0f1d31f404cc36f6cce8f7f93b016682/gqlparser.go#L11) over [here](https://github.com/Khan/genqlient/blob/a4aa6d9bb0f45cb71b3b7816742172011d96fbc1/generate/parse.go#L34). As you can see `gqlparser.LoadSchema` uses it's sub directory declared [`validator.LoadSchema`](https://github.com/vektah/gqlparser/blob/2a3d320c0f1d31f404cc36f6cce8f7f93b016682/gqlparser.go#L12) - but prepends a schema with [typical implicit declared types](https://github.com/vektah/gqlparser/blob/2a3d320c0f1d31f404cc36f6cce8f7f93b016682/validator/prelude.go#L5). Full server schema introspection exposes the entire schema explicitly, hence causing a clash with this prelude schema rendering introspection derived schemas to fail.

Here I just introduce a two stage schema parsing step to accomodate both implicit and explicit sdl's.

--

I have also added to the FAQ as per https://github.com/Khan/genqlient/issues/4 how we can use introspection to fetch the schema when using `genqlient`.

Co-authored-by: Ben Kraft <ben@benkraft.org>
2021-10-27 15:27:37 -07:00
Steve Coffman a4aa6d9bb0 Update dependencies to latest (#144)
Signed-off-by: Steve Coffman <steve@khanacademy.org>
2021-10-22 15:40:26 -07:00
Tarrence van As 3657ce129a docs: fix go generate directive (#143) 2021-10-22 09:26:48 -07:00
John Maguire 10dc388016 Walk parent directories to find config file (#141)
Code is mostly borrowed from [gqlgen](https://github.com/99designs/gqlgen).

The idea here is that I want to be able to store `genqlient.yaml` at the top-level, but my client code lives down in `graph/client/`. I put the `//go:generate` line in `graph/client/client.go`.
2021-10-21 21:43:34 -04:00
John Maguire 9ecc62e285 Fix error handling during config init (#142)
Previously initConfig always returned an error even if it succeeded.
This resulted in a confusing CLI error message that did not match the
executed behavior.

Now it returns an error only if it fails to init the config.
2021-10-21 11:46:01 -07:00
John Maguire 5c5c94b8a9 Fix link to genqlient.yaml from FAQ.md (#140) 2021-10-21 09:41:23 -04:00
Ben Kraft 22019287da Align support for multiple operation-files and multiple schema-files (#137)
Multiple schema-files are now supported as of #134, but the support was
a bit different from how we did multiple operation-files.  Before anyone
starts to depend on the ways the syntaxes differ, let's just make them
the same.  Since it's easy, I also added support for having just a
single operations-file.

I also realized while writing this that the type-change is technically
breaking (if you call from Go), so documented it as such. I think
this is unlikely to affect many people.

Test plan: make check
2021-10-05 12:52:48 -07:00
Craig Silverstein a52e55632f 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
2021-10-05 08:49:50 -07:00
Hasibul Hasan 59b6df6aab ️ Accept array of string as valid input schema path. (#134)
* Fixes #88. Accept array of string as valid input schema path.
2021-10-04 13:33:21 -07:00
Steve Coffman 5e3c4d1be8 Add CODEOWNERS so community PR reviews are auto-assigned (#135)
Signed-off-by: Steve Coffman <steve@khanacademy.org>
2021-10-04 14:24:15 -04:00
Ben Kraft 3a5bf46da4 Add getter methods to all fields, not just where needed (#126)
## Summary:
If your type implements an interface, we add getter methods for the
shared fields, so that those may be accessed via the interface.  But it
turns out occasionally it's useful to have these getter methods when
they don't implement a GraphQL interface, so you can use two
genqlient-generated types in the same function if they have the same
fields.  (This comes up most often when you have a GraphQL union that
maybe should really be an interface, or if you don't yet support
interfaces implementing other interfaces (indeed our parser doesn't
either).  But one can imagine other use cases.)

We can't predict how you want to do that, so we can't generate the
interface, but we can generate the methods, so you can define the
interface and do a type assertion from there.  Since these methods are
pretty simple to generate, we just do it always.  (As with #120, if
binary size becomes an issue we could later add an option to only
generate methods that are truly needed but including them seems like the
better default.)

This also fixes a subtle and rare bug, which would have become much more
common (indeed existing tests caught it).  Specifically, if you have a
query like
```graphql
fragment FragmentOne on T { id }
fragment FragmentTwo on T { id }
query Q {
    f {   # interface type T
        ...FragmentOne
        ...FragmentTwo
    }
}
```
since both `FragmentOne` and `FragmentTwo` request some common field,
say `id`, we generate a method `GetId` on each one.  But since
`FragmentOne` and `FragmentTwo` are both on `T`, we also include their
interfaces in the interface we generate for the type of `f`, `QFT`.  So
`QFT` includes a method `GetId`.  But on the implementations, the two
methods conflict, and neither gets promoted; this causes various code to
fail to compile.  With this change, this would have happened much more
frequently -- even if only one of the two fragments is on `T`, as long
as both request the field.  Anyway, we now generate explicit methods on
each struct for all of its recursively emebedded fields -- using the
logic from #120 to compute them -- so that we don't need to rely on
method-promotion.

## Test plan:
make tesc


Author: benjaminjkraft

Reviewers: csilvers, dnerdy, aberkan, jvoll, mahtabsabet, MiguelCastillo, StevenACoffman

Required Reviewers: 

Approved By: csilvers, dnerdy

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/126
2021-10-01 15:02:07 -07:00