代码拉取完成,页面将自动刷新
package internal
import (
"context"
"go/ast"
"go/parser"
"go/token"
"go/types"
"log/slog"
"os"
"strings"
"github.com/samber/lo"
"github.com/xuender/kit/los"
)
type Bind struct {
pkgs map[string][]*ast.File
}
func NewBind() *Bind {
return &Bind{
pkgs: map[string][]*ast.File{},
}
}
func (p *Bind) Add(path string) {
if _, has := p.pkgs[path]; has {
return
}
pkgs, errs := LoadPackages(context.Background(), los.Must(os.Getwd()), os.Environ(), "", []string{path})
if len(errs) > 0 {
los.Must0(errs[0])
}
fset := token.NewFileSet()
files := []*ast.File{}
for _, pkg := range pkgs {
for _, file := range pkg.GoFiles {
file := los.Must(parser.ParseFile(fset, file, nil, parser.ParseComments))
files = append(files, file)
}
}
p.pkgs[path] = files
}
func (p *Bind) Bind(igen *bindGen, target, source *types.Var, ignores []string) {
slog.Info("bind",
"target", target.Name(),
"targetType", target.Type(),
"source", source.Name(),
"sourceType", source.Type(),
"ignores", ignores,
)
idx := strings.LastIndex(target.Type().String(), ".")
targetPkg := target.Type().String()[:idx]
targetStruct := target.Type().String()[idx+1:]
targetPkg = strings.Trim(targetPkg, "*")
slog.Info("target", "pkg", targetPkg, "model", targetStruct)
idx = strings.LastIndex(source.Type().String(), ".")
sourcePkg := source.Type().String()[:idx]
sourceStruct := source.Type().String()[idx+1:]
sourcePkg = strings.Trim(sourcePkg, "*")
slog.Info("source", "pkg", sourcePkg, "model", sourceStruct)
p.Add(targetPkg)
p.Add(sourcePkg)
sourceFields := p.Geter(sourcePkg, sourceStruct)
targetFields := p.Seter(targetPkg, targetStruct)
for _, name := range targetFields.Mixed(sourceFields) {
if lo.Contains(ignores, name) {
continue
}
sourceField := sourceFields.Find(name)
targetField := targetFields.Find(name)
val := sourceField.Val(source.Name(), targetField.Type)
if targetField.Mod == Set {
igen.Pf("\t"+target.Name()+".Set"+name+"(%s)\n", val)
} else {
igen.Pf("\t"+target.Name()+"."+name+" = %s\n", val)
}
for key, val := range sourceField.Imports {
if _, has := igen.g.imports[key]; !has {
igen.g.imports[key] = val
}
}
}
}
func (p *Bind) fields(pkgName, structName, prefix string) Fielders {
pkg, has := p.pkgs[pkgName]
if !has {
return nil
}
ret := Fielders{}
for _, file := range pkg {
for _, decl := range file.Decls {
genDecl, isOk := decl.(*ast.GenDecl)
if !isOk || genDecl.Tok != token.TYPE {
continue
}
// 遍历结构体定义
for _, spec := range genDecl.Specs {
typeSpec := spec.(*ast.TypeSpec)
structType, isOk := typeSpec.Type.(*ast.StructType)
if !isOk {
continue
}
//
if typeSpec.Name.Name != structName {
continue
}
ret = readFields(structType, ret)
ast.Inspect(file, func(node ast.Node) bool {
ret = readFuncs(node, typeSpec, prefix, ret)
return true
})
}
}
}
return ret
}
func readFuncs(node ast.Node, typeSpec *ast.TypeSpec, prefix string, ret Fielders) Fielders {
if fun, isOk := node.(*ast.FuncDecl); isOk {
if fun.Recv == nil {
return ret
}
if len(fun.Recv.List) == 0 {
return ret
}
if ident, isOk := fun.Recv.List[0].Type.(*ast.StarExpr); isOk {
if ident.X.(*ast.Ident).Name == typeSpec.Name.Name && strings.HasPrefix(fun.Name.Name, prefix) {
mod := Get
fieldType := ""
if prefix == "Set" {
mod = Set
ident := fun.Type.Params.List[0].Type.(*ast.Ident)
fieldType = ident.Name
} else {
// ident := fun.Type.Results.List[0].Type.(*ast.Ident)
// fieldType = ident.Name
ident, ok := fun.Type.Results.List[0].Type.(*ast.Ident)
if ok {
fieldType = ident.Name
}
}
ret.Add(Fielder{
Name: fun.Name.Name[len(prefix):],
Mod: mod,
Type: fieldType,
Imports: map[string]ImportInfo{},
})
}
}
}
return ret
}
func readFields(structType *ast.StructType, ret Fielders) Fielders {
for _, field := range structType.Fields.List {
for _, name := range field.Names {
if name.IsExported() {
fieldType := ""
switch obj := field.Type.(type) {
case *ast.ArrayType, *ast.StarExpr:
continue
case *ast.Ident:
fieldType = obj.Name
case *ast.SelectorExpr:
pkgIdent, isOk := obj.X.(*ast.Ident)
if !isOk {
slog.Warn("Unknown package")
continue
}
fieldType = pkgIdent.Name + "." + obj.Sel.Name
}
ret.Add(Fielder{
Name: name.Name,
Mod: Exported,
Type: fieldType,
Imports: map[string]ImportInfo{},
})
}
}
}
return ret
}
func (p *Bind) Geter(pkgName, model string) Fielders {
return p.fields(pkgName, model, "Get")
}
func (p *Bind) Seter(pkgName, model string) Fielders {
return p.fields(pkgName, model, "Set")
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。