github.com/Konstantin8105/c4go@v0.0.0-20240505174241-768bb1c65a51/unused.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "go/ast" 6 "go/parser" 7 "go/token" 8 "os" 9 "sort" 10 ) 11 12 func unused(filenames ...string) { 13 for _, src := range filenames { 14 fset := token.NewFileSet() // positions are relative to fset 15 16 // Parse src but stop after processing the imports. 17 f, err := parser.ParseFile(fset, src, nil, parser.ParseComments) 18 if err != nil { 19 fmt.Fprintf(os.Stderr, "%v", err) 20 return 21 } 22 23 // map 24 m := map[string][]string{} 25 26 // Print the imports from the file's AST. 27 for i := range f.Decls { 28 decls := f.Decls[i] 29 if fd, ok := decls.(*ast.FuncDecl); ok { 30 name := fd.Name.Name 31 var cs CallSearcher 32 ast.Walk(&cs, fd) 33 m[name] = cs.used 34 } 35 } 36 37 // list of all function 38 used := map[string]bool{} 39 list := []string{"main"} 40 41 for iter := len(m) * 10; iter > 0; iter-- { 42 rem: 43 sort.Strings(list) 44 for i := range list { 45 if i == 0 { 46 continue 47 } 48 if list[i-1] == list[i] { 49 // remove from list 50 list = append(list[:i], list[i+1:]...) 51 goto rem 52 } 53 } 54 for i := range list { 55 _, ok := used[list[i]] 56 if ok { 57 // remove from list 58 list = append(list[:i], list[i+1:]...) 59 goto rem 60 } 61 } 62 var newlist []string 63 for k, v := range m { 64 for i := range list { 65 used[list[i]] = true 66 if k == list[i] { 67 used[k] = true 68 newlist = append(newlist, v...) 69 } 70 } 71 } 72 list = newlist 73 } 74 75 // full list 76 full := map[string]bool{} 77 for k, v := range m { 78 full[k] = true 79 for i := range v { 80 full[v[i]] = true 81 } 82 } 83 84 // unused 85 for k := range full { 86 _, ok := used[k] 87 if ok { 88 continue 89 } 90 fmt.Fprintf(os.Stdout, "%s\n", k) 91 } 92 } 93 } 94 95 type CallSearcher struct { 96 used []string 97 } 98 99 var GoFuncs = []string{ 100 "len", "make", "append", 101 "string", 102 "float64", "float32", 103 "int", "int64", "int32", "int16", 104 "go", "close", 105 "panic", 106 } 107 108 func (c *CallSearcher) Visit(node ast.Node) (w ast.Visitor) { 109 if call, ok := node.(*ast.CallExpr); ok { 110 if f, ok := call.Fun.(*ast.Ident); ok { 111 isFound := false 112 for i := range GoFuncs { 113 if f.Name == GoFuncs[i] { 114 isFound = true 115 } 116 } 117 if !isFound { 118 c.used = append(c.used, f.Name) 119 } 120 } 121 } 122 return c 123 } 124 125 func search(f *ast.FuncDecl) (used []string) { 126 127 return 128 }