goctl added

This commit is contained in:
kim
2020-07-29 17:11:41 +08:00
parent b1975d29a7
commit 121323b8c3
142 changed files with 10690 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
package util
import "zero/tools/goctl/api/spec"
func GetAnnotationValue(annos []spec.Annotation, key, field string) (string, bool) {
for _, anno := range annos {
if anno.Name == key {
value, ok := anno.Properties[field]
return value, ok
}
}
return "", false
}

View File

@@ -0,0 +1,107 @@
package util
func IsUpperCase(r rune) bool {
if r >= 'A' && r <= 'Z' {
return true
}
return false
}
func IsLowerCase(r rune) bool {
if r >= 'a' && r <= 'z' {
return true
}
return false
}
func ToSnakeCase(s string) string {
out := []rune{}
for index, r := range s {
if index == 0 {
out = append(out, ToLowerCase(r))
continue
}
if IsUpperCase(r) && index != 0 {
if IsLowerCase(rune(s[index-1])) {
out = append(out, '_', ToLowerCase(r))
continue
}
if index < len(s)-1 && IsLowerCase(rune(s[index+1])) {
out = append(out, '_', ToLowerCase(r))
continue
}
out = append(out, ToLowerCase(r))
continue
}
out = append(out, r)
}
return string(out)
}
func ToCamelCase(s string) string {
s = ToLower(s)
out := []rune{}
for index, r := range s {
if r == '_' {
continue
}
if index == 0 {
out = append(out, ToUpperCase(r))
continue
}
if index > 0 && s[index-1] == '_' {
out = append(out, ToUpperCase(r))
continue
}
out = append(out, r)
}
return string(out)
}
func ToLowerCase(r rune) rune {
dx := 'A' - 'a'
if IsUpperCase(r) {
return r - dx
}
return r
}
func ToUpperCase(r rune) rune {
dx := 'A' - 'a'
if IsLowerCase(r) {
return r + dx
}
return r
}
func ToLower(s string) string {
out := []rune{}
for _, r := range s {
out = append(out, ToLowerCase(r))
}
return string(out)
}
func ToUpper(s string) string {
out := []rune{}
for _, r := range s {
out = append(out, ToUpperCase(r))
}
return string(out)
}
func LowerFirst(s string) string {
if len(s) == 0 {
return s
}
return ToLower(s[:1]) + s[1:]
}
func UpperFirst(s string) string {
if len(s) == 0 {
return s
}
return ToUpper(s[:1]) + s[1:]
}

View File

@@ -0,0 +1,58 @@
package util
import (
"strconv"
"strings"
)
func TagLookup(tag, key string) (value string, ok bool) {
tag = strings.Replace(tag, "`", "", -1)
for tag != "" {
// Skip leading space.
i := 0
for i < len(tag) && tag[i] == ' ' {
i++
}
tag = tag[i:]
if tag == "" {
break
}
// Scan to colon. A space, a quote or a control character is a syntax error.
// Strictly speaking, control chars include the range [0x7f, 0x9f], not just
// [0x00, 0x1f], but in practice, we ignore the multi-byte control characters
// as it is simpler to inspect the tag's bytes than the tag's runes.
i = 0
for i < len(tag) && tag[i] > ' ' && tag[i] != ':' && tag[i] != '"' && tag[i] != 0x7f {
i++
}
if i == 0 || i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' {
break
}
name := string(tag[:i])
tag = tag[i+1:]
// Scan quoted string to find value.
i = 1
for i < len(tag) && tag[i] != '"' {
if tag[i] == '\\' {
i++
}
i++
}
if i >= len(tag) {
break
}
qvalue := string(tag[:i+1])
tag = tag[i+1:]
if key == name {
value, err := strconv.Unquote(qvalue)
if err != nil {
break
}
return value, true
}
}
return "", false
}

View File

