scripts/inspectSet/inspectSet.go (197 lines of code) (raw):

package main import ( "fmt" "go/ast" "go/parser" "go/token" "os" "path/filepath" "strings" ) var TerraformProviderPath string type Node struct { name string child []*Node } func GetSchema(fileName string) *Node { file, _ := os.Open(fileName) fset := token.NewFileSet() node, _ := parser.ParseFile(fset, "", file, parser.AllErrors) var root *ast.KeyValueExpr ast.Inspect(node, func(n ast.Node) bool { if returnStmt, ok := n.(*ast.ReturnStmt); ok { results := returnStmt.Results if len(results) == 0 { return true } unaryExpr := results[0] if unaryExpr, ok := unaryExpr.(*ast.UnaryExpr); ok { if x, ok := unaryExpr.X.(*ast.CompositeLit); ok { elts := x.Elts for _, kvexpr := range elts { if Exprkv, ok := kvexpr.(*ast.KeyValueExpr); ok { if Exprk, ok := Exprkv.Key.(*ast.Ident); ok && Exprk.Name == "Schema" { root = Exprkv } } } } } } return true }) rootNode := new(Node) rootNode.child = make([]*Node, 0) dfs(root, rootNode) return rootNode } func GetDsetAttributes(fileName string) []string { attributes := make([]string, 0) file, _ := os.Open(fileName) fset := token.NewFileSet() node, _ := parser.ParseFile(fset, "", file, parser.AllErrors) ast.Inspect(node, func(n ast.Node) bool { if call, ok := n.(*ast.CallExpr); ok { if fun, ok := call.Fun.(*ast.SelectorExpr); ok { if x, ok := fun.X.(*ast.Ident); ok { if x.Name == "d" && fun.Sel.Name == "Set" { args := call.Args if len(args) == 2 { if attr, ok := args[0].(*ast.BasicLit); ok { value := attr.Value[1 : len(attr.Value)-1] attributes = append(attributes, value) } } } } } } return true }) ast.Inspect(node, func(n ast.Node) bool { if assignment, ok := n.(*ast.AssignStmt); ok { if len(assignment.Lhs) == 1 { if left, ok := assignment.Lhs[0].(*ast.Ident); ok { if left.Name == "mapping" { if len(assignment.Rhs) == 1 { if compositelit, ok := assignment.Rhs[0].(*ast.CompositeLit); ok { if typ, ok := compositelit.Type.(*ast.MapType); ok { if _, ok := typ.Value.(*ast.InterfaceType); ok { for _, elt := range compositelit.Elts { if kv, ok := elt.(*ast.KeyValueExpr); ok { if attr, ok := kv.Key.(*ast.BasicLit); ok { value := attr.Value[1 : len(attr.Value)-1] attributes = append(attributes, value) } } } } } } } } } } } return true }) return attributes } func dfs(left *ast.KeyValueExpr, leftNode *Node) { LeftValue, _ := left.Value.(*ast.CompositeLit) LeftElts := &LeftValue.Elts for _, leftAttribute := range *LeftElts { leftAttribute, _ := leftAttribute.(*ast.KeyValueExpr) //判断leftAttribute是文件节点还是目录节点 var ifSchema bool leftKey, _ := leftAttribute.Key.(*ast.BasicLit) leftAttributeValue, ok := leftAttribute.Value.(*ast.CompositeLit) if ok { elts := leftAttributeValue.Elts for i := 0; i < len(elts); i++ { if kv, ok := elts[i].(*ast.KeyValueExpr); ok { if k, ok := kv.Key.(*ast.Ident); ok && k.Name == "Elem" { ifSchema = true break } } } } childNode := new(Node) childNode.name = strings.TrimSuffix(strings.TrimPrefix(leftKey.Value, "\""), "\"") childNode.child = make([]*Node, 0) leftNode.child = append(leftNode.child, childNode) //如果是目录类型 if ifSchema { var leftChild *ast.KeyValueExpr //提取出左孩子 leftAttributeValue, _ := leftAttribute.Value.(*ast.CompositeLit) elts := leftAttributeValue.Elts for _, kvExpr := range elts { kvExpr := kvExpr.(*ast.KeyValueExpr) if kExpr, ok := kvExpr.Key.(*ast.Ident); ok && kExpr.Name == "Elem" { kExprValue := kvExpr.Value if unaryExpr, ok := kExprValue.(*ast.UnaryExpr); ok { x := unaryExpr.X.(*ast.CompositeLit) for _, e := range x.Elts { if leftchild, ok := e.(*ast.KeyValueExpr); ok { if leftchildKey, ok := leftchild.Key.(*ast.Ident); ok && leftchildKey.Name == "Schema" { leftChild = leftchild } } } } } } if leftChild != nil { dfs(leftChild, childNode) } } } } func main() { if len(os.Args) < 2 { fmt.Println("请传入一个参数:terraform项目地址") os.Exit(1) } TerraformProviderPath = os.Args[1] dirname := TerraformProviderPath + "/alibabacloudstack" // your directory containing Go source files f, _ := os.Create("output.txt") filepath.Walk(dirname, func(path string, info os.FileInfo, err error) error { if err != nil { return err } name := info.Name() if name == "data_source_apsarastack_common.go" { fmt.Println() } if !info.IsDir() && !strings.HasSuffix(path, "test.go") && strings.HasSuffix(path, "go") { // process only Go files if strings.HasPrefix(name, "data") || strings.HasPrefix(name, "resource") { testFilename := strings.TrimSuffix(path, ".go") testFilename = testFilename + "_test.go" _, err := os.Stat(testFilename) if err != nil { return nil } root := GetSchema(path) attributes := GetDsetAttributes(path) var dfs func(*Node, string) bool dfs = func(n *Node, s string) bool { if s == n.name { return true } for _, child := range n.child { if dfs(child, s) == true { return true } } return false } for _, attribute := range attributes { if !dfs(root, attribute) { fmt.Fprintln(f, path, attribute) } } } } return nil }) fmt.Println() }