diff --git a/golden_test.go b/golden_test.go index 8144fc6..46740c7 100644 --- a/golden_test.go +++ b/golden_test.go @@ -34,28 +34,32 @@ var golden = []Golden{ } var goldenJSON = []Golden{ - {"prime", primeJsonIn, primeJsonOut}, + {"prime with JSON", primeJsonIn, primeJsonOut}, } var goldenText = []Golden{ - {"prime", primeTextIn, primeTextOut}, + {"prime with Text", primeTextIn, primeTextOut}, } var goldenYAML = []Golden{ - {"prime", primeYamlIn, primeYamlOut}, + {"prime with YAML", primeYamlIn, primeYamlOut}, } var goldenSQL = []Golden{ - {"prime", primeSqlIn, primeSqlOut}, + {"prime with SQL", primeSqlIn, primeSqlOut}, } var goldenJSONAndSQL = []Golden{ - {"prime", primeJsonAndSqlIn, primeJsonAndSqlOut}, + {"prime with JSONAndSQL", primeJsonAndSqlIn, primeJsonAndSqlOut}, } var goldenPrefix = []Golden{ {"prefix", prefixIn, dayOut}, } +var goldenWithLineComments = []Golden{ + {"primer with line Comments", primeWithLineCommentIn, primeWithLineCommentOut}, +} + // Each example starts with "type XXX [u]int", with a single space separating them. // Simple test: enumeration of type int starting at 0. @@ -1025,6 +1029,90 @@ const ( ) ` +const primeWithLineCommentIn = `type Prime int +const ( + p2 Prime = 2 + p3 Prime = 3 + p5 Prime = 5 + p7 Prime = 7 + p77 Prime = 7 // Duplicate; note that p77 doesn't appear below. + p11 Prime = 11 + p13 Prime = 13 + p17 Prime = 17 + p19 Prime = 19 + p23 Prime = 23 + p29 Prime = 29 + p37 Prime = 31 + p41 Prime = 41 + p43 Prime = 43 +) +` + +const primeWithLineCommentOut = ` +const _PrimeName = "p2p3GoodPrimep7p11p13p17p19p23p29p37TwinPrime41Twin prime 43" + +var _PrimeMap = map[Prime]string{ + 2: _PrimeName[0:2], + 3: _PrimeName[2:4], + 5: _PrimeName[4:13], + 7: _PrimeName[13:15], + 11: _PrimeName[15:18], + 13: _PrimeName[18:21], + 17: _PrimeName[21:24], + 19: _PrimeName[24:27], + 23: _PrimeName[27:30], + 29: _PrimeName[30:33], + 31: _PrimeName[33:36], + 41: _PrimeName[36:47], + 43: _PrimeName[47:60], +} + +func (i Prime) String() string { + if str, ok := _PrimeMap[i]; ok { + return str + } + return fmt.Sprintf("Prime(%d)", i) +} + +var _PrimeValues = []Prime{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 41, 43} + +var _PrimeNameToValueMap = map[string]Prime{ + _PrimeName[0:2]: 2, + _PrimeName[2:4]: 3, + _PrimeName[4:13]: 5, + _PrimeName[13:15]: 7, + _PrimeName[15:18]: 11, + _PrimeName[18:21]: 13, + _PrimeName[21:24]: 17, + _PrimeName[24:27]: 19, + _PrimeName[27:30]: 23, + _PrimeName[30:33]: 29, + _PrimeName[33:36]: 31, + _PrimeName[36:47]: 41, + _PrimeName[47:60]: 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 + } + return 0, fmt.Errorf("%s does not belong to Prime values", s) +} + +// PrimeValues returns all values of the enum +func PrimeValues() []Prime { + return _PrimeValues +} + +// IsAPrime returns "true" if the value is listed in the enum definition. "false" otherwise +func (i Prime) IsAPrime() bool { + _, ok := _PrimeMap[i] + return ok +} +` + func TestGolden(t *testing.T) { for _, test := range golden { runGoldenTest(t, test, false, false, false, false, "") @@ -1076,7 +1164,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, generateText, "noop", prefix) + g.generate(tokens[1], generateJSON, generateYAML, generateSQL, generateText, "noop", prefix, false) got := string(g.format()) if got != test.output { t.Errorf("%s: got\n====\n%s====\nexpected\n====%s", test.name, got, test.output) diff --git a/stringer.go b/stringer.go index 17c670b..26ff247 100644 --- a/stringer.go +++ b/stringer.go @@ -51,6 +51,7 @@ var ( output = flag.String("output", "", "output file name; default srcdir/_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: \"\"") + lineComment = flag.Bool("linecomment", false, "use line comment text as printed text when present") ) var comments arrayFlags @@ -120,7 +121,7 @@ func main() { // Run generate for each type. for _, typeName := range types { - g.generate(typeName, *json, *yaml, *sql, *text, *transformMethod, *trimPrefix) + g.generate(typeName, *json, *yaml, *sql, *text, *transformMethod, *trimPrefix, *lineComment) } // Format the output. @@ -331,8 +332,16 @@ func (g *Generator) trimValueNames(values []Value, prefix string) { } } +func (g *Generator) replaceValuesWithLineComment(values []Value) { + for i, val := range values { + if val.comment != "" { + values[i].name = val.comment + } + } +} + // generate produces the String method for the named type. -func (g *Generator) generate(typeName string, includeJSON, includeYAML, includeSQL, includeText bool, transformMethod string, trimPrefix string) { +func (g *Generator) generate(typeName string, includeJSON, includeYAML, includeSQL, includeText bool, transformMethod string, trimPrefix string, lineComment bool) { values := make([]Value, 0, 100) for _, file := range g.pkg.files { // Set the state for this run of the walker. @@ -352,6 +361,10 @@ func (g *Generator) generate(typeName string, includeJSON, includeYAML, includeS g.transformValueNames(values, transformMethod) + if lineComment { + g.replaceValuesWithLineComment(values) + } + runs := splitIntoRuns(values) // The decision of which pattern to use depends on the number of // runs in the numbers. If there's only one, it's easy. For more than @@ -443,9 +456,10 @@ type Value struct { // this matters is when sorting. // Much of the time the str field is all we need; it is printed // by Value.String. - value uint64 // Will be converted to int64 when needed. - signed bool // Whether the constant is a signed type. - str string // The string representation given by the "go/exact" package. + value uint64 // Will be converted to int64 when needed. + signed bool // Whether the constant is a signed type. + str string // The string representation given by the "go/exact" package. + comment string // The comment on the right of the constant } func (v *Value) String() string { @@ -530,11 +544,17 @@ func (f *File) genDecl(node ast.Node) bool { if !isInt { u64 = uint64(i64) } + comment := "" + if c := vspec.Comment; c != nil && len(c.List) == 1 { + comment = strings.TrimSpace(c.Text()) + } + v := Value{ - name: name.Name, - value: u64, - signed: info&types.IsUnsigned == 0, - str: value.String(), + name: name.Name, + value: u64, + signed: info&types.IsUnsigned == 0, + str: value.String(), + comment: comment, } f.values = append(f.values, v) } diff --git a/util_test.go b/util_test.go index fa50393..8dd35e2 100644 --- a/util_test.go +++ b/util_test.go @@ -54,7 +54,7 @@ Outer: for n, test := range splitTests { values := make([]Value, len(test.input)) for i, v := range test.input { - values[i] = Value{"", v, test.signed, fmt.Sprint(v)} + values[i] = Value{"", v, test.signed, fmt.Sprint(v), ""} } runs := splitIntoRuns(values) if len(runs) != len(test.output) {