@@ -0,0 +1,159 @@
package util
import (
"fmt"
"strings"
"zero/tools/goctl/api/spec"
)
func DecomposeType(t string) (result []string, err error) {
add := func(tp string) error {
ret, err := DecomposeType(tp)
if err != nil {
return err
}
result = append(result, ret...)
return nil
}
if strings.HasPrefix(t, "map") {
t = strings.ReplaceAll(t, "map", "")
if t[0] == '[' {
pos := strings.Index(t, "]")
if pos > 1 {
if err = add(t[1:pos]); err != nil {
return
}
if len(t) > pos+1 {
err = add(t[pos+1:])
return
}
}
}
} else if strings.HasPrefix(t, "[]") {
if len(t) > 2 {
err = add(t[2:])
return
}
} else if strings.HasPrefix(t, "*") {
err = add(t[1:])
return
} else {
result = append(result, t)
return
}
err = fmt.Errorf("bad type %q", t)
return
}
func GetAllTypes(api *spec.ApiSpec, route spec.Route) []spec.Type {
var rts []spec.Type
types := api.Types
getTypeRecursive(route.RequestType, types, &rts)
getTypeRecursive(route.ResponseType, types, &rts)
return rts
}
func GetLocalTypes(api *spec.ApiSpec, route spec.Route) []spec.Type {
sharedTypes := GetSharedTypes(api)
isSharedType := func(ty spec.Type) bool {
for _, item := range sharedTypes {
if item.Name == ty.Name {
return true
}
}
return false
}
var rts = GetAllTypes(api, route)
var result []spec.Type
for _, item := range rts {
if !isSharedType(item) {
result = append(result, item)
}
}
return result
}
func getTypeRecursive(ty spec.Type, allTypes []spec.Type, result *[]spec.Type) {
isCustomType := func(name string) (*spec.Type, bool) {
for _, item := range allTypes {
if item.Name == name {
return &item, true
}
}
return nil, false
}
if len(ty.Name) > 0 {
*result = append(*result, ty)
}
for _, member := range ty.Members {
decomposedItems, _ := DecomposeType(member.Type)
if len(decomposedItems) == 0 {
continue
}
var customTypes []spec.Type
for _, item := range decomposedItems {
c, e := isCustomType(item)
if e {
customTypes = append(customTypes, *c)
}
}
for _, ty := range customTypes {
hasAppend := false
for _, item := range *result {
if ty.Name == item.Name {
hasAppend = true
break
}
}
if !hasAppend {
getTypeRecursive(ty, allTypes, result)
}
}
}
}
func GetSharedTypes(api *spec.ApiSpec) []spec.Type {
types := api.Types
var result []spec.Type
var container []spec.Type
hasInclude := func(all []spec.Type, ty spec.Type) bool {
for _, item := range all {
if item.Name == ty.Name {
return true
}
}
return false
}
for _, route := range api.Service.Routes {
var rts []spec.Type
getTypeRecursive(route.RequestType, types, &rts)
getTypeRecursive(route.ResponseType, types, &rts)
for _, item := range rts {
if len(item.Name) == 0 {
continue
}
if hasInclude(container, item) {
hasAppend := false
for _, r := range result {
if item.Name == r.Name {
hasAppend = true
break
}
}
if !hasAppend {
result = append(result, item)
}
} else {
container = append(container, item)
}
}
}
return result
}

View File

@@ -0,0 +1,74 @@
package util
import (
"errors"
"fmt"
"io"
"os"
"path"
"strings"
"zero/tools/goctl/api/spec"
"zero/core/lang"
"zero/tools/goctl/util"
)
func MaybeCreateFile(dir, subdir, file string) (fp *os.File, created bool, err error) {
lang.Must(util.MkdirIfNotExist(path.Join(dir, subdir)))
fpath := path.Join(dir, subdir, file)
if util.FileExists(fpath) {
fmt.Printf("%s exists, ignored generation\n", fpath)
return nil, false, nil
}
fp, err = util.CreateIfNotExist(fpath)
created = err == nil
return
}
func ClearAndOpenFile(fpath string) (*os.File, error) {
f, err := os.OpenFile(fpath, os.O_WRONLY|os.O_TRUNC, 0600)
_, err = f.WriteString("")
if err != nil {
return nil, err
}
return f, nil
}
func WrapErr(err error, message string) error {
return errors.New(message + ", " + err.Error())
}
func Copy(src, dst string) (int64, error) {
sourceFileStat, err := os.Stat(src)
if err != nil {
return 0, err
}
if !sourceFileStat.Mode().IsRegular() {
return 0, fmt.Errorf("%s is not a regular file", src)
}
source, err := os.Open(src)
if err != nil {
return 0, err
}
defer source.Close()
destination, err := os.Create(dst)
if err != nil {
return 0, err
}
defer destination.Close()
nBytes, err := io.Copy(destination, source)
return nBytes, err
}
func ComponentName(api *spec.ApiSpec) string {
name := api.Service.Name
if strings.HasSuffix(name, "-api") {
return name[:len(name)-4] + "Components"
}
return name + "Components"
}