scripts/inspectRequest/scanFile.go (242 lines of code) (raw):
package main
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
"os"
"path/filepath"
"strings"
)
func GetApisFromScanFiles() []*Api {
dirname := "../../alibabacloudstack" // your directory containing Go source files
apis := make([]*Api, 0)
err := filepath.Walk(dirname, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
name := info.Name()
if !info.IsDir() && strings.HasSuffix(path, ".go") && !strings.HasSuffix(path, "test.go") { // process only Go files
if strings.HasPrefix(name, "resource") || strings.HasPrefix(name, "data") || strings.HasPrefix(name, "service") {
scanFile(path, &apis)
}
}
return nil
})
if err != nil {
fmt.Println(err)
return nil
}
//Printing the results
// for _, api := range apis {
// fmt.Printf("%s\n", api.FileName)
// fmt.Printf("%s\n", api.Name)
// fmt.Printf("%s\n", api.Product)
// fmt.Printf("Requests:\n")
// for _, req := range api.Requests {
// fmt.Printf("\t%s\n", req.Name)
// }
// fmt.Printf("Responses:\n")
// for _, resp := range api.Responses {
// fmt.Printf("\t%s\n", resp.Name)
// }
// }
return apis
}
func scanFile(filename string, apis *[]*Api) {
fs := token.NewFileSet()
node, err := parser.ParseFile(fs, filename, nil, parser.AllErrors)
if err != nil {
fmt.Println(err)
return
}
// 扫描高阶sdk
ast.Inspect(node, func(n ast.Node) bool {
fn, ok := n.(*ast.FuncDecl)
if !ok || fn.Body == nil {
return true
}
var api *Api
requestParams := make(map[string]bool)
ast.Inspect(fn.Body, func(n ast.Node) bool {
switch block := n.(type) {
case *ast.BlockStmt:
for _, stmt := range block.List {
if assignStmt, ok := stmt.(*ast.AssignStmt); ok {
var fnName, pkName string
leftExpr := assignStmt.Lhs[0]
rightExpr := assignStmt.Rhs[0]
call, ok := rightExpr.(*ast.CallExpr)
if ok {
fnName = getFuncName(call)
pkName = getPackageName(call)
}
//部分不规范的product
if pkName == "cr_ee" {
pkName = "cr"
}
if pkName == "r_kvstore" {
pkName = "R-kvstore"
}
if pkName == "slsPop" {
pkName = "Sls"
}
if strings.HasPrefix(fnName, "Create") && strings.HasSuffix(fnName, "Request") {
if api != nil {
for param := range requestParams {
api.Requests = append(api.Requests, Parm{Name: param})
}
if len(api.Requests) > 0 {
if api.name != "" && api.Product != "" {
*apis = append(*apis, api)
}
}
api = nil
requestParams = make(map[string]bool)
}
api = new(Api)
api.Type = "high"
api.Name = fnName[6 : len(fnName)-7] // Extract the core part of the function name.
api.name = api.Name
api.Product = pkName
api.FileName = filename
continue
} else {
selExpr, ok := leftExpr.(*ast.SelectorExpr)
if !ok {
continue
}
xIdent, ok := selExpr.X.(*ast.Ident)
if ok && xIdent.Name == "request" {
if selExpr.Sel.Name != "IaasProvider" && selExpr.Sel.Name != "Headers" && selExpr.Sel.Name != "QueryParams" && selExpr.Sel.Name != "RegionId" && selExpr.Sel.Name != "Schema" {
requestParams[selExpr.Sel.Name] = true
}
}
}
}
}
}
return true
})
if api != nil {
for param := range requestParams {
api.Requests = append(api.Requests, Parm{Name: param})
}
if len(api.Requests) > 0 {
if api.name != "" && api.Product != "" {
*apis = append(*apis, api)
}
}
api = nil
requestParams = make(map[string]bool)
}
return true
})
//扫描common sdk
ast.Inspect(node, func(n ast.Node) bool {
switch x := n.(type) {
case *ast.BlockStmt:
for _, stmt := range x.List {
if assignStmt, ok := stmt.(*ast.AssignStmt); ok {
for _, rhs := range assignStmt.Rhs {
call, ok := rhs.(*ast.CallExpr)
var pkName, fnName string
if ok {
fnName = getFuncName(call)
pkName = getPackageName(call)
}
//部分不规范的product
if pkName == "cr_ee" {
pkName = "cr"
}
if pkName == "r_kvstore" {
pkName = "R-kvstore"
}
if pkName == "slsPop" {
pkName = "Sls"
}
if fnName == "NewCommonRequest" {
var api = new(Api)
api.Type = "common"
api.FileName = filename
requestParams := make(map[string]bool)
for _, stmt := range x.List {
if assignStmt, ok := stmt.(*ast.AssignStmt); ok {
if lhs, ok := assignStmt.Lhs[0].(*ast.SelectorExpr); ok {
if lhs.Sel.Name == "QueryParams" {
rhs, ok := assignStmt.Rhs[0].(*ast.CompositeLit)
if !ok {
continue
}
elts := rhs.Elts
for _, e := range elts {
kv := e.(*ast.KeyValueExpr)
k := kv.Key.(*ast.BasicLit)
request := k.Value[1 : len(k.Value)-1]
if request == "AccessKeyId" || request == "RegionId" || request == "AccessKeySecret" || request == "Product" || request == "Action" || request == "Version" || request == "ProductName" || request == "Department" || request == "ResourceGroup" {
continue
}
if request == "X-acs-body" || request == "SignatureVersion" || request == "Language" || request == "SignatureMethod" || request == "AccountInfo" {
continue
}
requestParams[request] = true
}
} else if lhsx, ok := lhs.X.(*ast.Ident); ok && lhsx.Name == "request" {
if rhs, ok := assignStmt.Rhs[0].(*ast.BasicLit); ok {
value := rhs.Value[1 : len(rhs.Value)-1]
if lhs.Sel.Name == "ApiName" {
api.name = value
api.Name = value
}
if lhs.Sel.Name == "Product" {
api.Product = value
}
if lhs.Sel.Name == "Version" {
api.Version = value
}
}
}
}
}
}
for param := range requestParams {
api.Requests = append(api.Requests, Parm{Name: param})
}
if len(api.Requests) > 0 {
if api.name != "" && api.Product != "" {
*apis = append(*apis, api)
}
}
}
}
}
}
}
return true
})
/*
//扫描tea sdk
ast.Inspect(node, func(n ast.Node) bool {
switch x := n.(type) {
case *ast.BlockStmt:
var api = new(Api)
requestParams := make(map[string]bool)
for _, stmt := range x.List {
if assignStmt, ok := stmt.(*ast.IfStmt); ok {
x := assignStmt.Body
for _, stmt := range x.List {
if assignStmt, ok := stmt.(*ast.AssignStmt); ok {
if lhs, ok := assignStmt.Lhs[0].(*ast.Ident); ok {
if lhs.Name == "response" {
if rhs, ok := assignStmt.Rhs[0].(*ast.CallExpr); ok {
if len(rhs.Args) == 8 {
args := rhs.Args[3]
if args2, ok := args.(*ast.CallExpr); ok {
if version, ok := args2.Args[0].(*ast.BasicLit); ok {
api.Version = version.Value[1 : len(version.Value)-1]
}
}
}
}
}
}
}
}
}
if assignStmt, ok := stmt.(*ast.AssignStmt); ok {
for _, rhs := range assignStmt.Rhs {
lhs := assignStmt.Lhs[0]
request, ok := lhs.(*ast.Ident)
if !ok {
continue
}
var fun *ast.Ident
call, ok1 := rhs.(*ast.CallExpr)
_, ok2 := rhs.(*ast.CompositeLit)
if ok1 {
fun, ok = call.Fun.(*ast.Ident)
if !ok {
continue
}
}
if ((ok1 && fun.Name == "make") || (ok2)) && request.Name == "request" {
api.Type = "tea"
api.FileName = filename
for _, stmt := range x.List {
if assignStmt, ok := stmt.(*ast.AssignStmt); ok {
if lhs, ok := assignStmt.Lhs[0].(*ast.Ident); ok {
if lhs.Name == "action" {
if rhs, ok := assignStmt.Rhs[0].(*ast.BasicLit); ok {
value := rhs.Value[1 : len(rhs.Value)-1]
api.name = value
api.Name = value
continue
}
} else if lhs.Name == "response" {
if rhs, ok := assignStmt.Rhs[0].(*ast.CallExpr); ok {
args := rhs.Args[3]
if args2, ok := args.(*ast.CallExpr); ok {
if version, ok := args2.Args[0].(*ast.BasicLit); ok {
api.Version = version.Value[1 : len(version.Value)-1]
}
}
}
}
}
lhs = assignStmt.Lhs[0]
lhs, ok := lhs.(*ast.IndexExpr)
if !ok {
continue
}
x := lhs.X
x1, ok := x.(*ast.Ident)
if !ok {
continue
}
index := lhs.Index
index1, ok := index.(*ast.BasicLit)
if !ok {
continue
}
if x1.Name == "request" {
attribute := index1.Value[1 : len(index1.Value)-1]
if attribute == "Product" {
if rhs, ok := assignStmt.Rhs[0].(*ast.BasicLit); ok {
value := rhs.Value[1 : len(rhs.Value)-1]
api.Product = value
}
} else {
request := attribute
if request == "AccessKeyId" || request == "RegionId" || request == "AccessKeySecret" || request == "Product" || request == "Action" || request == "Version" || request == "ProductName" || request == "Department" || request == "ResourceGroup" {
continue
}
if request == "X-acs-body" || request == "SignatureVersion" || request == "Language" || request == "SignatureMethod" || request == "AccountInfo" {
continue
}
requestParams[request] = true
}
}
}
}
}
}
}
}
for param := range requestParams {
api.Requests = append(api.Requests, Parm{Name: param})
}
if len(api.Requests) > 0 {
if api.name != "" && api.Product != "" && api.Version != "" {
*apis = append(*apis, api)
}
}
}
return true
})*/
}
func getFuncName(call *ast.CallExpr) string {
switch fn := call.Fun.(type) {
case *ast.Ident:
return fn.Name
case *ast.SelectorExpr:
return fn.Sel.Name
default:
return ""
}
}
func getPackageName(call *ast.CallExpr) string {
switch fn := call.Fun.(type) {
case *ast.SelectorExpr:
if ident, ok := fn.X.(*ast.Ident); ok {
return ident.Name
}
}
return ""
}
func inspectRequest(stmt ast.Stmt, requestParams map[string]bool) {
ast.Inspect(stmt, func(n ast.Node) bool {
switch x := n.(type) {
case *ast.AssignStmt:
for _, lhs := range x.Lhs {
selExpr, ok := lhs.(*ast.SelectorExpr)
if !ok {
continue
}
xIdent, ok := selExpr.X.(*ast.Ident)
if ok && xIdent.Name == "request" {
if selExpr.Sel.Name != "IaasProvider" && selExpr.Sel.Name != "Headers" {
requestParams[selExpr.Sel.Name] = true
}
}
}
case *ast.IfStmt:
for _, stmt := range x.Body.List {
inspectRequest(stmt, requestParams)
}
}
return true
})
}