2017-01-24 15:09:23 +00:00
|
|
|
package internal
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"regexp"
|
|
|
|
"strings"
|
|
|
|
|
2017-03-02 03:24:35 +00:00
|
|
|
"github.com/client9/misspell"
|
2017-01-24 15:09:23 +00:00
|
|
|
"github.com/knq/snaker"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
// Base64EncodedParamName is the base64encoded variable name in command
|
|
|
|
// return values when they are optionally base64 encoded.
|
|
|
|
Base64EncodedParamName = "base64Encoded"
|
|
|
|
|
|
|
|
// Base64EncodedDescriptionPrefix is the prefix for command return
|
|
|
|
// description prefix when base64 encoded.
|
|
|
|
Base64EncodedDescriptionPrefix = "Base64-encoded"
|
|
|
|
)
|
|
|
|
|
2017-12-01 04:00:44 +00:00
|
|
|
// misspellReplacer is the misspelling replacer
|
|
|
|
var misspellReplacer *misspell.Replacer
|
2017-03-02 03:24:35 +00:00
|
|
|
|
|
|
|
func init() {
|
2017-12-01 04:00:44 +00:00
|
|
|
misspellReplacer = misspell.New()
|
|
|
|
misspellReplacer.Compile()
|
|
|
|
}
|
|
|
|
|
2017-12-18 00:11:42 +00:00
|
|
|
var descReplacer = strings.NewReplacer(
|
2017-12-01 04:00:44 +00:00
|
|
|
"<", "<",
|
|
|
|
">", ">",
|
|
|
|
">", ">",
|
2017-12-18 00:11:42 +00:00
|
|
|
"`", "",
|
|
|
|
"\n", " ",
|
2017-12-01 04:00:44 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// codeRE is a regexp to match <code> and </code> tags.
|
|
|
|
var codeRE = regexp.MustCompile(`<\/?code>`)
|
|
|
|
|
|
|
|
// CleanDesc cleans comments / descriptions of "<code>" and "</code>" strings
|
|
|
|
// and "`" characters, and fixes common misspellings.
|
|
|
|
func CleanDesc(s string) string {
|
2017-12-18 00:11:42 +00:00
|
|
|
s, _ = misspellReplacer.Replace(codeRE.ReplaceAllString(s, ""))
|
|
|
|
return descReplacer.Replace(s)
|
2017-03-02 03:24:35 +00:00
|
|
|
}
|
|
|
|
|
2017-01-24 15:09:23 +00:00
|
|
|
// ForceCamel forces camel case specific to go.
|
|
|
|
func ForceCamel(s string) string {
|
|
|
|
if s == "" {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
return snaker.SnakeToCamelIdentifier(snaker.CamelToSnake(s))
|
|
|
|
}
|
|
|
|
|
2017-01-26 07:28:34 +00:00
|
|
|
// ForceCamelWithFirstLower forces the first portion to be lower case.
|
|
|
|
func ForceCamelWithFirstLower(s string) string {
|
|
|
|
if s == "" {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
s = snaker.CamelToSnake(s)
|
|
|
|
first := strings.SplitN(s, "_", -1)[0]
|
|
|
|
s = snaker.SnakeToCamelIdentifier(s)
|
|
|
|
|
|
|
|
return strings.ToLower(first) + s[len(first):]
|
|
|
|
}
|
|
|
|
|
2017-01-24 15:09:23 +00:00
|
|
|
// resolve finds the ref in the provided domains, relative to domain d when ref
|
|
|
|
// is not namespaced.
|
|
|
|
func resolve(ref string, d *Domain, domains []*Domain) (DomainType, *Type, string) {
|
|
|
|
n := strings.SplitN(ref, ".", 2)
|
|
|
|
|
|
|
|
// determine domain
|
|
|
|
dtyp := d.Domain
|
|
|
|
typ := n[0]
|
|
|
|
if len(n) == 2 {
|
|
|
|
err := (&dtyp).UnmarshalJSON([]byte(`"` + n[0] + `"`))
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
typ = n[1]
|
|
|
|
}
|
|
|
|
|
|
|
|
// determine if ref points to an object
|
|
|
|
var other *Type
|
|
|
|
for _, z := range domains {
|
|
|
|
if dtyp == z.Domain {
|
|
|
|
for _, j := range z.Types {
|
|
|
|
if j.ID == typ {
|
|
|
|
other = j
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if other == nil {
|
|
|
|
panic(fmt.Sprintf("could not resolve type %s in domain %s", ref, d))
|
|
|
|
}
|
|
|
|
|
|
|
|
var s string
|
|
|
|
// add prefix if not an internal type and not defined in the domain
|
2017-01-26 07:28:34 +00:00
|
|
|
if IsCDPType(dtyp, typ) {
|
|
|
|
if d.Domain != DomainType("cdp") {
|
|
|
|
s += "cdp."
|
|
|
|
}
|
|
|
|
} else if dtyp != d.Domain {
|
2017-01-24 15:09:23 +00:00
|
|
|
s += strings.ToLower(dtyp.String()) + "."
|
|
|
|
}
|
|
|
|
|
|
|
|
return dtyp, other, s + ForceCamel(typ)
|
|
|
|
}
|
|
|
|
|
|
|
|
// structDef returns a struct definition for a list of types.
|
|
|
|
func structDef(types []*Type, d *Domain, domains []*Domain, noExposeOverride, omitOnlyWhenOptional bool) string {
|
|
|
|
s := "struct"
|
|
|
|
if len(types) > 0 {
|
|
|
|
s += " "
|
|
|
|
}
|
|
|
|
s += "{"
|
|
|
|
for _, v := range types {
|
|
|
|
s += "\n\t" + v.GoName(noExposeOverride) + " " + v.GoType(d, domains)
|
|
|
|
|
|
|
|
omit := ",omitempty"
|
|
|
|
if omitOnlyWhenOptional && !v.Optional.Bool() {
|
|
|
|
omit = ""
|
|
|
|
}
|
|
|
|
|
|
|
|
// add json tag
|
|
|
|
if v.NoExpose {
|
|
|
|
s += " `json:\"-\"`"
|
|
|
|
} else {
|
|
|
|
s += " `json:\"" + v.Name + omit + "\"`"
|
|
|
|
}
|
|
|
|
|
|
|
|
// add comment
|
|
|
|
if v.Type != TypeObject && v.Description != "" {
|
2017-12-01 04:00:44 +00:00
|
|
|
s += " // " + CleanDesc(v.Description)
|
2017-01-24 15:09:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if len(types) > 0 {
|
|
|
|
s += "\n"
|
|
|
|
}
|
|
|
|
s += "}"
|
|
|
|
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
2017-01-26 07:28:34 +00:00
|
|
|
// cdpTypes is the list of internal types.
|
|
|
|
var cdpTypes map[string]bool
|
2017-01-24 15:09:23 +00:00
|
|
|
|
2017-01-26 07:28:34 +00:00
|
|
|
// SetCDPTypes sets the internal types.
|
|
|
|
func SetCDPTypes(types map[string]bool) {
|
|
|
|
cdpTypes = types
|
2017-01-24 15:09:23 +00:00
|
|
|
}
|
|
|
|
|
2017-01-26 07:28:34 +00:00
|
|
|
// IsCDPType determines if the specified domain and typ constitute an
|
2017-01-24 15:09:23 +00:00
|
|
|
// internal type.
|
2017-01-26 07:28:34 +00:00
|
|
|
func IsCDPType(dtyp DomainType, typ string) bool {
|
|
|
|
if _, ok := cdpTypes[dtyp.String()+"."+typ]; ok {
|
2017-01-24 15:09:23 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2017-01-26 07:28:34 +00:00
|
|
|
// CDPTypeList returns the list of internal types.
|
|
|
|
func CDPTypeList() []string {
|
2017-01-24 15:09:23 +00:00
|
|
|
var types []string
|
2017-01-26 07:28:34 +00:00
|
|
|
for k := range cdpTypes {
|
2017-01-24 15:09:23 +00:00
|
|
|
n := strings.SplitN(k, ".", 2)
|
|
|
|
types = append(types, ForceCamel(n[1]))
|
|
|
|
}
|
|
|
|
|
|
|
|
return types
|
|
|
|
}
|
|
|
|
|
2017-02-12 04:59:33 +00:00
|
|
|
// goReservedNames is the list of reserved names in Go.
|
2017-01-24 15:09:23 +00:00
|
|
|
var goReservedNames = map[string]bool{
|
|
|
|
// language words
|
|
|
|
"break": true,
|
|
|
|
"case": true,
|
|
|
|
"chan": true,
|
|
|
|
"const": true,
|
|
|
|
"continue": true,
|
|
|
|
"default": true,
|
|
|
|
"defer": true,
|
|
|
|
"else": true,
|
|
|
|
"fallthrough": true,
|
|
|
|
"for": true,
|
|
|
|
"func": true,
|
|
|
|
"go": true,
|
|
|
|
"goto": true,
|
|
|
|
"if": true,
|
|
|
|
"import": true,
|
|
|
|
"interface": true,
|
|
|
|
"map": true,
|
|
|
|
"package": true,
|
|
|
|
"range": true,
|
|
|
|
"return": true,
|
|
|
|
"select": true,
|
|
|
|
"struct": true,
|
|
|
|
"switch": true,
|
|
|
|
"type": true,
|
|
|
|
"var": true,
|
|
|
|
|
|
|
|
// go types
|
|
|
|
"error": true,
|
|
|
|
"bool": true,
|
|
|
|
"string": true,
|
|
|
|
"byte": true,
|
|
|
|
"rune": true,
|
|
|
|
"uintptr": true,
|
|
|
|
"int": true,
|
|
|
|
"int8": true,
|
|
|
|
"int16": true,
|
|
|
|
"int32": true,
|
|
|
|
"int64": true,
|
|
|
|
"uint": true,
|
|
|
|
"uint8": true,
|
|
|
|
"uint16": true,
|
|
|
|
"uint32": true,
|
|
|
|
"uint64": true,
|
|
|
|
"float32": true,
|
|
|
|
"float64": true,
|
|
|
|
"complex64": true,
|
|
|
|
"complex128": true,
|
|
|
|
}
|