Merge pull request #15 from wttw/master

add -trimprefix and -autotrimprefix
This commit is contained in:
Álvaro López Espinosa 2018-02-06 12:04:43 +00:00 committed by GitHub
commit 644919b7e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 64 additions and 11 deletions

View File

@ -104,10 +104,14 @@ the JSON related methods will be generated. Similarly if the yaml flag is set to
the YAML related methods will be generated. And if the sql flag is set to true, the Scanner and Valuer interface will
be implemented to seamlessly use the enum in a database model.
For enum string representation transformation `transform` flag was added (i.e. `enumer -type=MyType -json -transform=snake`).
Possible values are `snake` and `kebab` for transformation to snake_case and kebab-case accordingly.
For enum string representation transformation the `transform` and `trimprefix` flags
were added (i.e. `enumer -type=MyType -json -transform=snake`).
Possible transform values are `snake` and `kebab` for transformation to snake_case and kebab-case accordingly.
The default value for `transform` flag is `noop` which means no transformation will be performed.
If a prefix is provided via the `trimprefix` flag that will be trimmed from the start of each name (before
it is transformed). If a name doesn't have the prefix it will be passed unchanged.
## Inspiring projects
* [Stringer](https://godoc.org/golang.org/x/tools/cmd/stringer)
* [jsonenums](https://github.com/campoy/jsonenums)

View File

@ -46,6 +46,10 @@ var goldenJSONAndSQL = []Golden{
{"prime", prime_json_and_sql_in, prime_json_and_sql_out},
}
var goldenPrefix = []Golden{
{"prefix", prefix_in, day_out},
}
// Each example starts with "type XXX [u]int", with a single space separating them.
// Simple test: enumeration of type int starting at 0.
@ -83,6 +87,8 @@ var _DayNameToValueMap = map[string]Day{
_DayName[44:50]: 6,
}
// DayString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func DayString(s string) (Day, error) {
if val, ok := _DayNameToValueMap[s]; ok {
return val, nil
@ -122,6 +128,8 @@ var _NumberNameToValueMap = map[string]Number{
_NumberName[6:11]: 3,
}
// NumberString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func NumberString(s string) (Number, error) {
if val, ok := _NumberNameToValueMap[s]; ok {
return val, nil
@ -183,6 +191,8 @@ var _GapNameToValueMap = map[string]Gap{
_GapName_2[0:6]: 11,
}
// GapString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func GapString(s string) (Gap, error) {
if val, ok := _GapNameToValueMap[s]; ok {
return val, nil
@ -223,6 +233,8 @@ var _NumNameToValueMap = map[string]Num{
_NumName[10:12]: 2,
}
// NumString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func NumString(s string) (Num, error) {
if val, ok := _NumNameToValueMap[s]; ok {
return val, nil
@ -276,6 +288,8 @@ var _UnumNameToValueMap = map[string]Unum{
_UnumName_1[3:6]: 254,
}
// UnumString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func UnumString(s string) (Unum, error) {
if val, ok := _UnumNameToValueMap[s]; ok {
return val, nil
@ -347,6 +361,8 @@ var _PrimeNameToValueMap = map[string]Prime{
_PrimeName[32:35]: 43,
}
// PrimeString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func PrimeString(s string) (Prime, error) {
if val, ok := _PrimeNameToValueMap[s]; ok {
return val, nil
@ -415,6 +431,8 @@ var _PrimeNameToValueMap = map[string]Prime{
_PrimeName[32:35]: 43,
}
// PrimeString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func PrimeString(s string) (Prime, error) {
if val, ok := _PrimeNameToValueMap[s]; ok {
return val, nil
@ -499,6 +517,8 @@ var _PrimeNameToValueMap = map[string]Prime{
_PrimeName[32:35]: 43,
}
// PrimeString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func PrimeString(s string) (Prime, error) {
if val, ok := _PrimeNameToValueMap[s]; ok {
return val, nil
@ -583,6 +603,8 @@ var _PrimeNameToValueMap = map[string]Prime{
_PrimeName[32:35]: 43,
}
// PrimeString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func PrimeString(s string) (Prime, error) {
if val, ok := _PrimeNameToValueMap[s]; ok {
return val, nil
@ -680,6 +702,8 @@ var _PrimeNameToValueMap = map[string]Prime{
_PrimeName[32:35]: 43,
}
// PrimeString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func PrimeString(s string) (Prime, error) {
if val, ok := _PrimeNameToValueMap[s]; ok {
return val, nil
@ -731,25 +755,40 @@ func (i *Prime) Scan(value interface{}) error {
}
`
const prefix_in = `type Day int
const (
DayMonday Day = iota
DayTuesday
DayWednesday
DayThursday
DayFriday
DaySaturday
DaySunday
)
`
func TestGolden(t *testing.T) {
for _, test := range golden {
runGoldenTest(t, test, false, false, false)
runGoldenTest(t, test, false, false, false, "")
}
for _, test := range goldenJSON {
runGoldenTest(t, test, true, false, false)
runGoldenTest(t, test, true, false, false, "")
}
for _, test := range goldenYAML {
runGoldenTest(t, test, false, true, false)
runGoldenTest(t, test, false, true, false, "")
}
for _, test := range goldenSQL {
runGoldenTest(t, test, false, false, true)
runGoldenTest(t, test, false, false, true, "")
}
for _, test := range goldenJSONAndSQL {
runGoldenTest(t, test, true, false, true)
runGoldenTest(t, test, true, false, true, "")
}
for _, test := range goldenPrefix {
runGoldenTest(t, test, false, false, false, "Day")
}
}
func runGoldenTest(t *testing.T, test Golden, generateJSON, generateYAML, generateSQL bool) {
func runGoldenTest(t *testing.T, test Golden, generateJSON, generateYAML, generateSQL bool, prefix string) {
var g Generator
input := "package test\n" + test.input
file := test.name + ".go"
@ -759,7 +798,7 @@ func runGoldenTest(t *testing.T, test Golden, generateJSON, generateYAML, genera
if len(tokens) != 3 {
t.Fatalf("%s: need type declaration on first line", test.name)
}
g.generate(tokens[1], generateJSON, generateYAML, generateSQL, "noop")
g.generate(tokens[1], generateJSON, generateYAML, generateSQL, "noop", prefix)
got := string(g.format())
if got != test.output {
t.Errorf("%s: got\n====\n%s====\nexpected\n====%s", test.name, got, test.output)

View File

@ -93,6 +93,7 @@ var (
yaml = flag.Bool("yaml", false, "if true, yaml marshaling methods will be generated. Default: false")
output = flag.String("output", "", "output file name; default srcdir/<type>_string.go")
transformMethod = flag.String("transform", "noop", "enum item name transformation method. Default: noop")
trimPrefix = flag.String("trimprefix", "", "transform each item name by removing a prefix. Default: \"\"")
)
// Usage is a replacement usage function for the flags package.
@ -155,7 +156,7 @@ func main() {
// Run generate for each type.
for _, typeName := range types {
g.generate(typeName, *json, *yaml, *sql, *transformMethod)
g.generate(typeName, *json, *yaml, *sql, *transformMethod, *trimPrefix)
}
// Format the output.
@ -306,8 +307,15 @@ func (g *Generator) transformValueNames(values []Value, transformMethod string)
}
}
// trimValueNames removes a prefix from each name
func (g *Generator) trimValueNames(values []Value, prefix string) {
for i := range values {
values[i].name = strings.TrimPrefix(values[i].name, prefix)
}
}
// generate produces the String method for the named type.
func (g *Generator) generate(typeName string, includeJSON, includeYAML, includeSQL bool, transformMethod string) {
func (g *Generator) generate(typeName string, includeJSON, includeYAML, includeSQL bool, transformMethod string, trimPrefix string) {
values := make([]Value, 0, 100)
for _, file := range g.pkg.files {
// Set the state for this run of the walker.
@ -323,6 +331,8 @@ func (g *Generator) generate(typeName string, includeJSON, includeYAML, includeS
log.Fatalf("no values defined for type %s", typeName)
}
g.trimValueNames(values, trimPrefix)
g.transformValueNames(values, transformMethod)
runs := splitIntoRuns(values)