Files
toolset/parser/goast.go
2024-04-12 15:54:05 +08:00

179 lines
4.9 KiB
Go
Raw Permalink 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 parser
import (
"go/ast"
"go/parser"
"go/token"
"io/ioutil"
"log"
"strings"
)
func NewAst(path string, skips ...map[string]bool) map[string][]GoFileParser {
got := make(map[string][]GoFileParser)
for _, dir := range GetChildrenDir(path, skips...) {
arr := make([]GoFileParser, 0)
for _, file := range dir.GetFiles(".go") {
if strings.Index(file.Name(), "_gen.go") != -1 {
continue
}
gof := getAstGoFileParser(file.Path)
arr = append(arr, gof)
}
got[dir.Path] = arr
}
return got
}
func getAstGoFileParser(fileName string) GoFileParser {
got := GoFileParser{
PackageName: "",
PackageDoc: "",
Imports: make(map[string]string),
Types: make(map[string]GoType),
Funds: make(map[string]GoFunc),
}
// 1. 读取文件内容
fileContent, err := ioutil.ReadFile(fileName)
if err != nil {
log.Fatalf("Error reading file: %v", err)
}
// 2. 创建一个token.FileSet用于保存位置信息
fset := token.NewFileSet()
// 3. 解析Go源代码
file, err := parser.ParseFile(fset, fileName, fileContent, parser.ParseComments)
if err != nil {
log.Fatal(err)
}
got.PackageName = file.Name.Name
// 4. 遍历AST并处理函数和变量
for _, decl := range file.Decls {
switch decl := decl.(type) {
case *ast.FuncDecl: // 处理函数声明
case *ast.GenDecl:
// 处理通用声明(变量声明)
switch decl.Tok {
case token.VAR:
case token.IMPORT: // import
for _, spec := range decl.Specs {
Spec := spec.(*ast.ImportSpec)
if Spec.Name == nil {
arr := strings.Split(Spec.Path.Value, "/")
got.Imports[strings.Trim(arr[len(arr)-1], "\"")] = strings.Trim(Spec.Path.Value, "\"")
} else {
got.Imports[Spec.Name.Name] = strings.Trim(Spec.Path.Value, "\"")
}
}
case token.CONST: // const 变量声明
case token.TYPE: // type 变量声明、结构
var doc string
if decl.Doc != nil {
for _, d := range decl.Doc.List {
doc = doc + d.Text + "\n"
}
} else {
// 没有注释, 跳过
continue
}
for _, spec := range decl.Specs {
Spec := spec.(*ast.TypeSpec)
TypeSpec, ok := Spec.Type.(*ast.StructType)
if ok {
t := GoType{
Doc: GoDoc(doc),
Name: Spec.Name.Name,
Attrs: map[string]GoTypeAttr{},
AttrsSort: make([]string, 0),
GoFileParser: &got,
}
for _, field := range TypeSpec.Fields.List {
attr := GoTypeAttr{GoFileParser: &got}
for _, name := range field.Names {
attr.Name = name.Name
}
if expr, ok := field.Type.(*ast.SelectorExpr); ok {
if attr.Name == "" {
attr.Name = strings.Trim(expr.Sel.Name, ".")
}
attr.TypeAlias = expr.X.(*ast.Ident).Name
attr.TypeName = attr.TypeAlias + "." + expr.Sel.Name
attr.TypeImport = got.Imports[attr.TypeAlias]
} else if expr, ok := field.Type.(*ast.Ident); ok {
if attr.Name == "" {
attr.Name = expr.Name
}
attr.TypeName = expr.Name
attr.InPackage = true
} else if expr, ok := field.Type.(*ast.MapType); ok {
if _, ok := expr.Key.(*ast.SelectorExpr); ok {
attr.TypeName = "map todo"
attr.InPackage = true
} else if iv, ok := expr.Key.(*ast.Ident); ok {
attr.TypeName = iv.Name
attr.InPackage = true
} else if iv, ok := expr.Key.(*ast.StarExpr); ok {
attr.TypeName = iv.X.(*ast.Ident).Name
attr.InPackage = true
}
} else if _, ok := field.Type.(*ast.ArrayType); ok {
attr.TypeName = "[]todo"
} else if _, ok := field.Type.(*ast.InterfaceType); ok {
attr.TypeName = "todointerface"
} else if expr, ok := field.Type.(*ast.StarExpr); ok {
if expr2, ok := expr.X.(*ast.SelectorExpr); ok {
if attr.Name == "" {
attr.Name = strings.Trim(expr2.Sel.Name, ".")
}
attr.TypeAlias = expr2.X.(*ast.Ident).Name
attr.TypeName = "*" + attr.TypeAlias + "." + expr2.Sel.Name
attr.TypeImport = got.Imports[attr.TypeAlias]
} else if expr2, ok := expr.X.(*ast.Ident); ok {
if attr.Name == "" {
attr.Name = expr2.Name
}
attr.TypeAlias = expr2.Name
attr.TypeName = "*" + expr2.Name
attr.InPackage = true
} else {
}
} else {
}
// 解析 go tag
attr.Tag = make(map[string]TagDoc)
if field.Tag != nil {
for _, tagStrArr := range getArrGoTag(field.Tag.Value) {
td := tagStrArr[1]
if len(td) > 1 {
attr.Tag[tagStrArr[0]] = TagDoc(td[1 : len(td)-1])
}
}
}
if attr.TypeName == "" {
continue
}
t.Attrs[attr.Name] = attr
t.AttrsSort = append(t.AttrsSort, attr.Name)
}
got.Types[Spec.Name.Name] = t
}
}
default:
}
default:
}
}
return got
}