From 5300f83da08d6eafc717e1edf15960a25ff033ca Mon Sep 17 00:00:00 2001 From: Bernerd Schaefer Date: Mon, 12 Oct 2020 12:12:10 -0700 Subject: [PATCH] Handle properties with question marks The heroku schema now includes the `ca_signed?` and `self_signed?` properties which schematic attempts to turn into this code which doesn't compile: type SSLCert struct { ... CaSigned? string `json:"ca_signed?"` } This updates the Go field name generation to turn `foo?` schema properties into `IsFoo` struct fields to match Go's idioms. --- cmd/schematic/schematic.go | 1 + helpers.go | 11 ++++++++ helpers_test.go | 53 +++++++++++++++++++++++++++----------- templates/templates.go | 3 +-- 4 files changed, 51 insertions(+), 17 deletions(-) diff --git a/cmd/schematic/schematic.go b/cmd/schematic/schematic.go index fd89f90..eb411e4 100644 --- a/cmd/schematic/schematic.go +++ b/cmd/schematic/schematic.go @@ -70,6 +70,7 @@ func main() { code, err := s.Generate() if err != nil { + fmt.Fprintf(os.Stderr, "%s\n", code) log.Fatal(err) } diff --git a/helpers.go b/helpers.go index 43be6d1..c3ddd9f 100644 --- a/helpers.go +++ b/helpers.go @@ -16,6 +16,7 @@ var helpers = template.FuncMap{ "initialLow": initialLow, "methodCap": methodCap, "asComment": asComment, + "fieldName": fieldName, "fieldTag": fieldTag, "params": params, "requestParams": requestParams, @@ -51,6 +52,16 @@ func fieldTag(n string, required bool) string { return fmt.Sprintf("`%s %s`", jsonTag(n, required), urlTag(n, required)) } +func fieldName(name string) string { + fieldName := initialCap(name) + + if strings.HasSuffix(name, "?") { + fieldName = "Is" + strings.TrimSuffix(fieldName, "?") + } + + return fieldName +} + func jsonTag(n string, required bool) string { tags := []string{n} if !required { diff --git a/helpers_test.go b/helpers_test.go index 2df3532..d583e36 100644 --- a/helpers_test.go +++ b/helpers_test.go @@ -3,40 +3,63 @@ package schematic import "testing" var initialCapTests = []struct { - Ident string - Depuncted string + In string + Out string }{ { - Ident: "provider_id", - Depuncted: "ProviderID", + In: "provider_id", + Out: "ProviderID", }, { - Ident: "app-identity", - Depuncted: "AppIdentity", + In: "app-identity", + Out: "AppIdentity", }, { - Ident: "uuid", - Depuncted: "UUID", + In: "uuid", + Out: "UUID", }, { - Ident: "oauth-client", - Depuncted: "OAuthClient", + In: "oauth-client", + Out: "OAuthClient", }, { - Ident: "Dyno all", - Depuncted: "DynoAll", + In: "Dyno all", + Out: "DynoAll", }, } func TestInitialCap(t *testing.T) { for i, ict := range initialCapTests { - depuncted := depunct(ict.Ident, true) - if depuncted != ict.Depuncted { - t.Errorf("%d: wants %v, got %v", i, ict.Depuncted, depuncted) + depuncted := depunct(ict.In, true) + if depuncted != ict.Out { + t.Errorf("%d: wants %v, got %v", i, ict.Out, depuncted) } } } +var fieldNameTests = append([]struct { + In string + Out string +}{ + { + In: "ca_signed?", + Out: "IsCaSigned", + }, +}, + initialCapTests..., +) + +func TestFieldName(t *testing.T) { + for _, tt := range fieldNameTests { + t.Run(tt.In, func(t *testing.T) { + got := fieldName(tt.In) + if got != tt.Out { + t.Fatalf("got %q want %q", got, tt.Out) + } + }) + } +} + var asCommentTests = []struct { Comment string Commented string diff --git a/templates/templates.go b/templates/templates.go index 19c5e4a..4b5b6ec 100644 --- a/templates/templates.go +++ b/templates/templates.go @@ -2,7 +2,7 @@ package templates import "text/template" -var templates = map[string]string{"field.tmpl": `{{initialCap .Name}} {{.Type}} {{fieldTag .Name .Required}} {{asComment .Definition.Description}} +var templates = map[string]string{"field.tmpl": `{{fieldName .Name}} {{.Type}} {{fieldTag .Name .Required}} {{asComment .Definition.Description}} `, "funcs.tmpl": `{{$Name := .Name}} {{$Def := .Definition}} @@ -265,4 +265,3 @@ func Parse(t *template.Template) (*template.Template, error) { } return t, nil } -