mirror of
https://github.com/bufanyun/hotgo.git
synced 2025-11-13 12:43:45 +08:00
147 lines
3.1 KiB
Go
147 lines
3.1 KiB
Go
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
|
|
//
|
|
// This Source Code Form is subject to the terms of the MIT License.
|
|
// If a copy of the MIT was not distributed with this file,
|
|
// You can obtain one at https://github.com/gogf/gf.
|
|
|
|
package genenums
|
|
|
|
import (
|
|
"go/constant"
|
|
"go/types"
|
|
"golang.org/x/tools/go/packages"
|
|
|
|
"github.com/gogf/gf/v2/encoding/gjson"
|
|
"github.com/gogf/gf/v2/text/gstr"
|
|
"github.com/gogf/gf/v2/util/gconv"
|
|
)
|
|
|
|
const pkgLoadMode = 0xffffff
|
|
|
|
type EnumsParser struct {
|
|
enums []EnumItem
|
|
parsedPkg map[string]struct{}
|
|
prefixes []string
|
|
}
|
|
|
|
type EnumItem struct {
|
|
Name string
|
|
Value string
|
|
Kind constant.Kind // String/Int/Bool/Float/Complex/Unknown
|
|
Type string // Pkg.ID + TypeName
|
|
}
|
|
|
|
var standardPackages = make(map[string]struct{})
|
|
|
|
func init() {
|
|
stdPackages, err := packages.Load(nil, "std")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
for _, p := range stdPackages {
|
|
standardPackages[p.ID] = struct{}{}
|
|
}
|
|
}
|
|
|
|
func NewEnumsParser(prefixes []string) *EnumsParser {
|
|
return &EnumsParser{
|
|
enums: make([]EnumItem, 0),
|
|
parsedPkg: make(map[string]struct{}),
|
|
prefixes: prefixes,
|
|
}
|
|
}
|
|
|
|
func (p *EnumsParser) ParsePackages(pkgs []*packages.Package) {
|
|
for _, pkg := range pkgs {
|
|
p.ParsePackage(pkg)
|
|
}
|
|
}
|
|
|
|
func (p *EnumsParser) ParsePackage(pkg *packages.Package) {
|
|
// Ignore std packages.
|
|
if _, ok := standardPackages[pkg.ID]; ok {
|
|
return
|
|
}
|
|
// Ignore pared packages.
|
|
if _, ok := p.parsedPkg[pkg.ID]; ok {
|
|
return
|
|
}
|
|
p.parsedPkg[pkg.ID] = struct{}{}
|
|
|
|
// Only parse specified prefixes.
|
|
if len(p.prefixes) > 0 {
|
|
var hasPrefix bool
|
|
for _, prefix := range p.prefixes {
|
|
if hasPrefix = gstr.HasPrefix(pkg.ID, prefix); hasPrefix {
|
|
break
|
|
}
|
|
}
|
|
if !hasPrefix {
|
|
return
|
|
}
|
|
}
|
|
|
|
var (
|
|
scope = pkg.Types.Scope()
|
|
names = scope.Names()
|
|
)
|
|
for _, name := range names {
|
|
con, ok := scope.Lookup(name).(*types.Const)
|
|
if !ok {
|
|
// Only constants can be enums.
|
|
continue
|
|
}
|
|
if !con.Exported() {
|
|
// Ignore unexported values.
|
|
continue
|
|
}
|
|
|
|
var enumType = con.Type().String()
|
|
if !gstr.Contains(enumType, "/") {
|
|
// Ignore std types.
|
|
continue
|
|
}
|
|
var (
|
|
enumName = con.Name()
|
|
enumValue = con.Val().ExactString()
|
|
enumKind = con.Val().Kind()
|
|
)
|
|
if con.Val().Kind() == constant.String {
|
|
enumValue = constant.StringVal(con.Val())
|
|
}
|
|
p.enums = append(p.enums, EnumItem{
|
|
Name: enumName,
|
|
Value: enumValue,
|
|
Type: enumType,
|
|
Kind: enumKind,
|
|
})
|
|
}
|
|
for _, im := range pkg.Imports {
|
|
p.ParsePackage(im)
|
|
}
|
|
}
|
|
|
|
func (p *EnumsParser) Export() string {
|
|
var typeEnumMap = make(map[string][]interface{})
|
|
for _, enum := range p.enums {
|
|
if typeEnumMap[enum.Type] == nil {
|
|
typeEnumMap[enum.Type] = make([]interface{}, 0)
|
|
}
|
|
var value interface{}
|
|
switch enum.Kind {
|
|
case constant.Int:
|
|
value = gconv.Int64(enum.Value)
|
|
case constant.String:
|
|
value = enum.Value
|
|
case constant.Float:
|
|
value = gconv.Float64(enum.Value)
|
|
case constant.Bool:
|
|
value = gconv.Bool(enum.Value)
|
|
default:
|
|
value = enum.Value
|
|
}
|
|
typeEnumMap[enum.Type] = append(typeEnumMap[enum.Type], value)
|
|
}
|
|
return gjson.MustEncodeString(typeEnumMap)
|
|
}
|