clean up various TODOs and comments
This commit is contained in:
+2
-2
@@ -21,8 +21,8 @@ type Config struct {
|
||||
Package string `yaml:"package"`
|
||||
// The filename with the GraphQL schema (in SDL format); defaults to
|
||||
// schema.graphql
|
||||
// TODO: allow other formats
|
||||
// TODO: allow URLs
|
||||
// TODO: Allow fetching a schema via introspection (will need to figure out
|
||||
// how to convert that to SDL).
|
||||
Schema string `yaml:"schema"`
|
||||
// The filename with the queries; defaults to queries.graphql
|
||||
Queries string `yaml:"queries"`
|
||||
|
||||
+13
-7
@@ -56,14 +56,20 @@ func newGenerator(config *Config, schema *ast.Schema) *generator {
|
||||
}
|
||||
|
||||
func (g *generator) Types() string {
|
||||
names := make([]string, 0, len(g.typeMap))
|
||||
for name := range g.typeMap {
|
||||
names = append(names, name)
|
||||
}
|
||||
// Sort alphabetically by type-name. Sorting somehow deterministically is
|
||||
// important to ensure generated code is deterministic. Alphabetical is
|
||||
// nice because it's easy, and in the current naming scheme, it's even
|
||||
// vaguely aligned to the structure of the queries.
|
||||
sort.Strings(names)
|
||||
|
||||
defs := make([]string, 0, len(g.typeMap))
|
||||
for _, def := range g.typeMap {
|
||||
defs = append(defs, def)
|
||||
for _, name := range names {
|
||||
defs = append(defs, g.typeMap[name])
|
||||
}
|
||||
// Make sure we have a stable order. (It's somewhat
|
||||
// arbitrary but in practice mostly alphabetical.)
|
||||
// TODO: ideally we'd do a nice semantic ordering.
|
||||
sort.Strings(defs)
|
||||
return strings.Join(defs, "\n\n")
|
||||
}
|
||||
|
||||
@@ -84,7 +90,7 @@ func (g *generator) getArgument(arg *ast.VariableDefinition) (argument, error) {
|
||||
|
||||
func (g *generator) getDocComment(op *ast.OperationDefinition) string {
|
||||
var commentLines []string
|
||||
var sourceLines = strings.Split(op.Position.Src.Input, "\n")
|
||||
sourceLines := strings.Split(op.Position.Src.Input, "\n")
|
||||
for i := op.Position.Line - 1; i > 0; i-- {
|
||||
line := sourceLines[i-1]
|
||||
if strings.HasPrefix(line, "#") {
|
||||
|
||||
@@ -11,9 +11,6 @@ import (
|
||||
)
|
||||
|
||||
func getSchema(filename string) (*ast.Schema, error) {
|
||||
// TODO: IRL we have to get the schema from GraphQL (maybe we can generate
|
||||
// that once we can bootstrap) where it comes as JSON, not SDL, so we have
|
||||
// to convert (or add gqlparser support to convert)
|
||||
text, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unreadable schema file %v: %v", filename, err)
|
||||
|
||||
@@ -7,8 +7,11 @@ import (
|
||||
)
|
||||
|
||||
// TODO: package templates into the binary using one of those asset thingies
|
||||
var _, thisFilename, _, _ = runtime.Caller(0)
|
||||
var thisDir = filepath.Dir(thisFilename)
|
||||
// (e.g. embed, if we wait until 1.16 to do this)
|
||||
var (
|
||||
_, thisFilename, _, _ = runtime.Caller(0)
|
||||
thisDir = filepath.Dir(thisFilename)
|
||||
)
|
||||
|
||||
func mustTemplate(relFilename string) *template.Template {
|
||||
return template.Must(template.ParseFiles(filepath.Join(thisDir, relFilename)))
|
||||
|
||||
+14
-18
@@ -29,12 +29,11 @@ func (g *generator) baseTypeForOperation(operation ast.Operation) *ast.Definitio
|
||||
|
||||
func (g *generator) getTypeForOperation(operation *ast.OperationDefinition) (name string, err error) {
|
||||
// TODO: configure ResponseName format
|
||||
namePrefix := upperFirst(operation.Name)
|
||||
name = namePrefix + "Response"
|
||||
name = operation.Name + "Response"
|
||||
|
||||
if def, ok := g.typeMap[name]; ok {
|
||||
// TODO: check for and handle conflicts a better way
|
||||
return "", fmt.Errorf("%s already defined:\n%s", name, def)
|
||||
return "", fmt.Errorf("%s defined twice:\n%s", name, def)
|
||||
}
|
||||
|
||||
fields, err := selections(operation.SelectionSet)
|
||||
@@ -43,15 +42,16 @@ func (g *generator) getTypeForOperation(operation *ast.OperationDefinition) (nam
|
||||
}
|
||||
|
||||
return g.addTypeForDefinition(
|
||||
namePrefix, name, g.baseTypeForOperation(operation.Operation), fields)
|
||||
operation.Name, name, g.baseTypeForOperation(operation.Operation), fields)
|
||||
}
|
||||
|
||||
var builtinTypes = map[string]string{
|
||||
"Int": "int", // TODO: technically int32 is always enough, use that?
|
||||
// GraphQL guarantees int32 is enough, but using int seems more idiomatic
|
||||
"Int": "int",
|
||||
"Float": "float64",
|
||||
"String": "string",
|
||||
"Boolean": "bool",
|
||||
"ID": "string", // TODO: named type for IDs?
|
||||
"ID": "string",
|
||||
}
|
||||
|
||||
func (g *generator) addTypeForDefinition(namePrefix, nameOverride string, typ *ast.Definition, fields []field) (name string, err error) {
|
||||
@@ -117,11 +117,9 @@ type field interface {
|
||||
type outputField struct{ field *ast.Field }
|
||||
|
||||
func (s outputField) Alias() string {
|
||||
if s.field.Alias != "" {
|
||||
return s.field.Alias
|
||||
}
|
||||
// TODO: is this case needed? tests don't seem to get here.
|
||||
return s.field.Name
|
||||
// gqlparser sets Alias even if the field is not aliased, see e.g.
|
||||
// https://github.com/vektah/gqlparser/blob/c06d8e0d135f285e37e7f1ff397f10e049733eb3/parser/query.go#L150
|
||||
return s.field.Alias
|
||||
}
|
||||
|
||||
func (s outputField) Type() *ast.Type {
|
||||
@@ -192,11 +190,11 @@ func (builder *typeBuilder) writeField(field field) error {
|
||||
}
|
||||
|
||||
err = builder.writeType(
|
||||
// Note we don't deduplicate here -- if our prefix is GetUser and the
|
||||
// field name is User, we do GetUserUser. This is important because if
|
||||
// you have a field called user on a type called User we need
|
||||
// `query q { user { user { id } } }` to generate two types, QUser and
|
||||
// QUserUser.
|
||||
// Note we don't deduplicate suffixes here -- if our prefix is GetUser
|
||||
// and the field name is User, we do GetUserUser. This is important
|
||||
// because if you have a field called user on a type called User we
|
||||
// need `query q { user { user { id } } }` to generate two types, QUser
|
||||
// and QUserUser.
|
||||
// Note also this is the alias, not the field-name, because if we have
|
||||
// `query q { a: f { b }, c: f { d } }` we need separate types for a
|
||||
// and c, even though they are the same type in GraphQL, because they
|
||||
@@ -273,7 +271,6 @@ func (builder *typeBuilder) writeTypedef(typedef *ast.Definition, fields []field
|
||||
return err
|
||||
}
|
||||
|
||||
// HACK HACK HACK
|
||||
builder.typeMap[name] += fmt.Sprintf(
|
||||
"\nfunc (v %v) %v() {}", name, implementsMethodName)
|
||||
}
|
||||
@@ -285,7 +282,6 @@ func (builder *typeBuilder) writeTypedef(typedef *ast.Definition, fields []field
|
||||
builder.WriteString("string\n")
|
||||
builder.WriteString("const (\n")
|
||||
for _, val := range typedef.EnumValues {
|
||||
// TODO: casing should be configurable
|
||||
fmt.Fprintf(builder, "%s %s = \"%s\"\n",
|
||||
builder.typeNamePrefix+goConstName(val.Name),
|
||||
builder.typeName, val.Name)
|
||||
|
||||
@@ -33,7 +33,7 @@ func (builder *typeBuilder) maybeWriteUnmarshal(fields []field) error {
|
||||
for _, typedef := range builder.schema.GetPossibleTypes(typedef) {
|
||||
fieldInfo.ConcreteTypes = append(fieldInfo.ConcreteTypes,
|
||||
concreteType{
|
||||
// TODO: this is quite fragile (and maybe wrong if the
|
||||
// TODO: this is quite fragile (and wrong if the
|
||||
// field name + type name are the same)
|
||||
GoName: builder.typeNamePrefix + fieldInfo.GoName + upperFirst(typedef.Name),
|
||||
GraphQLName: typedef.Name,
|
||||
|
||||
Reference in New Issue
Block a user