161 строка
2,6 КиБ
Go
161 строка
2,6 КиБ
Go
package service
|
|
|
|
import (
|
|
"fmt"
|
|
"go/ast"
|
|
"strings"
|
|
)
|
|
|
|
var (
|
|
inFunctionDepth = 0
|
|
)
|
|
|
|
func incInFunctionDepth() {
|
|
inFunctionDepth++
|
|
}
|
|
func decInFunctionDepth() {
|
|
inFunctionDepth--
|
|
if inFunctionDepth < 0 {
|
|
panic(fmt.Sprintf("inFunctionDepth: %v", inFunctionDepth))
|
|
}
|
|
}
|
|
func IsInFunction() bool {
|
|
return inFunctionDepth > 0
|
|
}
|
|
|
|
func handleFuncDecl(decl ast.Decl) string {
|
|
incInFunctionDepth()
|
|
defer decInFunctionDepth()
|
|
|
|
fd := decl.(*ast.FuncDecl)
|
|
if fd.Recv != nil {
|
|
return handleMethodDeclaration(fd)
|
|
}
|
|
return handleFunctionDeclaration(fd)
|
|
}
|
|
func handleFunctionDeclaration(fd *ast.FuncDecl) string {
|
|
if shouldSkipFunction(fd.Type) {
|
|
return ""
|
|
}
|
|
code := ""
|
|
name := ""
|
|
ft := handleFuncDeclType(fd.Type)
|
|
code += ft
|
|
code += " "
|
|
name = handleFuncDeclName(fd.Name)
|
|
if name == "NewController" {
|
|
return ""
|
|
}
|
|
code += name
|
|
code += "("
|
|
fp := handleFuncDeclParams(fd.Type)
|
|
code += fp
|
|
|
|
addFunctionDeclaration(ft + " " + name + "(" + fp + ");")
|
|
|
|
code += ") {\n"
|
|
code += handleBlockStmt(fd.Body)
|
|
code += "}\n"
|
|
return code
|
|
}
|
|
func shouldSkipFunction(t *ast.FuncType) (res bool) {
|
|
r := t.Results
|
|
if r == nil {
|
|
return
|
|
}
|
|
|
|
l := r.List
|
|
if len(l) != 1 {
|
|
return
|
|
}
|
|
|
|
p := l[0]
|
|
if p == nil {
|
|
return
|
|
}
|
|
|
|
pt := p.Type
|
|
if pt == nil {
|
|
return
|
|
}
|
|
|
|
i, ok := pt.(*ast.Ident)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
if i.Name == "ShouldBeSkipped" {
|
|
return true
|
|
}
|
|
return
|
|
}
|
|
|
|
func handleFuncDeclType(t *ast.FuncType) string {
|
|
code := ""
|
|
if t.Results == nil {
|
|
return "void"
|
|
}
|
|
|
|
fl := t.Results
|
|
if fl.NumFields() == 0 {
|
|
panic("handleFuncDeclType: fl.NumFields() == 0")
|
|
}
|
|
|
|
switch ft := fl.List[0].Type.(type) {
|
|
case *ast.Ident:
|
|
code += handleIdentExpr(ft)
|
|
case *ast.StarExpr:
|
|
code += handleStarExpr(ft)
|
|
code += "*"
|
|
}
|
|
|
|
return code
|
|
}
|
|
|
|
func handleFuncDeclName(ident *ast.Ident) (code string) {
|
|
if ident == nil {
|
|
return
|
|
}
|
|
code += ident.Name
|
|
if val, ok := mapping[code]; ok {
|
|
code = val
|
|
}
|
|
return
|
|
}
|
|
|
|
func handleFuncDeclParams(t *ast.FuncType) string {
|
|
code := ""
|
|
if t.Params == nil || t.Params.List == nil {
|
|
return code
|
|
}
|
|
values := make([]string, 0)
|
|
for _, field := range t.Params.List {
|
|
ftype := ""
|
|
star := false
|
|
switch ft := field.Type.(type) {
|
|
case *ast.Ident:
|
|
ftype = handleIdentExpr(ft)
|
|
case *ast.StarExpr:
|
|
ftype = handleStarExpr(ft)
|
|
star = true
|
|
}
|
|
for _, names := range field.Names {
|
|
n := ftype
|
|
if star {
|
|
n += "*"
|
|
}
|
|
n += " "
|
|
n += names.Name
|
|
values = append(values, n)
|
|
}
|
|
}
|
|
code += strings.Join(values, ",")
|
|
return code
|
|
}
|
|
|
|
func addFunctionDeclaration(f string) {
|
|
dlock.Lock()
|
|
defer dlock.Unlock()
|
|
|
|
funcDeclarations = append(funcDeclarations, f)
|
|
}
|