-
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
Allow creating aliases for builtin types, using typename
.
#133
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,11 @@ | ||
query ConflictingTypeNames { | ||
# @genqlient(typename: "T") | ||
f { g } | ||
f { | ||
g | ||
} | ||
# @genqlient(typename: "T") | ||
otherF: f { g h } | ||
otherF: f { | ||
g | ||
h | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,20 @@ | ||
# @genqlient(typename: "Resp") | ||
query TypeNames { | ||
# @genqlient(typename: "User") | ||
user { id name } | ||
user { | ||
id | ||
name | ||
} | ||
# @genqlient(typename: "Item") | ||
randomItem { id name } | ||
randomItem { | ||
id | ||
# @genqlient(typename: "NameType") | ||
name | ||
} | ||
# (ok to reuse the name as long as they match) | ||
# @genqlient(typename: "User") | ||
users { id name } | ||
users { | ||
id | ||
name | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -65,6 +65,14 @@ type ( | |
GraphQLName string | ||
Marshaler, Unmarshaler string | ||
} | ||
// goTypenameForBuiltinType represents a builtin type that was | ||
// given a different name due to a `typename` directive. We | ||
// create a type like `type MyString string` for it. | ||
goTypenameForBuiltinType struct { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I might also name this goTypeForBuiltinType. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (I would have called it |
||
GoTypeName string | ||
GoBuiltinName string | ||
GraphQLName string | ||
} | ||
// goSliceType represents the Go type []Elem, used to represent GraphQL | ||
// list types. | ||
goSliceType struct{ Elem goType } | ||
|
@@ -75,21 +83,29 @@ type ( | |
) | ||
|
||
// Opaque types are defined by the user; pointers and slices need no definition | ||
func (typ *goOpaqueType) WriteDefinition(io.Writer, *generator) error { return nil } | ||
func (typ *goOpaqueType) WriteDefinition(io.Writer, *generator) error { return nil } | ||
|
||
func (typ *goTypenameForBuiltinType) WriteDefinition(w io.Writer, g *generator) error { | ||
fmt.Fprintf(w, "type %s %s", typ.GoTypeName, typ.GoBuiltinName) | ||
return nil | ||
} | ||
func (typ *goSliceType) WriteDefinition(io.Writer, *generator) error { return nil } | ||
func (typ *goPointerType) WriteDefinition(io.Writer, *generator) error { return nil } | ||
|
||
func (typ *goOpaqueType) Reference() string { return typ.GoRef } | ||
func (typ *goSliceType) Reference() string { return "[]" + typ.Elem.Reference() } | ||
func (typ *goPointerType) Reference() string { return "*" + typ.Elem.Reference() } | ||
func (typ *goOpaqueType) Reference() string { return typ.GoRef } | ||
func (typ *goTypenameForBuiltinType) Reference() string { return typ.GoTypeName } | ||
func (typ *goSliceType) Reference() string { return "[]" + typ.Elem.Reference() } | ||
func (typ *goPointerType) Reference() string { return "*" + typ.Elem.Reference() } | ||
|
||
func (typ *goOpaqueType) SelectionSet() ast.SelectionSet { return nil } | ||
func (typ *goSliceType) SelectionSet() ast.SelectionSet { return typ.Elem.SelectionSet() } | ||
func (typ *goPointerType) SelectionSet() ast.SelectionSet { return typ.Elem.SelectionSet() } | ||
func (typ *goOpaqueType) SelectionSet() ast.SelectionSet { return nil } | ||
func (typ *goTypenameForBuiltinType) SelectionSet() ast.SelectionSet { return nil } | ||
func (typ *goSliceType) SelectionSet() ast.SelectionSet { return typ.Elem.SelectionSet() } | ||
func (typ *goPointerType) SelectionSet() ast.SelectionSet { return typ.Elem.SelectionSet() } | ||
|
||
func (typ *goOpaqueType) GraphQLTypeName() string { return typ.GraphQLName } | ||
func (typ *goSliceType) GraphQLTypeName() string { return typ.Elem.GraphQLTypeName() } | ||
func (typ *goPointerType) GraphQLTypeName() string { return typ.Elem.GraphQLTypeName() } | ||
func (typ *goOpaqueType) GraphQLTypeName() string { return typ.GraphQLName } | ||
func (typ *goTypenameForBuiltinType) GraphQLTypeName() string { return typ.GraphQLName } | ||
func (typ *goSliceType) GraphQLTypeName() string { return typ.Elem.GraphQLTypeName() } | ||
func (typ *goPointerType) GraphQLTypeName() string { return typ.Elem.GraphQLTypeName() } | ||
|
||
// goEnumType represents a Go named-string type used to represent a GraphQL | ||
// enum. In this case, we generate both the type (`type T string`) and also a | ||
|
@@ -502,26 +518,29 @@ func (typ *goInterfaceType) Reference() string { return typ.GoName | |
func (typ *goInterfaceType) SelectionSet() ast.SelectionSet { return typ.Selection } | ||
func (typ *goInterfaceType) GraphQLTypeName() string { return typ.GraphQLName } | ||
|
||
func (typ *goOpaqueType) Unwrap() goType { return typ } | ||
func (typ *goSliceType) Unwrap() goType { return typ.Elem.Unwrap() } | ||
func (typ *goPointerType) Unwrap() goType { return typ.Elem.Unwrap() } | ||
func (typ *goEnumType) Unwrap() goType { return typ } | ||
func (typ *goStructType) Unwrap() goType { return typ } | ||
func (typ *goInterfaceType) Unwrap() goType { return typ } | ||
|
||
func (typ *goOpaqueType) SliceDepth() int { return 0 } | ||
func (typ *goSliceType) SliceDepth() int { return typ.Elem.SliceDepth() + 1 } | ||
func (typ *goPointerType) SliceDepth() int { return 0 } | ||
func (typ *goEnumType) SliceDepth() int { return 0 } | ||
func (typ *goStructType) SliceDepth() int { return 0 } | ||
func (typ *goInterfaceType) SliceDepth() int { return 0 } | ||
|
||
func (typ *goOpaqueType) IsPointer() bool { return false } | ||
func (typ *goSliceType) IsPointer() bool { return typ.Elem.IsPointer() } | ||
func (typ *goPointerType) IsPointer() bool { return true } | ||
func (typ *goEnumType) IsPointer() bool { return false } | ||
func (typ *goStructType) IsPointer() bool { return false } | ||
func (typ *goInterfaceType) IsPointer() bool { return false } | ||
func (typ *goOpaqueType) Unwrap() goType { return typ } | ||
func (typ *goTypenameForBuiltinType) Unwrap() goType { return typ } | ||
func (typ *goSliceType) Unwrap() goType { return typ.Elem.Unwrap() } | ||
func (typ *goPointerType) Unwrap() goType { return typ.Elem.Unwrap() } | ||
func (typ *goEnumType) Unwrap() goType { return typ } | ||
func (typ *goStructType) Unwrap() goType { return typ } | ||
func (typ *goInterfaceType) Unwrap() goType { return typ } | ||
|
||
func (typ *goOpaqueType) SliceDepth() int { return 0 } | ||
func (typ *goTypenameForBuiltinType) SliceDepth() int { return 0 } | ||
func (typ *goSliceType) SliceDepth() int { return typ.Elem.SliceDepth() + 1 } | ||
func (typ *goPointerType) SliceDepth() int { return 0 } | ||
func (typ *goEnumType) SliceDepth() int { return 0 } | ||
func (typ *goStructType) SliceDepth() int { return 0 } | ||
func (typ *goInterfaceType) SliceDepth() int { return 0 } | ||
|
||
func (typ *goOpaqueType) IsPointer() bool { return false } | ||
func (typ *goTypenameForBuiltinType) IsPointer() bool { return false } | ||
func (typ *goSliceType) IsPointer() bool { return typ.Elem.IsPointer() } | ||
func (typ *goPointerType) IsPointer() bool { return true } | ||
func (typ *goEnumType) IsPointer() bool { return false } | ||
func (typ *goStructType) IsPointer() bool { return false } | ||
func (typ *goInterfaceType) IsPointer() bool { return false } | ||
|
||
func writeDescription(w io.Writer, desc string) { | ||
if desc != "" { | ||
|
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.
In principle we should probably support this for types via global or local
bind
as well, if you have an int and you want to bind it toint32
and also use a named type? The best way to do that is probably to do it in the callerconvertType
, similar to how we dopointer
. (Or you could make it a TODO until anyone actually cares.)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.
I went to write this TODO and realized I don't understand exactly the use case you're talking about. Can you give a concrete example?
bind
works with types you define, so you can already docan't you?
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, I see,
bind
wins overtypename
, I was worriedtypename
would win overbind
which would be more confusing. So it's still the case that if you have ingenqlient.yaml
:and now you do
the
typename
is ignored. Really we should combine the two, i.e.:Of course it's not really clear why you would want that, so we could also explicitly error. But it's honestly probably just as easy to make it do the obvious thing. (Initially I was worried we'd do
type MyOtherType int
, which would be wrong.)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.
Did you mean we should emit
type MyOtherType int32
? I guess I'm not seeing what "the obvious thing" is.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 yes that's what I meant! Edited.
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.
OK, I'll take a stab when I have a moment, or else add a TODO (also when I have a moment :-) )
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.
And, to be clear, that's the obvious thing: define a new alias (from
typename
) to the bound type (frombind
).