1 Star 0 Fork 0

eden-framework / eden-framework

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
utils.go 7.69 KB
一键复制 编辑 原始数据 按行查看 历史
文兄 提交于 2022-01-25 16:27 . feat. controller generator
package scanner
import (
"fmt"
"gitee.com/eden-framework/codegen"
"gitee.com/eden-framework/courier"
"gitee.com/eden-framework/courier/client"
"gitee.com/eden-framework/courier/httpx"
"gitee.com/eden-framework/courier/status_error"
"gitee.com/eden-framework/courier/transport_http"
"gitee.com/eden-framework/reflectx"
"gitee.com/eden-framework/sqlx/builder"
str "gitee.com/eden-framework/strings"
"github.com/go-courier/oas"
"go/ast"
"go/constant"
"go/types"
"reflect"
"regexp"
"strconv"
"strings"
)
const (
XID = `x-id`
XGoVendorType = `x-go-vendor-type`
XGoStarLevel = `x-go-star-level`
XGoFieldName = `x-go-field-name`
XTagValidate = `x-tag-validate`
XTagMime = `x-tag-mime`
XTagJSON = `x-tag-json`
XTagXML = `x-tag-xml`
XTagName = `x-tag-name`
XEnumOptions = `x-enum-options`
XStatusErrs = `x-status-errors`
XAnnotationRevert = `x-annotation-revert`
)
var (
pkgImportPathHttpTransport = reflectx.ImportGoPath(reflect.TypeOf(transport_http.HttpRouteMeta{}).PkgPath())
pkgImportPathHttpx = reflectx.ImportGoPath(reflect.TypeOf(httpx.MethodGet{}).PkgPath())
pkgImportPathCourier = reflectx.ImportGoPath(reflect.TypeOf(courier.Router{}).PkgPath())
)
var (
PkgImportPathClient = reflectx.ImportGoPath(reflect.TypeOf(client.Client{}).PkgPath())
PkgImportPathStatusErr = reflectx.ImportGoPath(reflect.TypeOf(status_error.StatusErrorCode(0)).PkgPath())
)
var (
rxEnum = regexp.MustCompile(`api:enum`)
rxStrFmt = regexp.MustCompile(`api:stringFormat\s+(\S+)([\s\S]+)?$`)
)
var (
defRegexp = regexp.MustCompile(`@def ([^\n]+)`)
relRegexp = regexp.MustCompile(`@rel ([^\n]+)`)
)
var positionOrders = map[oas.Position]string{
"path": "1",
"header": "2",
"query": "3",
"cookie": "4",
}
func valueOf(v constant.Value) interface{} {
if v == nil {
return nil
}
switch v.Kind() {
case constant.Float:
v, _ := strconv.ParseFloat(v.String(), 10)
return v
case constant.Bool:
v, _ := strconv.ParseBool(v.String())
return v
case constant.String:
v, _ := strconv.Unquote(v.String())
return v
case constant.Int:
v, _ := strconv.ParseInt(v.String(), 10, 64)
return v
}
return nil
}
func isRouterType(typ types.Type) bool {
return strings.HasSuffix(typ.String(), pkgImportPathCourier+".Router")
}
func isFromHttpTransport(typ types.Type) bool {
return strings.Contains(typ.String(), pkgImportPathHttpTransport+".")
}
func filterMarkedLines(comments []string) []string {
lines := make([]string, 0)
for _, line := range comments {
if !strings.HasPrefix(line, "@") {
lines = append(lines, line)
}
}
return lines
}
func tagValueAndFlagsByTagString(tagString string) (string, map[string]bool) {
valueAndFlags := strings.Split(tagString, ",")
v := valueAndFlags[0]
tagFlags := map[string]bool{}
if len(valueAndFlags) > 1 {
for _, flag := range valueAndFlags[1:] {
tagFlags[flag] = true
}
}
return v, tagFlags
}
func dropMarkedLines(lines []string) string {
return strings.Join(filterMarkedLines(lines), "\n")
}
func fullTypeName(typeName *types.TypeName) string {
pkg := typeName.Pkg()
if pkg != nil {
return pkg.Path() + "." + typeName.Name()
}
return typeName.Name()
}
func ParseEnum(doc string) (string, bool) {
if rxEnum.MatchString(doc) {
return strings.TrimSpace(strings.Replace(doc, "api:enum", "", -1)), true
}
return doc, false
}
func ParseType(typeExpr ast.Expr) (keyType, pkgName string, pointer bool) {
switch typeExpr.(type) {
case *ast.Ident:
keyType = typeExpr.(*ast.Ident).Name
case *ast.StarExpr:
starExpr := typeExpr.(*ast.StarExpr)
keyType, pkgName, _ = ParseType(starExpr.X)
keyType = "*" + keyType
pointer = true
case *ast.SelectorExpr:
selectorExpr := typeExpr.(*ast.SelectorExpr)
pkgName, _, pointer = ParseType(selectorExpr.X)
keyType = selectorExpr.Sel.Name
case *ast.ArrayType:
arrayType := typeExpr.(*ast.ArrayType)
keyType, pkgName, pointer = ParseType(arrayType.Elt)
keyType = "[]" + keyType
}
return
}
func ParseStringFormat(doc string) (string, string) {
matched := rxStrFmt.FindAllStringSubmatch(doc, -1)
if len(matched) > 0 {
return strings.TrimSpace(matched[0][2]), matched[0][1]
}
return doc, ""
}
func RetrievePackageName(path string) string {
path = strings.Trim(path, "\"")
paths := strings.Split(path, "/")
return strings.Replace(paths[len(paths)-1], "-", "_", -1)
}
func ForEachStructField(structType *types.Struct, fn func(fieldVar *types.Var, columnName string, tagValue string)) {
for i := 0; i < structType.NumFields(); i++ {
field := structType.Field(i)
tag := structType.Tag(i)
if field.Exported() {
structTag := reflect.StructTag(tag)
tagValue, exists := structTag.Lookup("db")
if exists {
if tagValue != "-" {
fn(field, builder.GetColumnName(field.Name(), tagValue), tagValue)
}
} else if field.Anonymous() {
if nextStructType, ok := field.Type().Underlying().(*types.Struct); ok {
ForEachStructField(nextStructType, fn)
}
continue
}
}
}
}
func defSplit(def string) (defs []string) {
vs := strings.Split(def, " ")
for _, s := range vs {
if s != "" {
defs = append(defs, s)
}
}
return
}
func parseColRelFromComment(doc string) (string, []string) {
others := make([]string, 0)
rel := ""
for _, line := range strings.Split(doc, "\n") {
if len(line) == 0 {
continue
}
matches := relRegexp.FindAllStringSubmatch(line, 1)
if matches == nil {
others = append(others, line)
continue
}
if len(matches) == 1 {
rel = matches[0][1]
}
}
return rel, others
}
func parseKeysFromDoc(doc string) (*Keys, []string) {
ks := &Keys{}
others := make([]string, 0)
for _, line := range strings.Split(doc, "\n") {
if len(line) == 0 {
continue
}
matches := defRegexp.FindAllStringSubmatch(line, -1)
if matches == nil {
others = append(others, line)
continue
}
for _, subMatch := range matches {
if len(subMatch) == 2 {
defs := defSplit(subMatch[1])
switch strings.ToLower(defs[0]) {
case "primary":
if len(defs) < 2 {
panic(fmt.Errorf("primary at lease 1 Field"))
}
ks.Primary = defs[1:]
case "unique_index":
if len(defs) < 3 {
panic(fmt.Errorf("unique indexes at lease 1 Field"))
}
if ks.UniqueIndexes == nil {
ks.UniqueIndexes = builder.Indexes{}
}
ks.UniqueIndexes[defs[1]] = defs[2:]
case "index":
if len(defs) < 3 {
panic(fmt.Errorf("index at lease 1 Field"))
}
if ks.Indexes == nil {
ks.Indexes = builder.Indexes{}
}
ks.Indexes[defs[1]] = defs[2:]
}
}
}
}
return ks, others
}
func stringUniq(list []string) (result []string) {
strMap := make(map[string]bool)
for _, str := range list {
strMap[str] = true
}
for i := range list {
str := list[i]
if _, ok := strMap[str]; ok {
delete(strMap, str)
result = append(result, str)
}
}
return
}
func toDefaultTableName(name string) string {
return str.ToLowerSnakeCase("t_" + name)
}
var basicTypeToNilVal = map[string]interface{}{
"invalid": "",
"bool": false,
"error": nil,
"float32": 0,
"float64": 0,
"int": 0,
"int8": 0,
"int16": 0,
"int32": 0,
"int64": 0,
"rune": 0,
"uint": 0,
"uint8": 0,
"uint16": 0,
"uint32": 0,
"uint64": 0,
"byte": 0,
"string": "",
}
// 返回 val 的空值字符串表达式
func toNilVal(typ types.Type) codegen.Snippet {
switch t := typ.(type) {
case *types.Basic:
if empty, ok := basicTypeToNilVal[t.String()]; ok {
return codegen.Expr("?", empty)
}
case *types.Named:
return toNilVal(typ.Underlying())
case *types.Interface, *types.Pointer, *types.Map, *types.Slice, *types.Array:
return nil
}
return nil
}
func isBasicType(typ types.Type) bool {
if _, ok := basicTypeToNilVal[typ.String()]; ok {
return true
}
return false
}
1
https://gitee.com/eden-framework/eden-framework.git
git@gitee.com:eden-framework/eden-framework.git
eden-framework
eden-framework
eden-framework
v1.4.7

搜索帮助