Skip to content

Commit

Permalink
Initial pass at 99designs#2321
Browse files Browse the repository at this point in the history
  • Loading branch information
dcarbone committed Aug 12, 2022
1 parent 2304c10 commit 3de65d2
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 5 deletions.
113 changes: 113 additions & 0 deletions codegen/templates/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ import (
"os"
"path/filepath"
"reflect"
"regexp"
"runtime"
"sort"
"strconv"
"strings"
"sync"
"text/template"
"unicode"

Expand Down Expand Up @@ -202,6 +204,7 @@ func Funcs() template.FuncMap {
"lookupImport": CurrentImports.Lookup,
"go": ToGo,
"goPrivate": ToGoPrivate,
"goModelName": ToGoModelName,
"add": func(a, b int) int {
return a + b
},
Expand Down Expand Up @@ -291,6 +294,116 @@ func Call(p *types.Func) string {
return pkg + p.Name()
}

var (
modelNamesMu sync.Mutex
modelNames = make(map[string]string, 0)
)

func resetModelNames() {
modelNamesMu.Lock()
defer modelNamesMu.Unlock()
modelNames = make(map[string]string, 0)
}

func buildGoModelNameKey(parts []string) string {
const sep = ":"
return strings.Join(parts, sep)
}

func ToGoModelName(parts ...string) string {
modelNamesMu.Lock()
defer modelNamesMu.Unlock()

var (
goNameKey string
partLen int

nameExists = func(n string) bool {
for _, v := range modelNames {
if n == v {
return true
}
}
return false
}

applyToGo = func(parts []string) string {
var out string
for _, p := range parts {
out = fmt.Sprintf("%s%s", out, ToGo(p))
}
return out
}

applyValidGoName = func(parts []string) string {
var out string
for _, p := range parts {
out = fmt.Sprintf("%s%s", out, ValidGoName(p))
}
return out
}
)

// build key for this entity
goNameKey = buildGoModelNameKey(parts)

// determine if we've seen this entity before, and reuse if so
if goName, ok := modelNames[goNameKey]; ok {
return goName
}

// attempt first pass

// test first pass
if goName := applyToGo(parts); !nameExists(goName) {
modelNames[goNameKey] = goName
return goName
}

// determine number of parts
partLen = len(parts)

// if there is only 1 part, append incrementing number until no conflict
if partLen == 1 {
base := applyToGo(parts)
for i := 0; ; i++ {
tmp := fmt.Sprintf("%s%d", base, i)
if !nameExists(tmp) {
modelNames[goNameKey] = tmp
return tmp
}
}
}

// best effort "pretty" name
for i := partLen - 1; i >= 1; i-- {
tmp := fmt.Sprintf("%s%s", applyToGo(parts[0:i]), applyValidGoName(parts[i:]))
fmt.Println(i, tmp)
if !nameExists(tmp) {
modelNames[goNameKey] = tmp
return tmp
}
}

// finally, fallback to just adding an incrementing number
for i := 0; ; i++ {
base := applyToGo(parts)
tmp := fmt.Sprintf("%s%d", base, i)
if !nameExists(tmp) {
modelNames[goNameKey] = tmp
return tmp
}
}
}

var (
goNameRe = regexp.MustCompile("[^a-zA-Z0-9_]")
)

func ValidGoName(in string) string {
return goNameRe.ReplaceAllString(in, "_")
}

func ToGo(name string) string {
if name == "_" {
return "_"
Expand Down
39 changes: 38 additions & 1 deletion codegen/templates/templates_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,46 @@ func TestToGoPrivate(t *testing.T) {
require.Equal(t, "_", ToGoPrivate("_"))
}

func TestToGoModelName(t *testing.T) {
type aTest struct {
input [][]string
expected []string
}

theTests := []aTest{
{
input: [][]string{{"MyValue"}},
expected: []string{"MyValue"},
},
{
input: [][]string{{"MyValue"}, {"YourValue"}},
expected: []string{"MyValue", "YourValue"},
},
{
input: [][]string{{"MyEnumName", "Value"}},
expected: []string{"MyEnumNameValue"},
},
{
input: [][]string{{"MyEnumName", "Value"}, {"MyEnumName", "value"}},
expected: []string{"MyEnumNameValue", "MyEnumNamevalue"},
},
{
input: [][]string{{"MyEnumName", "Value"}, {"MyEnumName", "value"}, {"MyEnumName", "vALue"}},
expected: []string{"MyEnumNameValue", "MyEnumNamevalue", "MyEnumNamevALue"},
},
}

for _, at := range theTests {
resetModelNames()
for i, n := range at.input {
require.Equal(t, at.expected[i], ToGoModelName(n...))
}
}
}

func Test_wordWalker(t *testing.T) {
helper := func(str string) []*wordInfo {
resultList := []*wordInfo{}
var resultList []*wordInfo
wordWalker(str, func(info *wordInfo) {
resultList = append(resultList, info)
})
Expand Down
8 changes: 4 additions & 4 deletions plugin/modelgen/models.gotpl
Original file line number Diff line number Diff line change
Expand Up @@ -54,19 +54,19 @@

{{ range $enum := .Enums }}
{{ with .Description }} {{.|prefixLines "// "}} {{end}}
type {{.Name|go }} string
type {{.Name|goModelName }} string
const (
{{- range $value := .Values}}
{{- with .Description}}
{{.|prefixLines "// "}}
{{- end}}
{{ $enum.Name|go }}{{ .Name|go }} {{$enum.Name|go }} = {{.Name|quote}}
{{ goModelName $enum.Name .Name }} {{ $enum.Name|goModelName }} = {{ .Name|quote }}
{{- end }}
)

var All{{.Name|go }} = []{{ .Name|go }}{
var All{{ .Name|goModelName }} = []{{ .Name|goModelName }}{
{{- range $value := .Values}}
{{$enum.Name|go }}{{ .Name|go }},
{{ goModelName $enum.Name .Name }},
{{- end }}
}

Expand Down

0 comments on commit 3de65d2

Please sign in to comment.