thrift/thrift-gen/names.go (121 lines of code) (raw):
// Copyright (c) 2015 Uber Technologies, Inc.
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package main
// This file implements go name generation for thrift identifiers.
// It has to match the Apache Thrift generated names.
import "strings"
// goKeywords taken from https://golang.org/ref/spec#Keywords (and added error).
var goKeywords = map[string]bool{
"error": true,
"break": true,
"default": true,
"func": true,
"interface": true,
"select": true,
"case": true,
"defer": true,
"go": true,
"map": true,
"struct": true,
"chan": true,
"else": true,
"goto": true,
"package": true,
"switch": true,
"const": true,
"fallthrough": true,
"if": true,
"range": true,
"type": true,
"continue": true,
"for": true,
"import": true,
"return": true,
"var": true,
}
// This set is taken from https://github.com/golang/lint/blob/master/lint.go#L692
var commonInitialisms = map[string]bool{
"API": true,
"ASCII": true,
"CPU": true,
"CSS": true,
"DNS": true,
"EOF": true,
"GUID": true,
"HTML": true,
"HTTP": true,
"HTTPS": true,
"ID": true,
"IP": true,
"JSON": true,
"LHS": true,
"QPS": true,
"RAM": true,
"RHS": true,
"RPC": true,
"SLA": true,
"SMTP": true,
"SQL": true,
"SSH": true,
"TCP": true,
"TLS": true,
"TTL": true,
"UDP": true,
"UI": true,
"UID": true,
"UUID": true,
"URI": true,
"URL": true,
"UTF8": true,
"VM": true,
"XML": true,
"XSRF": true,
"XSS": true,
}
func goName(name string) string {
// Thrift Identifier from IDL: ( Letter | '_' ) ( Letter | Digit | '.' | '_' )*
// Go identifier from spec: letter { letter | unicode_digit } .
// Go letter allows underscore, so the only difference is period. However, periods cannot
// actaully be used - this seems to be a bug in the IDL.
if _, ok := goKeywords[name]; ok {
// The thrift compiler appends _a1 for any clashes with go keywords.
name += "_a1"
}
name = camelCase(name, false /* publicName */)
return name
}
// camelCase takes a name with underscores such as my_arg and returns camelCase (e.g. myArg).
// if publicName is true, then it returns UpperCamelCase.
// This method will also fix common initialisms (e.g. ID, API, etc).
func camelCase(name string, publicName bool) string {
parts := strings.Split(name, "_")
startAt := 1
if publicName {
startAt = 0
}
for i := startAt; i < len(parts); i++ {
name := parts[i]
if name == "" {
continue
}
// For all words except the first, if the first letter of the word is
// uppercase, Thrift keeps the underscore.
if i > 0 && strings.ToUpper(name[0:1]) == name[0:1] {
name = "_" + name
} else {
name = strings.ToUpper(name[0:1]) + name[1:]
}
if isInitialism := commonInitialisms[strings.ToUpper(name)]; isInitialism {
name = strings.ToUpper(name)
}
parts[i] = name
}
return strings.Join(parts, "")
}
func avoidThriftClash(name string) string {
if strings.HasSuffix(name, "Result") ||
strings.HasSuffix(name, "Args") ||
strings.HasPrefix(name, "New") {
return name + "_"
}
return name
}
// goPublicName returns a go identifier that is exported.
func goPublicName(name string) string {
return camelCase(name, true /* publicName */)
}
// goPublicFieldName returns the name of the field as used in a struct.
func goPublicFieldName(name string) string {
return avoidThriftClash(goPublicName(name))
}
var thriftToGo = map[string]string{
"bool": "bool",
"byte": "int8",
"i16": "int16",
"i32": "int32",
"i64": "int64",
"double": "float64",
"string": "string",
}