package service import ( "go/ast" "strings" ) func handleFuncDecl(decl ast.Decl) string { fd := decl.(*ast.FuncDecl) 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 += ") {" code += handleBlockStmt(fd.Body) code += "}" 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) } return code } func handleFuncDeclName(ident *ast.Ident) string { code := "" if ident == nil { return code } code += ident.Name if val, ok := mapping[code]; ok { code = val } return code } 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 := "" switch ft := field.Type.(type) { case *ast.Ident: ftype = handleIdentExpr(ft) } for _, names := range field.Names { values = append(values, ftype+" "+names.Name) } } code += strings.Join(values, ",") return code } func addFunctionDeclaration(f string) { dlock.Lock() defer dlock.Unlock() funcDeclarations = append(funcDeclarations, f) }