2025-05-08 17:33:46 +08:00

196 lines
4.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package errcode
import (
"flag"
"fmt"
"go/ast"
"go/token"
"golang.org/x/tools/go/packages"
"log"
"os"
"path/filepath"
"strconv"
"strings"
)
type File struct {
pkg *Package
fileName string
rawAstFile *ast.File
content string
importList map[string]struct{}
errcodeList *ErrCodeList
}
type Package struct {
Name string
rawAstPkg *packages.Package
rawAstFileSet *token.FileSet
files []*File
ImportList []string
}
func Generate() {
flag.Parse()
curRootDir, err := os.Getwd()
if err != nil {
log.Fatal(err)
}
log.Printf("================================================")
log.Printf("args: %v", os.Args[1:])
log.Printf("pwd: %v", curRootDir)
cfg := &packages.Config{
Mode: packages.NeedName | packages.NeedTypes | packages.NeedTypesInfo | packages.NeedSyntax | packages.NeedFiles,
Tests: true,
BuildFlags: []string{fmt.Sprintf("-tags=%s", strings.Join([]string{}, " "))},
Logf: func(format string, args ...interface{}) {
//log.Printf(format, args...)
},
}
rawPkgs, err := packages.Load(cfg, ".")
if err != nil {
log.Fatal(err)
}
if len(rawPkgs) == 0 {
log.Fatalf("当前包居然读取不到ast信息尝试项目根目录执行go mod tidy解决报错")
}
pkgs := make([]*Package, 0, len(rawPkgs))
firstPkgPath := ""
for i, pkg := range rawPkgs {
if i == 0 {
firstPkgPath = pkg.PkgPath
} else {
if strings.Contains(pkg.PkgPath, firstPkgPath) {
continue
}
}
p := &Package{
Name: pkg.Name,
rawAstPkg: pkg,
rawAstFileSet: pkg.Fset,
files: make([]*File, 0, len(pkg.Syntax)),
}
for j, file := range pkg.Syntax {
goFile := pkg.GoFiles[j]
if strings.HasSuffix(goFile, ".gen.go") {
continue
}
content, err := os.ReadFile(goFile)
if err != nil {
panic(err)
}
p.files = append(p.files, &File{
pkg: p,
fileName: filepath.Base(goFile),
rawAstFile: file,
content: string(content),
importList: make(map[string]struct{}),
})
}
pkgs = append(pkgs, p)
}
if len(pkgs) > 1 {
s := ""
for _, v := range pkgs {
s += v.rawAstPkg.Name + ","
log.Printf("pak:%v, gofiles:%v", v.rawAstPkg.PkgPath, v.rawAstPkg.GoFiles)
}
log.Fatalf("居然发现%v个包(%v),联系@李坤支持:", len(pkgs), s)
}
for _, pkg := range pkgs {
for _, file := range pkg.files {
file.errcodeList = &ErrCodeList{
List: make([]*ErrCode, 0),
}
ast.Inspect(file.rawAstFile, file.genDecl)
//log.Printf("after gen, file %v list len:%v", file.fileName, len(file.errcodeList.List))
if len(file.errcodeList.List) > 0 {
fileName := "code_content.gen.go"
outputFile := filepath.Join(curRootDir, fileName)
err := renderFile(file.errcodeList, tpl, outputFile)
if err != nil {
log.Printf("render file %v error:%v", fileName, err)
os.Exit(1)
}
}
}
}
}
// genDecl processes one declaration clause.
func (f *File) genDecl(node ast.Node) bool {
//log.Printf("node:%+v", node)
if f.pkg.Name != "errcode" {
return true
}
if f.fileName != "code.go" {
return true
}
if node == nil {
return true
}
fileSet := f.pkg.rawAstFileSet
fpos := fileSet.File(node.Pos())
fileNode, ok := node.(*ast.File)
if !ok {
return true
}
for _, v := range fileNode.Decls {
d := v.(*ast.GenDecl)
if d.Tok.String() != "const" {
continue
}
// 静态错误码
for _, spec := range d.Specs {
specValue := spec.(*ast.ValueSpec)
specContent := f.content[fpos.Offset(specValue.Pos()):fpos.Offset(specValue.End())]
specContent = strings.ReplaceAll(specContent, " ", "")
values := strings.Split(specContent, "=")
if len(values) != 2 {
log.Printf("错误码:%v 按等号分隔字符串之后不满足var=value格式", specContent)
os.Exit(1)
}
commentContent := specValue.Comment.Text()
commentContent = strings.ReplaceAll(commentContent, "\n", "")
if commentContent == "" {
log.Printf("错误码:%v 没有定义文本内容格式为ErrCode = 123 // <文本内容>", specContent)
os.Exit(1)
}
code, _ := strconv.Atoi(values[1])
f.errcodeList.List = append(f.errcodeList.List, &ErrCode{
Name: values[0],
Value: code,
Comment: commentContent,
})
//log.Printf("错误码:%v 值:%v --> 注释:%v\n", values[0], values[1], commentContent)
}
}
return true
}