1 Star 0 Fork 0

ichub / gomini

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
dimeta_factroy.go 11.63 KB
一键复制 编辑 原始数据 按行查看 历史
leijmdas 提交于 2024-05-14 16:27 . add
package goast
import (
"fmt"
"gitee.com/ichub/goconfig/common/base/basedto"
"gitee.com/ichub/goconfig/common/base/baseutils/fileutils"
"gitee.com/ichub/goconfig/common/base/baseutils/jsonutils"
"gitee.com/ichub/goconfig/common/ichubconfig"
"gitee.com/ichub/goconfig/common/ichublog"
"gitee.com/ichub/gomini/mini/meta/goast/diconsts"
"gitee.com/ichub/gomini/mini/meta/goast/dimeta"
"gitee.com/ichub/gomini/mini/metafile"
"github.com/duke-git/lancet/fileutil"
"github.com/sirupsen/logrus"
"go/ast"
"go/parser"
"go/token"
"os"
"path/filepath"
"reflect"
"strconv"
"strings"
)
const dataOutputDiStruct = "/data/output/di/struct"
const dataOutputDiFile = "/data/output/di/file"
type DimetaFactroy struct {
basedto.BaseEntitySingle
metafile.MetaFile `json:"-"`
BasePkg string
Rootdir string
//指定的结构名称
filterStru string `json:"-"`
FileInfoDtos []*dimeta.FileInfoDto
StructInfos map[string]*dimeta.StructInfo
Config *ichubconfig.IchubConfig `di:"auto"`
}
func NewDiFactroy() *DimetaFactroy {
return (&DimetaFactroy{
Rootdir: fileutils.FindRootDir(),
FileInfoDtos: make([]*dimeta.FileInfoDto, 0),
StructInfos: make(map[string]*dimeta.StructInfo),
}).init()
}
func (this *DimetaFactroy) init() *DimetaFactroy {
ichublog.InitLogrus()
this.BasePkg = this.FindBasePkg()
return this
}
func (this *DimetaFactroy) FindBasePkg() string {
var content, _ = fileutil.ReadFileToString(fileutils.FindRootDirGoMod() + "/go.mod")
var lines = strings.Split(content, "\n")
for _, line := range lines {
if strings.Contains(line, "module") {
var lineArr = strings.Split(line, "module")
this.BasePkg = strings.Trim(lineArr[1], " ")
this.BasePkg = strings.Trim(this.BasePkg, "\r")
return this.BasePkg
}
}
return ""
}
func (this *DimetaFactroy) FindFile(file string) *dimeta.FileInfoDto {
fset := token.NewFileSet()
// 这里取绝对路径,方便打印出来的语法树可以转跳到编辑器
path, _ := filepath.Abs(file)
_, err := parser.ParseFile(fset, path, nil, parser.AllErrors)
if err != nil {
logrus.Println(err)
return nil
}
// 打印语法树 ast.Print(fset, f.Scope.Objects)
var fi = &dimeta.FileInfoDto{
//AstFile: f,
PathFile: path,
}
return fi
}
func (this *DimetaFactroy) FindGoFile(stru string) *dimeta.FileInfoDto {
this.FindGoFiles()
for _, fi := range this.FileInfoDtos {
if strings.Contains(fi.PathFile, stru) {
return fi
}
}
return nil
}
func (this *DimetaFactroy) FindGoFiles() error {
// 指定需要遍历的目录
dirPath := this.Rootdir
// 使用filepath.Walk遍历目录
err := filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
if err != nil {
logrus.Error(err)
return err
}
// 如果是文件,可以进行额外操作,比如读取文件内容
if !info.IsDir() {
if !strings.HasSuffix(path, "_test.go") &&
strings.HasSuffix(path, ".go") {
var somepath = strings.Split(path, this.Rootdir)
var some = strings.Replace(path, this.Rootdir, "", -1)
var file = dimeta.NewFileInfoDto()
file.PathFile = this.Rootdir + some
if len(somepath) > 1 {
this.FileInfoDtos = append(this.FileInfoDtos, file)
}
}
}
// 返回nil继续遍历
return nil
})
if err != nil {
logrus.Error("Error walking the path:", err)
}
return err
}
func (this *DimetaFactroy) ParseDir(pathf string) {
path, _ := filepath.Abs(pathf)
fset := token.NewFileSet()
pkgs, err := parser.ParseDir(fset, path, nil, parser.ParseComments)
if err != nil {
logrus.Error(err)
return
}
if pkgs == nil {
pkgs = map[string]*ast.Package{}
}
logrus.Error(path)
}
//func CurrentFile() string {
// _, pathfile, _, ok := runtime.Caller(1)
// if !ok {
// panic(errors.New("Can not get current pathfile info"))
// }
// return pathfile
//}
func (this *DimetaFactroy) FindSome(struname string) (*dimeta.FileInfoDto, bool) {
for _, fileInfoDto := range this.FileInfoDtos {
for _, structInfo := range fileInfoDto.StructInfos {
if structInfo.StructName == struname {
return fileInfoDto, true
}
}
}
return nil, false
}
func (this *DimetaFactroy) GoastOne(stru string) (*dimeta.FileInfoDto, bool) {
this.GoastAll()
var fi, ok = this.FindSome(stru)
if !ok {
logrus.Error("no found")
return nil, ok
}
var fileinfo = this.Parse(fi.PathFile)
this.FileInfoDtos = append(this.FileInfoDtos, fileinfo)
for _, structInfo := range fileinfo.StructInfos {
fi.StructInfoMap[structInfo.PkgName+"::"+structInfo.StructName] = structInfo
this.WriteGoastFile(structInfo)
}
return fi, ok
}
func (this *DimetaFactroy) GoastAll() {
this.FindGoFiles()
for _, fileInfoDto := range this.FileInfoDtos {
var fileinfo = this.Parse(fileInfoDto.PathFile)
this.FileInfoDtos = append(this.FileInfoDtos, fileinfo)
for _, structInfo := range fileinfo.StructInfos {
fileInfoDto.StructInfoMap[structInfo.PkgName+"::"+structInfo.StructName] = structInfo
}
}
this.Save2JSONFile()
this.SaveFile2JSONFile()
}
func (this *DimetaFactroy) Save2JSONFile() {
var path = this.Rootdir + dataOutputDiStruct
os.Remove(path)
os.MkdirAll(path, os.ModePerm)
for _, v := range this.StructInfos {
if !v.IsBaseEntiyStruct {
continue
}
var jsonStr = jsonutils.ToJsonPretty(v)
var fileName = v.StructName + ".json"
var filePath = path + "/" + fileName
fileutil.WriteBytesToFile(filePath, []byte(jsonStr))
logrus.Info(filePath)
}
}
func (this *DimetaFactroy) SaveFile2JSONFile() {
var path = this.Rootdir + dataOutputDiFile
os.Remove(path)
os.MkdirAll(path, os.ModePerm)
for _, v := range this.FileInfoDtos {
var filePath = path + "/" + filepath.Base(v.PathFile) + ".json"
filePath = strings.Replace(filePath, ".go", "", -1)
fileutil.WriteBytesToFile(filePath, v.ToJsonBytes())
logrus.Info(filePath)
}
}
func (this *DimetaFactroy) ParseFuncs(FileInf *dimeta.FileInfoDto, nodes *ast.File) {
ast.Inspect(nodes, func(node ast.Node) bool {
switch funcDecl := node.(type) {
case *ast.FuncDecl:
logrus.Info("Function:", funcDecl.Name.Name)
var funcDefine = dimeta.NewFuncDefine(funcDecl.Name.Name)
if funcDecl.Recv != nil {
funcDefine.StruName = funcDecl.Recv.List[0].Type.(*ast.StarExpr).X.(*ast.Ident).Name
}
if funcDecl.Type.Params != nil {
// 打印参数列表
logrus.Println("参数:", funcDecl.Type.Params.List)
funcDefine.Params = funcDecl.Type.Params.List
funcDefine.ParamsCount = len(funcDecl.Type.Params.List)
} else {
funcDefine.ParamsCount = 0
}
if funcDecl.Type.Results != nil {
// 如果函数有结果列表(返回值),则打印
if funcDecl.Type.Results != nil {
logrus.Println("返回值:", funcDecl.Type.Results.List)
funcDefine.Results = funcDecl.Type.Results.List
}
}
FileInf.FuncDefines = append(FileInf.FuncDefines, funcDefine)
}
return true
})
}
func (this *DimetaFactroy) ParseImports(FileInf *dimeta.FileInfoDto, nodes *ast.File) {
// 遍历AST中的所有声明
ast.Inspect(nodes, func(n ast.Node) bool {
switch x := n.(type) {
case *ast.ImportSpec:
// 获取import路径
path, err := strconv.Unquote(x.Path.Value)
if err != nil {
panic(err)
}
fmt.Println("Imported package:", path)
FileInf.ImportedLibs = append(FileInf.ImportedLibs, path)
}
// 继续遍历子节点
return true
})
}
func (this *DimetaFactroy) ParseTags(stru *dimeta.StructInfo, nodes *ast.File) {
// 遍历 AST,查找结构体定义
ast.Inspect(nodes, func(n ast.Node) bool {
if typeSpec, ok := n.(*ast.TypeSpec); ok {
if structType, ok := typeSpec.Type.(*ast.StructType); ok {
// 遍历结构体字段
for _, field := range structType.Fields.List {
// 检查字段是否有标签
if field.Tag != nil {
// 提取标签的内容
tag := reflect.StructTag(strings.Trim(field.Tag.Value, "`"))
logrus.Println("Tag:", tag)
}
}
}
}
return true
})
}
func (this *DimetaFactroy) ParseStruct(decl *ast.GenDecl, nodes *ast.File, pathfile string) *dimeta.StructInfo {
if decl.Tok != token.TYPE {
return nil
}
if len(decl.Specs) != 1 {
return nil
}
spec, ok := decl.Specs[0].(*ast.TypeSpec)
if !ok {
return nil
}
structType, ok1 := spec.Type.(*ast.StructType)
if !ok1 {
logrus.Error("处理失败!!!", structType)
return nil
}
structInfo := dimeta.NewStructInfo()
structInfo.StructName = spec.Name.Name
structInfo.PkgName = nodes.Name.Name
structInfo.PathFile = pathfile
var diInjects = structInfo.DiInjects
var fields = []string{}
var parsefields = dimeta.NewParseFields()
for _, field := range structType.Fields.List {
var di = parsefields.Parse(field)
if len(di.MemberName) > 0 {
diInjects[di.MemberName] = di
di.SetInjectMod(strings.Contains(di.MemberName, diconsts.BaseEntity))
fields = append(fields, di.MemberName)
}
if field.Tag != nil {
di.ParseTag(field)
}
}
structInfo.Fields = fields
structInfo.CheckBaseEntity()
structInfo.DiInjects = diInjects
structInfo.ParsePkgName(this.Rootdir, this.BasePkg)
this.StructInfos[structInfo.StructName] = structInfo
return structInfo
}
func (this *DimetaFactroy) ParseMethods(decl *ast.FuncDecl) {
structName := ""
switch decl.Recv.List[0].Type.(type) {
case *ast.StarExpr: //指针方法
structName = decl.Recv.List[0].Type.(*ast.StarExpr).X.(*ast.Ident).Name
case *ast.Ident: //普通方法 //
structName = decl.Recv.List[0].Type.(*ast.Ident).Name
}
if structInfo, ok := this.StructInfos[structName]; ok {
structInfo.MethodNames = append(structInfo.MethodNames, decl.Name.Name)
}
}
func (this *DimetaFactroy) ExistNewMethod(nodes *ast.File, functionName string) bool {
var found = false
for _, obj := range nodes.Scope.Objects {
decl, ok := obj.Decl.(*ast.FuncDecl)
if ok {
if decl.Name.Name == functionName {
found = true
if decl.Type.Params != nil && len(decl.Type.Params.List) > 0 {
found = false
}
}
}
}
return found
}
func (this *DimetaFactroy) findNewFunc(node *ast.File, functionName string) bool {
found := false
ast.Inspect(node, func(n ast.Node) bool {
if fd, ok := n.(*ast.FuncDecl); ok {
if fd.Name.Name == functionName {
found = true
if fd.Type.Params != nil {
found = false
}
return false // 停止遍历
}
}
return true
})
return found
}
func (this *DimetaFactroy) Parse(file string) *dimeta.FileInfoDto {
var fileinfo = dimeta.NewFileInfoDto()
path, _ := filepath.Abs(file)
fset := token.NewFileSet()
nodes, err := parser.ParseFile(fset, path, nil, parser.ParseComments)
if err != nil {
logrus.Error(err)
return fileinfo
}
// 找方法
for i := 0; i < len(nodes.Decls); i++ {
decl, ok := nodes.Decls[i].(*ast.FuncDecl)
if !ok {
continue
}
if decl.Recv == nil || len(decl.Recv.List) != 1 {
continue
}
this.ParseMethods(decl)
}
this.ParseFuncs(fileinfo, nodes)
structInfos := make([]*dimeta.StructInfo, 0)
for i := 0; i < len(nodes.Decls); i++ {
decl, ok := nodes.Decls[i].(*ast.GenDecl)
if !ok {
continue
}
var stru = this.ParseStruct(decl, nodes, path)
if stru != nil {
fileinfo.ParseNewFunc(stru)
for _, v := range fileinfo.FuncDefines {
if v.StruName == stru.StructName {
stru.FuncDefines = append(stru.FuncDefines, v)
}
}
structInfos = append(structInfos, stru)
}
}
fileinfo.StructInfos = structInfos
fileinfo.PathFile = path
// 输出
logrus.Info(jsonutils.ToJsonPretty(fileinfo))
if len(fileinfo.StructInfos) == 0 {
logrus.Error("go文件或者结构体不存在!")
}
this.ParseImports(fileinfo, nodes)
this.SetImport2StructInfos(fileinfo)
return fileinfo
}
func (this *DimetaFactroy) SetImport2StructInfos(fileinfo *dimeta.FileInfoDto) {
for _, structInfo := range fileinfo.StructInfos {
structInfo.ImportedLibs = fileinfo.ImportedLibs
structInfo.ToInjectCode()
}
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/ichub/gomini.git
git@gitee.com:ichub/gomini.git
ichub
gomini
gomini
10e2095c6fe8

搜索帮助

344bd9b3 5694891 D2dac590 5694891