diff --git a/example/generated.go b/example/generated.go index 3bbd2e9..4670770 100644 --- a/example/generated.go +++ b/example/generated.go @@ -14,7 +14,6 @@ type getViewerResponse = struct { } `json:"viewer"` } -// TODO func getViewer(ctx context.Context, client *graphql.Client) (*getViewerResponse, error) { var retval getViewerResponse err := client.MakeRequest(ctx, ` @@ -33,7 +32,7 @@ type getUserResponse = struct { } `json:"user"` } -// TODO +// getUser gets the given user's name from their username. func getUser(ctx context.Context, client *graphql.Client, login string) (*getUserResponse, error) { variables := map[string]interface{}{ "login": login, diff --git a/example/queries.graphql b/example/queries.graphql index 9bd5f81..3237e43 100644 --- a/example/queries.graphql +++ b/example/queries.graphql @@ -1,11 +1,10 @@ -# getViewer gets the current user's name. query getViewer { viewer { MyName: name } } -# getUser gets the given user's name. +# getUser gets the given user's name from their username. query getUser($login: String!) { user(login: $login) { theirName: name diff --git a/generate/generate.go b/generate/generate.go index 407818f..cbf74a5 100644 --- a/generate/generate.go +++ b/generate/generate.go @@ -60,11 +60,35 @@ func fromASTArg(arg *ast.VariableDefinition, schema *ast.Schema) argument { } } +func reverse(slice []string) { + for left, right := 0, len(slice)-1; left < right; left, right = left+1, right-1 { + slice[left], slice[right] = slice[right], slice[left] + } +} + +func getDocComment(op *ast.OperationDefinition) string { + var commentLines []string + var 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, "#") { + commentLines = append(commentLines, + "// "+strings.TrimSpace(strings.TrimPrefix(line, "#"))) + } else { + break + } + } + + reverse(commentLines) + + return strings.Join(commentLines, "\n") +} + func fromASTOperation(op *ast.OperationDefinition, schema *ast.Schema) (operation, error) { // TODO: we may have to actually get the precise query text, in case we - // want to be hashing it or something like that. Although maybe - // there's no reasonable way to do that with several queries in one - // file. + // want to be hashing it or something like that. This is a bit tricky + // because gqlparser's ast doesn't provide node end-position (only + // token end-position). var builder strings.Builder f := formatter.NewFormatter(&builder) f.FormatQueryDocument(&ast.QueryDocument{ @@ -85,10 +109,7 @@ func fromASTOperation(op *ast.OperationDefinition, schema *ast.Schema) (operatio return operation{ Type: op.Operation, Name: op.Name, - // TODO: this is actually awkward, because GraphQL doesn't allow - // for docstrings on queries (only schemas). So we have to extract - // the comment, or omit doc-comments for now. - Doc: "TODO", + Doc: getDocComment(op), // The newline just makes it format a little nicer Body: "\n" + builder.String(), Args: args, @@ -130,9 +151,11 @@ func Generate(config *Config) ([]byte, error) { return nil, fmt.Errorf("could not render template: %v", err) } - formatted, err := format.Source(buf.Bytes()) + unformatted := buf.Bytes() + formatted, err := format.Source(unformatted) if err != nil { - return nil, fmt.Errorf("could not gofmt template: %v", err) + return nil, fmt.Errorf("could not gofmt code: %v\n---unformatted code---\n%v", + err, string(unformatted)) } return formatted, nil diff --git a/generate/main.go b/generate/main.go index 764388e..6c8d61f 100644 --- a/generate/main.go +++ b/generate/main.go @@ -11,17 +11,18 @@ func readConfigGenerateAndWrite(configFilename string) error { return err } + code, err := Generate(config) + if err != nil { + return err + } + + // Open out at the end -- decreases the chances we blank it if we err. out, err := os.OpenFile(config.Generated, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) if err != nil { return fmt.Errorf("could not open generated file %v: %v", config.Generated, err) } - code, err := Generate(config) - if err != nil { - return err - } - _, err = out.Write(code) return err } diff --git a/generate/operation.go.tmpl b/generate/operation.go.tmpl index 1a46a13..881c00d 100644 --- a/generate/operation.go.tmpl +++ b/generate/operation.go.tmpl @@ -11,7 +11,7 @@ import ( {{range .Operations}} type {{.ResponseName}} = {{.ResponseType}} -// {{.Doc}} +{{.Doc}} func {{.Name}}(ctx context.Context, client *graphql.Client{{range .Args}}, {{.GoName}} {{.GoType}}{{end}}) (*{{.ResponseName}}, error) { {{- if .Args -}} variables := map[string]interface{}{