cmd/stringer: add flag to use line comment as str
This can be very helpful if you lay out each value's string representation like this: and // & andAnd // && or // | orOr // || Without the use of comments, it's impossible to use stringer with these names as the characters & and | cannot form valid identifiers in a Go program. Fixes #20483. Change-Id: I4d36c74059dd48ae3a5e09b70a429a75853ef179 Reviewed-on: https://go-review.googlesource.com/44076 Run-TryBot: Daniel Martí <mvdan@mvdan.cc> Reviewed-by: Rob Pike <r@golang.org>
This commit is contained in:
parent
64890f4e2b
commit
ae8cc59455
|
@ -16,20 +16,22 @@ import (
|
|||
|
||||
// Golden represents a test case.
|
||||
type Golden struct {
|
||||
name string
|
||||
trimPrefix string
|
||||
input string // input; the package clause is provided when running the test.
|
||||
output string // exected output.
|
||||
name string
|
||||
trimPrefix string
|
||||
lineComment bool
|
||||
input string // input; the package clause is provided when running the test.
|
||||
output string // exected output.
|
||||
}
|
||||
|
||||
var golden = []Golden{
|
||||
{"day", "", day_in, day_out},
|
||||
{"offset", "", offset_in, offset_out},
|
||||
{"gap", "", gap_in, gap_out},
|
||||
{"num", "", num_in, num_out},
|
||||
{"unum", "", unum_in, unum_out},
|
||||
{"prime", "", prime_in, prime_out},
|
||||
{"prefix", "Type", prefix_in, prefix_out},
|
||||
{"day", "", false, day_in, day_out},
|
||||
{"offset", "", false, offset_in, offset_out},
|
||||
{"gap", "", false, gap_in, gap_out},
|
||||
{"num", "", false, num_in, num_out},
|
||||
{"unum", "", false, unum_in, unum_out},
|
||||
{"prime", "", false, prime_in, prime_out},
|
||||
{"prefix", "Type", false, prefix_in, prefix_out},
|
||||
{"tokens", "", true, tokens_in, tokens_out},
|
||||
}
|
||||
|
||||
// Each example starts with "type XXX [u]int", with a single space separating them.
|
||||
|
@ -264,9 +266,42 @@ func (i Type) String() string {
|
|||
}
|
||||
`
|
||||
|
||||
const tokens_in = `type Token int
|
||||
const (
|
||||
And Token = iota // &
|
||||
Or // |
|
||||
Add // +
|
||||
Sub // -
|
||||
Ident
|
||||
Period // .
|
||||
|
||||
// not to be used
|
||||
SingleBefore
|
||||
// not to be used
|
||||
BeforeAndInline // inline
|
||||
InlineGeneral /* inline general */
|
||||
)
|
||||
`
|
||||
|
||||
const tokens_out = `
|
||||
const _Token_name = "&|+-Ident.SingleBeforeinlineinline general"
|
||||
|
||||
var _Token_index = [...]uint8{0, 1, 2, 3, 4, 9, 10, 22, 28, 42}
|
||||
|
||||
func (i Token) String() string {
|
||||
if i < 0 || i >= Token(len(_Token_index)-1) {
|
||||
return "Token(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _Token_name[_Token_index[i]:_Token_index[i+1]]
|
||||
}
|
||||
`
|
||||
|
||||
func TestGolden(t *testing.T) {
|
||||
for _, test := range golden {
|
||||
g := Generator{trimPrefix: test.trimPrefix}
|
||||
g := Generator{
|
||||
trimPrefix: test.trimPrefix,
|
||||
lineComment: test.lineComment,
|
||||
}
|
||||
input := "package test\n" + test.input
|
||||
file := test.name + ".go"
|
||||
g.parsePackage(".", []string{file}, input)
|
||||
|
|
|
@ -78,9 +78,10 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
typeNames = flag.String("type", "", "comma-separated list of type names; must be set")
|
||||
output = flag.String("output", "", "output file name; default srcdir/<type>_string.go")
|
||||
trimprefix = flag.String("trimprefix", "", "trim the `prefix` from the generated constant names")
|
||||
typeNames = flag.String("type", "", "comma-separated list of type names; must be set")
|
||||
output = flag.String("output", "", "output file name; default srcdir/<type>_string.go")
|
||||
trimprefix = flag.String("trimprefix", "", "trim the `prefix` from the generated constant names")
|
||||
linecomment = flag.Bool("linecomment", false, "use line comment text as printed text when present")
|
||||
)
|
||||
|
||||
// Usage is a replacement usage function for the flags package.
|
||||
|
@ -114,7 +115,10 @@ func main() {
|
|||
|
||||
// Parse the package once.
|
||||
var dir string
|
||||
g := Generator{trimPrefix: *trimprefix}
|
||||
g := Generator{
|
||||
trimPrefix: *trimprefix,
|
||||
lineComment: *linecomment,
|
||||
}
|
||||
if len(args) == 1 && isDirectory(args[0]) {
|
||||
dir = args[0]
|
||||
g.parsePackageDir(args[0])
|
||||
|
@ -165,7 +169,8 @@ type Generator struct {
|
|||
buf bytes.Buffer // Accumulated output.
|
||||
pkg *Package // Package we are scanning.
|
||||
|
||||
trimPrefix string
|
||||
trimPrefix string
|
||||
lineComment bool
|
||||
}
|
||||
|
||||
func (g *Generator) Printf(format string, args ...interface{}) {
|
||||
|
@ -180,7 +185,8 @@ type File struct {
|
|||
typeName string // Name of the constant type.
|
||||
values []Value // Accumulator for constant values of that type.
|
||||
|
||||
trimPrefix string
|
||||
trimPrefix string
|
||||
lineComment bool
|
||||
}
|
||||
|
||||
type Package struct {
|
||||
|
@ -237,15 +243,16 @@ func (g *Generator) parsePackage(directory string, names []string, text interfac
|
|||
if !strings.HasSuffix(name, ".go") {
|
||||
continue
|
||||
}
|
||||
parsedFile, err := parser.ParseFile(fs, name, text, 0)
|
||||
parsedFile, err := parser.ParseFile(fs, name, text, parser.ParseComments)
|
||||
if err != nil {
|
||||
log.Fatalf("parsing package: %s: %s", name, err)
|
||||
}
|
||||
astFiles = append(astFiles, parsedFile)
|
||||
files = append(files, &File{
|
||||
file: parsedFile,
|
||||
pkg: g.pkg,
|
||||
trimPrefix: g.trimPrefix,
|
||||
file: parsedFile,
|
||||
pkg: g.pkg,
|
||||
trimPrefix: g.trimPrefix,
|
||||
lineComment: g.lineComment,
|
||||
})
|
||||
}
|
||||
if len(astFiles) == 0 {
|
||||
|
@ -457,6 +464,9 @@ func (f *File) genDecl(node ast.Node) bool {
|
|||
signed: info&types.IsUnsigned == 0,
|
||||
str: value.String(),
|
||||
}
|
||||
if c := vspec.Comment; f.lineComment && c != nil && len(c.List) == 1 {
|
||||
v.name = strings.TrimSpace(c.Text())
|
||||
}
|
||||
v.name = strings.TrimPrefix(v.name, f.trimPrefix)
|
||||
f.values = append(f.values, v)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue