-
Notifications
You must be signed in to change notification settings - Fork 114
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for interfaces, part 4: getter methods #57
Conversation
807a91a
to
1771758
Compare
a62553b
to
0965329
Compare
1771758
to
1821951
Compare
8352001
to
903f3af
Compare
1821951
to
ef831b4
Compare
903f3af
to
4e8b2d7
Compare
@@ -116,11 +137,25 @@ func TestInterfaceListField(t *testing.T) { | |||
|
|||
require.Len(t, resp.Beings, 3) | |||
|
|||
// We should get the following three beings: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note to self: post-rebase, need to apply these changes to TestInterfaceListPointerField
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! The detailed docstrings are a nice touch.
// how to refactor. | ||
for _, selection := range selectionSet { | ||
field, ok := selection.(*ast.Field) | ||
if !ok { // fragment/interface, not a shared field |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As we discovered with the validator edge case, a union doesn't have shared fields, but it may be possible to treat the fields as shared if all the union members implement the same interface corresponding to a fragment. Anyway, this will be tackled in the upcoming fragment changes (if we want to tackle it at all).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, yeah that's an interesting situation, and maybe a place where abstract-in-abstract spreads are more useful. Anyway, this is gonna get rewritten as you say.
ef831b4
to
3f3c64d
Compare
4e8b2d7
to
e0eaca5
Compare
3f3c64d
to
c37edb9
Compare
Right now, if you make a query like `{ myInterface { field } }`, you have to type-switch on all the possible implementations of `myInterface` to get at `field`. Now, we generate getter-methods (e.g. `GetField`), to make that access easier. Of course this only applies to shared fields (which for now are the only ones, but once we support fragments will no longer be). This also includes a small change to the way we generate type-names for interfaces: we no longer include the name of the concrete type in the interface we propagate forward, so we generate `MyInterfaceMyFieldMyType`, not `MyInterfaceMyImplMyFieldMyType`, in the case where you have an interface `MyInterface` implemented by `MyImpl` (and maybe other types) with field `myField: MyType`. This is necessary so the getter method returns a well-defined type, and also probably convenient for calling code. It will have to get a little bit more complicated once we support fragments, where you could have two implementing types with identically-named fields of different types, but I think it'll be easiest to figure out how to deal with that when implementing fragments. While I was in the area, I added to the interface doc-comment a list of the implementations. (In GraphQL, we're guaranteed to know them all assuming our schema is up to date.) Issue: #8 Test plan: make check Reviewers: marksandstrom, adam, miguel
e0eaca5
to
b8b66f5
Compare
Summary:
Right now, if you make a query like
{ myInterface { field } }
, youhave to type-switch on all the possible implementations of
myInterface
to get at
field
. Now, we generate getter-methods (e.g.GetField
),to make that access easier. Of course this only applies to shared
fields (which for now are the only ones, but once we support fragments
will no longer be).
This also includes a small change to the way we generate type-names for
interfaces: we no longer include the name of the concrete type in the
interface we propagate forward, so we generate
MyInterfaceMyFieldMyType
, notMyInterfaceMyImplMyFieldMyType
, in thecase where you have an interface
MyInterface
implemented byMyImpl
(and maybe other types) with field
myField: MyType
. This is necessaryso the getter method returns a well-defined type, and also probably
convenient for calling code. It will have to get a little bit more
complicated once we support fragments, where you could have two
implementing types with identically-named fields of different types, but
I think it'll be easiest to figure out how to deal with that when
implementing fragments.
While I was in the area, I added to the interface doc-comment a list of
the implementations. (In GraphQL, we're guaranteed to know them all
assuming our schema is up to date.)
Issue: #8
Test plan:
make check