mirror of
https://gitee.com/johng/gf
synced 2026-06-07 02:12:11 +08:00
enhance: improve gf gen ctrl using AST (#3470)
This commit is contained in:
@ -9,15 +9,13 @@ package genctrl
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||
"github.com/gogf/gf/v2/container/gset"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/text/gregex"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"github.com/gogf/gf/v2/util/gtag"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -38,7 +36,6 @@ gf gen ctrl
|
||||
)
|
||||
|
||||
const (
|
||||
PatternApiDefinition = `type[\s\(]+(\w+)Req\s+struct\s+{([\s\S]+?)}`
|
||||
PatternCtrlDefinition = `func\s+\(.+?\)\s+\w+\(.+?\*(\w+)\.(\w+)Req\)\s+\(.+?\*(\w+)\.(\w+)Res,\s+\w+\s+error\)\s+{`
|
||||
)
|
||||
|
||||
@ -146,7 +143,11 @@ func (c CGenCtrl) generateByWatchFile(watchFile, sdkPath string, sdkStdVersion,
|
||||
}
|
||||
// watch file should have api definitions.
|
||||
if gfile.Exists(watchFile) {
|
||||
if !gregex.IsMatchString(PatternApiDefinition, gfile.GetContents(watchFile)) {
|
||||
structsInfo, err := c.getStructsNameInSrc(watchFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(structsInfo) == 0 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,6 +7,12 @@
|
||||
package genctrl
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/printer"
|
||||
"go/token"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/text/gregex"
|
||||
@ -14,10 +20,7 @@ import (
|
||||
)
|
||||
|
||||
func (c CGenCtrl) getApiItemsInSrc(apiModuleFolderPath string) (items []apiItem, err error) {
|
||||
var (
|
||||
fileContent string
|
||||
importPath string
|
||||
)
|
||||
var importPath string
|
||||
// The second level folders: versions.
|
||||
apiVersionFolderPaths, err := gfile.ScanDir(apiModuleFolderPath, "*", false)
|
||||
if err != nil {
|
||||
@ -37,20 +40,13 @@ func (c CGenCtrl) getApiItemsInSrc(apiModuleFolderPath string) (items []apiItem,
|
||||
if gfile.IsDir(apiFileFolderPath) {
|
||||
continue
|
||||
}
|
||||
fileContent = gfile.GetContents(apiFileFolderPath)
|
||||
matches, err := gregex.MatchAllString(PatternApiDefinition, fileContent)
|
||||
structsInfo, err := c.getStructsNameInSrc(apiFileFolderPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, match := range matches {
|
||||
var (
|
||||
methodName = match[1]
|
||||
structBody = match[2]
|
||||
)
|
||||
// ignore struct name that match a request, but has no g.Meta in its body.
|
||||
if !gstr.Contains(structBody, `g.Meta`) {
|
||||
continue
|
||||
}
|
||||
for _, methodName := range structsInfo {
|
||||
// remove end "Req"
|
||||
methodName = gstr.TrimRightStr(methodName, "Req", 1)
|
||||
item := apiItem{
|
||||
Import: gstr.Trim(importPath, `"`),
|
||||
FileName: gfile.Name(apiFileFolderPath),
|
||||
@ -143,3 +139,41 @@ func (c CGenCtrl) getApiItemsInDst(dstFolder string) (items []apiItem, err error
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// getStructsNameInSrc retrieves all struct names
|
||||
// that end in "Req" and have "g.Meta" in their body.
|
||||
func (c CGenCtrl) getStructsNameInSrc(filePath string) (structsName []string, err error) {
|
||||
var (
|
||||
fileContent = gfile.GetContents(filePath)
|
||||
fileSet = token.NewFileSet()
|
||||
)
|
||||
|
||||
node, err := parser.ParseFile(fileSet, "", fileContent, parser.ParseComments)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ast.Inspect(node, func(n ast.Node) bool {
|
||||
if typeSpec, ok := n.(*ast.TypeSpec); ok {
|
||||
methodName := typeSpec.Name.Name
|
||||
if !gstr.HasSuffix(methodName, "Req") {
|
||||
// ignore struct name that do not end in "Req"
|
||||
return true
|
||||
}
|
||||
if structType, ok := typeSpec.Type.(*ast.StructType); ok {
|
||||
var buf bytes.Buffer
|
||||
if err := printer.Fprint(&buf, fileSet, structType); err != nil {
|
||||
return false
|
||||
}
|
||||
// ignore struct name that match a request, but has no g.Meta in its body.
|
||||
if !gstr.Contains(buf.String(), `g.Meta`) {
|
||||
return true
|
||||
}
|
||||
structsName = append(structsName, methodName)
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user