Skip to content

Commit

Permalink
add options as anonymous struct
Browse files Browse the repository at this point in the history
  • Loading branch information
cyberdelia committed Mar 7, 2014
1 parent 9099c40 commit fa18dae
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 127 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
cover.out

schematic
133 changes: 14 additions & 119 deletions schema/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,11 @@ import (
bundle "github.com/heroku/schematic/schema/templates"
"go/format"
"regexp"
"strings"
"text/template"
"unicode"
"unicode/utf8"
)

var templates = template.New("package.tmpl").Funcs(helpers)

var helpers = template.FuncMap{
"initialCap": initialCap,
"initialLow": initialLow,
"methodCap": methodCap,
"validIdentifer": validIdentifer,
"asComment": asComment,
"jsonTag": jsonTag,
"params": params,
"args": args,
"join": join,
}

var (
newlines = regexp.MustCompile(`(?m:\s*$)`)
acronyms = regexp.MustCompile(`(?m)(Url|Http|Id|Uuid|Api|Uri|Ssl|Cname|Oauth)`)
Expand Down Expand Up @@ -124,6 +109,10 @@ func (s *Schema) GoType(p *Schema) string {
case "array":
return "[]" + s.GoType(prop.Items)
case "object":
// Check if additionalProperties is false.
if m, ok := prop.AdditionalProperties.(bool); ok && !m {
return "map[string]string"
}
var buf bytes.Buffer
templates.ExecuteTemplate(&buf, "astruct.tmpl", struct {
Definition *Schema
Expand All @@ -148,9 +137,16 @@ func (s *Schema) Parameters(l *Link) map[string]string {
for name, def := range l.HRef.Resolve(s) {
params[name] = s.GoType(def)
}
switch l.Rel {
case "update", "create":
params["options"] = l.GoType(s)
case "instances":
params["r"] = "*ListRange"
}
return params
}

// Return function return values types.
func (s *Schema) Values(name string, l *Link) []string {
var values []string
name = initialCap(name)
Expand All @@ -165,108 +161,7 @@ func (s *Schema) Values(name string, l *Link) []string {
return values
}

func jsonTag(n string, def *Schema) string {
tags := []string{n}
if !contains(n, def.Required) {
tags = append(tags, "omitempty")
}
return fmt.Sprintf("`json:\"%s\"`", strings.Join(tags, ","))
}

func contains(n string, r []string) bool {
for _, r := range r {
if r == n {
return true
}
}
return false
}

func initialCap(ident string) string {
if ident == "" {
panic("blank identifier")
}
return depunct(ident, true)
}

func methodCap(ident string) string {
return initialCap(strings.ToLower(ident))
}

func initialLow(ident string) string {
capitalize := initialCap(ident)
r, n := utf8.DecodeRuneInString(capitalize)
return string(unicode.ToLower(r)) + capitalize[n:]
}

func validIdentifer(ident string) string {
return depunct(ident, false)
}

func depunct(ident string, needCap bool) string {
var buf bytes.Buffer
for _, c := range ident {
if c == '-' || c == '.' || c == '$' || c == '/' || c == ':' || c == '_' || c == ' ' || c == '{' || c == '}' {
needCap = true
continue
}
if needCap {
c = unicode.ToUpper(c)
needCap = false
}
buf.WriteByte(byte(c))
}
depuncted := acronyms.ReplaceAllFunc(buf.Bytes(), func(m []byte) []byte {
if len(m) > 4 {
return append(bytes.ToUpper(m[:2]), m[2:]...)
}
return bytes.ToUpper(m)
})
return string(depuncted)
}

func asComment(c string) string {
var buf bytes.Buffer
const maxLen = 70
removeNewlines := func(s string) string {
return strings.Replace(s, "\n", "\n// ", -1)
}
for len(c) > 0 {
line := c
if len(line) < maxLen {
fmt.Fprintf(&buf, "// %s\n", removeNewlines(line))
break
}
line = line[:maxLen]
si := strings.LastIndex(line, " ")
if si != -1 {
line = line[:si]
}
fmt.Fprintf(&buf, "// %s\n", removeNewlines(line))
c = c[len(line):]
if si != -1 {
c = c[1:]
}
}
return buf.String()
}

func join(p []string) string {
return strings.Join(p, ",")
}

func params(m map[string]string) string {
var p []string
for k, v := range m {
p = append(p, fmt.Sprintf("%s %s", k, v))
}
return strings.Join(p, ",")
}

func args(m map[string]*Schema) string {
var p []string
for k, _ := range m {
p = append(p, k)
}
return strings.Join(p, ", ")
func (l *Link) GoType(r *Schema) string {
// FIXME: Arguments are reverse from Schema.GoType()
return r.GoType(l.Schema)
}
128 changes: 128 additions & 0 deletions schema/helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package schema

import (
"bytes"
"fmt"
"strings"
"text/template"
"unicode"
"unicode/utf8"
)

var helpers = template.FuncMap{
"initialCap": initialCap,
"initialLow": initialLow,
"methodCap": methodCap,
"validIdentifer": validIdentifer,
"asComment": asComment,
"jsonTag": jsonTag,
"params": params,
"args": args,
"join": join,
}

func jsonTag(n string, def *Schema) string {
tags := []string{n}
if !contains(n, def.Required) {
tags = append(tags, "omitempty")
}
return fmt.Sprintf("`json:\"%s\"`", strings.Join(tags, ","))
}

func contains(n string, r []string) bool {
for _, r := range r {
if r == n {
return true
}
}
return false
}

func initialCap(ident string) string {
if ident == "" {
panic("blank identifier")
}
return depunct(ident, true)
}

func methodCap(ident string) string {
return initialCap(strings.ToLower(ident))
}

func initialLow(ident string) string {
capitalize := initialCap(ident)
r, n := utf8.DecodeRuneInString(capitalize)
return string(unicode.ToLower(r)) + capitalize[n:]
}

func validIdentifer(ident string) string {
return depunct(ident, false)
}

func depunct(ident string, needCap bool) string {
var buf bytes.Buffer
for _, c := range ident {
if c == '-' || c == '.' || c == '$' || c == '/' || c == ':' || c == '_' || c == ' ' || c == '{' || c == '}' {
needCap = true
continue
}
if needCap {
c = unicode.ToUpper(c)
needCap = false
}
buf.WriteByte(byte(c))
}
depuncted := acronyms.ReplaceAllFunc(buf.Bytes(), func(m []byte) []byte {
if len(m) > 4 {
return append(bytes.ToUpper(m[:2]), m[2:]...)
}
return bytes.ToUpper(m)
})
return string(depuncted)
}

func asComment(c string) string {
var buf bytes.Buffer
const maxLen = 70
removeNewlines := func(s string) string {
return strings.Replace(s, "\n", "\n// ", -1)
}
for len(c) > 0 {
line := c
if len(line) < maxLen {
fmt.Fprintf(&buf, "// %s\n", removeNewlines(line))
break
}
line = line[:maxLen]
si := strings.LastIndex(line, " ")
if si != -1 {
line = line[:si]
}
fmt.Fprintf(&buf, "// %s\n", removeNewlines(line))
c = c[len(line):]
if si != -1 {
c = c[1:]
}
}
return buf.String()
}

func join(p []string) string {
return strings.Join(p, ",")
}

func params(m map[string]string) string {
var p []string
for k, v := range m {
p = append(p, fmt.Sprintf("%s %s", k, v))
}
return strings.Join(p, ",")
}

func args(m map[string]*Schema) string {
var p []string
for k, _ := range m {
p = append(p, k)
}
return strings.Join(p, ", ")
}
8 changes: 6 additions & 2 deletions schema/templates/funcs.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@
func (c *Client) {{printf "%s-%s" $Name .Title | initialCap}}({{$Root.Parameters . | params}}) ({{$Root.Values $Name . | join}}) {
{{if eq .Rel "destroy"}}
return c.Delete(fmt.Sprintf("{{.HRef}}", {{.HRef.Resolve $Root | args}}))
{{else if eq .Rel "self"}}
{{$Var := initialLow $Name}}var {{$Var}} {{initialCap $Name}}
return &{{$Var}}, c.Get(&{{$Var}}, fmt.Sprintf("{{.HRef}}", {{.HRef.Resolve $Root | args}}))
{{else if eq .Rel "instances"}}
{{$Var := printf "%s-%s" $Name "List" | initialLow}}
var {{$Var}} []*{{initialCap $Name}}
return {{$Var}}, c.{{methodCap .Method}}(&{{$Var}}, fmt.Sprintf("{{.HRef}}", {{.HRef.Resolve $Root | args}}))
{{else}}
{{$Var := initialLow $Name}}var {{$Var}} {{initialCap $Name}}
return &{{$Var}}, c.{{methodCap .Method}}(&{{$Var}}, fmt.Sprintf("{{.HRef}}", {{.HRef.Resolve $Root | args}}))
return &{{$Var}}, c.{{methodCap .Method}}(&{{$Var}}, fmt.Sprintf("{{.HRef}}", {{.HRef.Resolve $Root | args}}), options)
{{end}}
}
{{end}}
{{end}}

2 changes: 1 addition & 1 deletion schema/templates/struct.tmpl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{{if .Definition.Properties}}
{{asComment .Definition.Description}}
type {{initialCap .Name}} {{template "astruct.tmpl" .}}
{{end}}
{{end}}
13 changes: 9 additions & 4 deletions schema/templates/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,21 @@ var templates = map[string]string{"astruct.tmpl": `{{$Root := .Root}} struct {
func (c *Client) {{printf "%s-%s" $Name .Title | initialCap}}({{$Root.Parameters . | params}}) ({{$Root.Values $Name . | join}}) {
{{if eq .Rel "destroy"}}
return c.Delete(fmt.Sprintf("{{.HRef}}", {{.HRef.Resolve $Root | args}}))
{{else if eq .Rel "self"}}
{{$Var := initialLow $Name}}var {{$Var}} {{initialCap $Name}}
return &{{$Var}}, c.Get(&{{$Var}}, fmt.Sprintf("{{.HRef}}", {{.HRef.Resolve $Root | args}}))
{{else if eq .Rel "instances"}}
{{$Var := printf "%s-%s" $Name "List" | initialLow}}
var {{$Var}} []*{{initialCap $Name}}
return {{$Var}}, c.{{methodCap .Method}}(&{{$Var}}, fmt.Sprintf("{{.HRef}}", {{.HRef.Resolve $Root | args}}))
{{else}}
{{$Var := initialLow $Name}}var {{$Var}} {{initialCap $Name}}
return &{{$Var}}, c.{{methodCap .Method}}(&{{$Var}}, fmt.Sprintf("{{.HRef}}", {{.HRef.Resolve $Root | args}}))
return &{{$Var}}, c.{{methodCap .Method}}(&{{$Var}}, fmt.Sprintf("{{.HRef}}", {{.HRef.Resolve $Root | args}}), options)
{{end}}
}
{{end}}`,
{{end}}
`,
"imports.tmpl": `{{if .}}
{{if len . | eq 1}}
import {{range .}}"{{.}}"{{end}}
Expand All @@ -40,7 +45,8 @@ var templates = map[string]string{"astruct.tmpl": `{{$Root := .Root}} struct {
"struct.tmpl": `{{if .Definition.Properties}}
{{asComment .Definition.Description}}
type {{initialCap .Name}} {{template "astruct.tmpl" .}}
{{end}}`,
{{end}}
`,
}

func Parse(t *template.Template) (*template.Template, error) {
Expand All @@ -60,4 +66,3 @@ func Parse(t *template.Template) (*template.Template, error) {
}
return t, nil
}

0 comments on commit fa18dae

Please sign in to comment.