Merge pull request #35 from Barberrrry/camel_case_functions

Generate CamelCase function names instead of under_score to pass golint check
This commit is contained in:
Victor Starodub
2016-07-28 15:31:05 +04:00
committed by GitHub
7 changed files with 71 additions and 27 deletions
+1
View File
@@ -5,3 +5,4 @@ go:
install:
- go get github.com/ugorji/go/codec
- go get github.com/pquerna/ffjson/fflib/v1
- go get github.com/golang/lint/golint
+2 -1
View File
@@ -26,7 +26,7 @@ generate: root build
.root/bin/easyjson -all .root/src/$(PKG)/tests/data.go
.root/bin/easyjson -all .root/src/$(PKG)/tests/nothing.go
.root/bin/easyjson -snake_case .root/src/$(PKG)/tests/snake.go
.root/bin/easyjson -omit_empty .root/src/$(PKG)/tests/omitempty.go
.root/bin/easyjson -omit_empty .root/src/$(PKG)/tests/omitempty.go
.root/bin/easyjson -build_tags=use_easyjson .root/src/$(PKG)/benchmark/data.go
test: generate root
@@ -36,6 +36,7 @@ test: generate root
$(PKG)/gen \
$(PKG)/buffer
go test -benchmem -tags use_easyjson -bench . $(PKG)/benchmark
golint -set_exit_status .root/src/$(PKG)/tests/*_easyjson.go
bench-other: generate root
@go test -benchmem -bench . $(PKG)/benchmark
+1 -1
View File
@@ -40,7 +40,7 @@ func generate(fname string) (err error) {
if *specifiedName != "" {
outName = *specifiedName
}
g := bootstrap.Generator{
BuildTags: *buildTags,
PkgPath: p.PkgPath,
+5 -3
View File
@@ -14,7 +14,7 @@ import (
const minSliceBytes = 64
func (g *Generator) getDecoderName(t reflect.Type) string {
return g.functionName("decode_", t)
return g.functionName("decode", t)
}
var primitiveDecoders = map[reflect.Kind]string{
@@ -169,7 +169,7 @@ func (g *Generator) genTypeDecoderNoCheck(t reflect.Type, out string, tags field
}
func (g *Generator) genStructFieldDecoder(t reflect.Type, f reflect.StructField) error {
jsonName := g.namer.GetJSONFieldName(t, f)
jsonName := g.fieldNamer.GetJSONFieldName(t, f)
tags := parseFieldTags(f)
if tags.omit {
@@ -199,7 +199,7 @@ func (g *Generator) genRequiredFieldSet(t reflect.Type, f reflect.StructField) {
}
func (g *Generator) genRequiredFieldCheck(t reflect.Type, f reflect.StructField) {
jsonName := g.namer.GetJSONFieldName(t, f)
jsonName := g.fieldNamer.GetJSONFieldName(t, f)
tags := parseFieldTags(f)
if !tags.required {
@@ -368,6 +368,7 @@ func (g *Generator) genStructUnmarshaller(t reflect.Type) error {
typ := g.getType(t)
if !g.noStdMarshalers {
fmt.Fprintln(g.out, "// UnmarshalJSON supports json.Unmarshaler interface")
fmt.Fprintln(g.out, "func (v *"+typ+") UnmarshalJSON(data []byte) error {")
fmt.Fprintln(g.out, " r := jlexer.Lexer{Data: data}")
fmt.Fprintln(g.out, " "+fname+"(&r, v)")
@@ -375,6 +376,7 @@ func (g *Generator) genStructUnmarshaller(t reflect.Type) error {
fmt.Fprintln(g.out, "}")
}
fmt.Fprintln(g.out, "// UnmarshalEasyJSON supports easyjson.Unmarshaler interface")
fmt.Fprintln(g.out, "func (v *"+typ+") UnmarshalEasyJSON(l *jlexer.Lexer) {")
fmt.Fprintln(g.out, " "+fname+"(l, v)")
fmt.Fprintln(g.out, "}")
+10 -8
View File
@@ -11,7 +11,7 @@ import (
)
func (g *Generator) getEncoderName(t reflect.Type) string {
return g.functionName("encode_", t)
return g.functionName("encode", t)
}
var primitiveEncoders = map[reflect.Kind]string{
@@ -155,14 +155,14 @@ func (g *Generator) genTypeEncoderNoCheck(t reflect.Type, in string, tags fieldT
fmt.Fprintln(g.out, ws+" out.RawString(`null`)")
fmt.Fprintln(g.out, ws+"} else {")
fmt.Fprintln(g.out, ws+" out.RawByte('{')")
fmt.Fprintln(g.out, ws+" "+tmpVar+"_first := true")
fmt.Fprintln(g.out, ws+" for "+tmpVar+"_name, "+tmpVar+"_value := range "+in+" {")
fmt.Fprintln(g.out, ws+" if !"+tmpVar+"_first { out.RawByte(',') }")
fmt.Fprintln(g.out, ws+" "+tmpVar+"_first = false")
fmt.Fprintln(g.out, ws+" out.String(string("+tmpVar+"_name))")
fmt.Fprintln(g.out, ws+" "+tmpVar+"First := true")
fmt.Fprintln(g.out, ws+" for "+tmpVar+"Name, "+tmpVar+"Value := range "+in+" {")
fmt.Fprintln(g.out, ws+" if !"+tmpVar+"First { out.RawByte(',') }")
fmt.Fprintln(g.out, ws+" "+tmpVar+"First = false")
fmt.Fprintln(g.out, ws+" out.String(string("+tmpVar+"Name))")
fmt.Fprintln(g.out, ws+" out.RawByte(':')")
g.genTypeEncoder(t.Elem(), tmpVar+"_value", tags, indent+2)
g.genTypeEncoder(t.Elem(), tmpVar+"Value", tags, indent+2)
fmt.Fprintln(g.out, ws+" }")
fmt.Fprintln(g.out, ws+" out.RawByte('}')")
@@ -207,7 +207,7 @@ func (g *Generator) notEmptyCheck(t reflect.Type, v string) string {
}
func (g *Generator) genStructFieldEncoder(t reflect.Type, f reflect.StructField) error {
jsonName := g.namer.GetJSONFieldName(t, f)
jsonName := g.fieldNamer.GetJSONFieldName(t, f)
tags := parseFieldTags(f)
if tags.omit {
@@ -296,6 +296,7 @@ func (g *Generator) genStructMarshaller(t reflect.Type) error {
typ := g.getType(t)
if !g.noStdMarshalers {
fmt.Fprintln(g.out, "// MarshalJSON supports json.Marshaler interface")
fmt.Fprintln(g.out, "func (v "+typ+") MarshalJSON() ([]byte, error) {")
fmt.Fprintln(g.out, " w := jwriter.Writer{}")
fmt.Fprintln(g.out, " "+fname+"(&w, v)")
@@ -303,6 +304,7 @@ func (g *Generator) genStructMarshaller(t reflect.Type) error {
fmt.Fprintln(g.out, "}")
}
fmt.Fprintln(g.out, "// MarshalEasyJSON supports easyjson.Marshaler interface")
fmt.Fprintln(g.out, "func (v "+typ+") MarshalEasyJSON(w *jwriter.Writer) {")
fmt.Fprintln(g.out, " "+fname+"(w, v)")
fmt.Fprintln(g.out, "}")
+33 -14
View File
@@ -27,13 +27,13 @@ type Generator struct {
pkgName string
pkgPath string
buildTags string
funcPrefix string
hashString string
varCounter int
noStdMarshalers bool
omitEmpty bool
namer FieldNamer
fieldNamer FieldNamer
// package path to local alias map for tracking imports
imports map[string]string
@@ -60,7 +60,7 @@ func NewGenerator(filename string) *Generator {
pkgLexer: "jlexer",
"encoding/json": "json",
},
namer: DefaultFieldNamer{},
fieldNamer: DefaultFieldNamer{},
marshallers: make(map[reflect.Type]bool),
typesSeen: make(map[reflect.Type]bool),
functionNames: make(map[string]reflect.Type),
@@ -70,7 +70,7 @@ func NewGenerator(filename string) *Generator {
// name clashes.
hash := fnv.New32()
hash.Write([]byte(filename))
ret.funcPrefix = fmt.Sprintf("easyjson_%x_", hash.Sum32())
ret.hashString = fmt.Sprintf("%x", hash.Sum32())
return ret
}
@@ -88,12 +88,12 @@ func (g *Generator) SetBuildTags(tags string) {
// SetFieldNamer sets field naming strategy.
func (g *Generator) SetFieldNamer(n FieldNamer) {
g.namer = n
g.fieldNamer = n
}
// UseSnakeCase sets snake_case field naming strategy.
func (g *Generator) UseSnakeCase() {
g.namer = SnakeCaseFieldNamer{}
g.fieldNamer = SnakeCaseFieldNamer{}
}
// NoStdMarshalers instructs not to generate standard MarshalJSON/UnmarshalJSON
@@ -255,7 +255,7 @@ func (g *Generator) uniqueVarName() string {
// safeName escapes unsafe characters in pkg/type name and returns a string that can be used
// in encoder/decoder names for the type.
func safeName(t reflect.Type) string {
func (g *Generator) safeName(t reflect.Type) string {
name := t.PkgPath()
if t.Name() == "" {
name += "anonymous"
@@ -263,15 +263,17 @@ func safeName(t reflect.Type) string {
name += "." + t.Name()
}
var ret []rune
parts := []string{}
part := []rune{}
for _, c := range name {
if unicode.IsLetter(c) || unicode.IsDigit(c) {
ret = append(ret, c)
} else {
ret = append(ret, '_')
part = append(part, c)
} else if len(part) > 0 {
parts = append(parts, string(part))
part = []rune{}
}
}
return string(ret)
return joinFunctionNameParts(false, parts...)
}
// functionName returns a function name for a given type with a given prefix. If a function
@@ -279,8 +281,8 @@ func safeName(t reflect.Type) string {
//
// Method is used to track encoder/decoder names for the type.
func (g *Generator) functionName(prefix string, t reflect.Type) string {
prefix = g.funcPrefix + prefix
name := prefix + safeName(t)
prefix = joinFunctionNameParts(true, "easyjson", g.hashString, prefix)
name := joinFunctionNameParts(true, prefix, g.safeName(t))
// Most of the names will be unique, try a shortcut first.
if e, ok := g.functionNames[name]; !ok || e == t {
@@ -374,3 +376,20 @@ func (SnakeCaseFieldNamer) GetJSONFieldName(t reflect.Type, f reflect.StructFiel
return camelToSnake(f.Name)
}
func joinFunctionNameParts(keepFirst bool, parts ...string) string {
buf := bytes.NewBufferString("")
for i, part := range parts {
if i == 0 && keepFirst {
buf.WriteString(part)
} else {
if len(part) > 0 {
buf.WriteString(strings.ToUpper(string(part[0])))
}
if len(part) > 1 {
buf.WriteString(part[1:])
}
}
}
return buf.String()
}
+19
View File
@@ -26,5 +26,24 @@ func TestCamelToSnake(t *testing.T) {
t.Errorf("[%d] camelToSnake(%s) = %s; want %s", i, test.In, got, test.Out)
}
}
}
func TestJoinFunctionNameParts(t *testing.T) {
for i, test := range []struct {
keepFirst bool
parts []string
out string
}{
{false, []string{}, ""},
{false, []string{"a"}, "A"},
{false, []string{"simple", "example"}, "SimpleExample"},
{true, []string{"first", "example"}, "firstExample"},
{false, []string{"some", "UPPER", "case"}, "SomeUPPERCase"},
{false, []string{"number", "123"}, "Number123"},
} {
got := joinFunctionNameParts(test.keepFirst, test.parts...)
if got != test.out {
t.Errorf("[%d] joinFunctionNameParts(%v) = %s; want %s", i, test.parts, got, test.out)
}
}
}