package main import ( "encoding/json" "go/ast" "go/parser" "go/token" "io/fs" "log" "os" "path" "path/filepath" "sort" "strings" ) func main() { results := Functions{} // Parse filepath.Walk("./kubernetes", func(file string, info fs.FileInfo, err error) error { if err != nil { return err } if info.IsDir() { return nil } if path.Ext(file) != ".go" { return nil } for _, s := range []string{ "fake", // test code "test", // test code "zz_generated", // generated code "generated", // generated code "api.pb.go", // generated code "vendor", // external libs "third_party", // external libs "sample", // example code "example", } { if strings.Contains(file, s) { return nil } } results = append(results, parseSrc(file)...) return nil }) // Sort sort.Sort(results) // Print repoId := 1 /* id of the kubernetes/kubernetes@v1.27.4 */ id := repoId * 100_000_000 for _, f := range results { f.ID = uint64(id) id += 1 json.NewEncoder(os.Stdout).Encode(f) } } func parseSrc(filename string) []Function { s, err := os.ReadFile(filename) if err != nil { panic(err) // there will be no err } lines := strings.Split(string(s), "\n") f := []Function{} fset := token.NewFileSet() node, err := parser.ParseFile(fset, filename, nil, parser.ParseComments) if err != nil { log.Fatalf("Error parsing file: %v", err) } for _, decl := range node.Decls { switch d := decl.(type) { case *ast.FuncDecl: start := fset.Position(d.Pos()).Line if d.Doc != nil { start = fset.Position(d.Doc.Pos()).Line } end := fset.Position(d.End()).Line signature_pos := fset.Position(d.Name.Pos()).Line signature, _ := strings.CutSuffix(lines[signature_pos-1], " {") f = append(f, Function{ Name: d.Name.Name, Signature: signature, Line: FunctionPos{ From: start, To: end, }, File: filename[11:], Code: strings.Join(lines[start-1:end], "\n"), }) } } return f }