Last active
February 15, 2023 09:59
-
-
Save paralin/5fda551c7740592869dc0f0b54c18d6f to your computer and use it in GitHub Desktop.
ChatGPT is kind of crazy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Written by ChatGPT w/ prompts from @paralin | |
| package main | |
| import ( | |
| "bytes" | |
| "flag" | |
| "fmt" | |
| "go/ast" | |
| "go/format" | |
| "go/parser" | |
| "go/token" | |
| "log" | |
| "os" | |
| "os/exec" | |
| "path/filepath" | |
| "strings" | |
| ) | |
| func main() { | |
| // Define command-line flags | |
| dirFlag := flag.String("dir", ".", "Directory containing the Git repository") | |
| flag.Parse() | |
| // Get the list of tracked files within the repository | |
| cmd := exec.Command("git", "ls-files") | |
| cmd.Dir = *dirFlag | |
| output, err := cmd.Output() | |
| if err != nil { | |
| log.Fatal(err) | |
| } | |
| trackedFiles := strings.Split(string(output), "\n") | |
| // Filter only the .go files | |
| goFiles := make([]string, 0) | |
| for _, file := range trackedFiles { | |
| if filepath.Ext(file) == ".go" { | |
| goFiles = append(goFiles, filepath.Join(*dirFlag, file)) | |
| } | |
| } | |
| // Process each Go file | |
| for _, file := range goFiles { | |
| if strings.HasSuffix(file, ".pb.go") || strings.HasSuffix(file, ".srpc.go") { | |
| continue | |
| } | |
| fmt.Printf("Processing file: %s\n", file) | |
| if err := refactorFile(file); err != nil { | |
| log.Printf("Failed to refactor file %s: %v", file, err) | |
| } | |
| } | |
| } | |
| func refactorFile(filename string) error { | |
| // Parse the Go file | |
| fset := token.NewFileSet() | |
| f, err := parser.ParseFile(fset, filename, nil, parser.ParseComments) | |
| if err != nil { | |
| return err | |
| } | |
| // Process each function declaration in the file | |
| for _, decl := range f.Decls { | |
| funcDecl, ok := decl.(*ast.FuncDecl) | |
| if !ok { | |
| continue | |
| } | |
| if funcDecl.Recv != nil || | |
| funcDecl.Type == nil || | |
| funcDecl.Type.Params == nil || | |
| funcDecl.Type.Results == nil || | |
| len(funcDecl.Type.Params.List) != 1 || | |
| len(funcDecl.Type.Results.List) != 2 { | |
| // Not a valid UnmarshalFoo function declaration | |
| continue | |
| } | |
| if _, ok := funcDecl.Type.Params.List[0].Type.(*ast.StarExpr); !ok { | |
| continue | |
| } | |
| // Get the type name from the function name | |
| funcName := funcDecl.Name.Name | |
| if !strings.HasPrefix(funcName, "Unmarshal") { | |
| continue | |
| } | |
| typeName := funcName[len("Unmarshal"):] | |
| // Check if the function already exists | |
| newFuncName := "New" + typeName + "Block" | |
| newFuncExists := false | |
| for _, decl := range f.Decls { | |
| if funcDecl, ok := decl.(*ast.FuncDecl); ok { | |
| if funcDecl.Name.Name == newFuncName { | |
| newFuncExists = true | |
| break | |
| } | |
| } | |
| } | |
| // Generate the new code | |
| var buf bytes.Buffer | |
| buf.WriteString("package gen\n\n") | |
| buf.WriteString(fmt.Sprintf("func %s(bcs *block.Cursor) (*%s, error) {\n", funcName, typeName)) | |
| buf.WriteString(fmt.Sprintf("\treturn block.UnmarshalBlock[*%s](bcs, %s)\n", typeName, newFuncName)) | |
| buf.WriteString("}\n") | |
| if !newFuncExists { | |
| buf.WriteString(fmt.Sprintf("func %s() block.Block {\n", newFuncName)) | |
| buf.WriteString(fmt.Sprintf("\treturn &%s{}\n", typeName)) | |
| buf.WriteString("}\n\n") | |
| } | |
| // Replace the old code with the new code | |
| funcDecl.Body.List = nil | |
| funcDecl.Body.Rbrace = 0 | |
| stmt, err := parser.ParseFile(fset, "", &buf, parser.ParseComments) | |
| if err != nil { | |
| return err | |
| } | |
| newFuncDecl := stmt.Decls[0].(*ast.FuncDecl) | |
| funcDecl.Body.List = newFuncDecl.Body.List | |
| if !newFuncExists { | |
| f.Decls = append(f.Decls, stmt.Decls[1]) | |
| } | |
| } | |
| // Write the modified Go file | |
| fh, err := os.Create(filename) | |
| if err != nil { | |
| return err | |
| } | |
| defer fh.Close() | |
| if err := format.Node(fh, fset, f); err != nil { | |
| return err | |
| } | |
| return nil | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment