package internal import ( "fmt" "regexp" "strings" "github.com/client9/misspell" "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" ) // misspellReplacer is the misspelling replacer var misspellReplacer *misspell.Replacer func init() { misspellReplacer = misspell.New() misspellReplacer.Compile() } var badHTMLReplacer = strings.NewReplacer( "<", "<", ">", ">", ">", ">", ) // codeRE is a regexp to match and tags. var codeRE = regexp.MustCompile(`<\/?code>`) // CleanDesc cleans comments / descriptions of "" and "" strings // and "`" characters, and fixes common misspellings. func CleanDesc(s string) string { s, _ = misspellReplacer.Replace(strings.Replace(codeRE.ReplaceAllString(s, ""), "`", "", -1)) return badHTMLReplacer.Replace(s) } // ForceCamel forces camel case specific to go. func ForceCamel(s string) string { if s == "" { return "" } return snaker.SnakeToCamelIdentifier(snaker.CamelToSnake(s)) } // 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):] } // 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 if IsCDPType(dtyp, typ) { if d.Domain != DomainType("cdp") { s += "cdp." } } else if dtyp != d.Domain { 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 != "" { s += " // " + CleanDesc(v.Description) } } if len(types) > 0 { s += "\n" } s += "}" return s } // cdpTypes is the list of internal types. var cdpTypes map[string]bool // SetCDPTypes sets the internal types. func SetCDPTypes(types map[string]bool) { cdpTypes = types } // IsCDPType determines if the specified domain and typ constitute an // internal type. func IsCDPType(dtyp DomainType, typ string) bool { if _, ok := cdpTypes[dtyp.String()+"."+typ]; ok { return true } return false } // CDPTypeList returns the list of internal types. func CDPTypeList() []string { var types []string for k := range cdpTypes { n := strings.SplitN(k, ".", 2) types = append(types, ForceCamel(n[1])) } return types } // goReservedNames is the list of reserved names in Go. 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, }