package main import ( "bufio" "fmt" "io" "os" "os/exec" "path/filepath" "strings" ) func main() { if len(os.Args) != 3 { fmt.Println("Usage: go run main.go ") return } inputDir := os.Args[1] outputDir := os.Args[2] files, err := getGoFiles(inputDir) if err != nil { fmt.Println(err) return } for _, file := range files { typeDecls, importDecls, err := extractTypes(file) if err != nil { fmt.Println(err) continue } // Filter out structs with "Nullable" at the beginning of their names. typeDecls = filterNullableTypes(typeDecls) // Generate the adapted file name by inserting the "_adapted" string before the ".go" extension of the original file name. adaptedFile := strings.Replace(filepath.Base(file), ".go", "_adapted.go", 1) adaptedFile = filepath.Join(outputDir, adaptedFile) // Write the struct declarations and import declarations to the adapted file. err = writeStruct(typeDecls, importDecls, adaptedFile) if err != nil { fmt.Println(err) continue } // Reformat the adapted file using gofmt. err = runGoImports(adaptedFile) if err != nil { fmt.Println(err) continue } } } // getGoFiles returns a list of .go files in the given directory. func getGoFiles(dir string) ([]string, error) { var files []string f, err := os.Open(dir) if err != nil { return nil, err } defer f.Close() fi, err := f.Readdir(-1) if err != nil { return nil, err } for _, file := range fi { if !file.IsDir() && strings.HasSuffix(file.Name(), ".go") { // Concatenate the directory path and the file name to get the full path. files = append(files, dir+"/"+file.Name()) } } return files, nil } // filterNullableTypes filters out structs with "Nullable" at the beginning of their names. func filterNullableTypes(structDecls []string) []string { var filteredStructDecls []string for _, s := range structDecls { // Check if the struct name starts with "Nullable". if !strings.HasPrefix(s, "type Nullable") { filteredStructDecls = append(filteredStructDecls, s) } } return filteredStructDecls } // extractTypes reads a .go file and returns a list of type declarations and a list of import declarations. func extractTypes(file string) ([]string, []string, error) { var typeDecls []string var importDecls []string f, err := os.Open(file) if err != nil { return nil, nil, err } defer f.Close() scanner := bufio.NewScanner(f) var typeDecl, importDecl string inStruct, inImport := false, false for scanner.Scan() { line := scanner.Text() if strings.HasPrefix(line, "import") { inImport = true importDecl = line + "\n" } else if inImport && (line == "" || strings.HasPrefix(line, ")")) { importDecl += line + "\n" inImport = false importDecls = append(importDecls, importDecl) } else if inImport { importDecl += line + "\n" } else if strings.HasPrefix(line, "type") { inStruct = true typeDecl = line + "\n" } else if inStruct && strings.HasPrefix(line, "}") { typeDecl += line + "\n" typeDecls = append(typeDecls, typeDecl) inStruct = false } else if inStruct { typeDecl += line + "\n" } } if err := scanner.Err(); err != nil { return nil, nil, err } return typeDecls, importDecls, nil } // writeStruct writes the given struct declarations and import declarations to a new file with the given name. func writeStruct(structDecls []string, importDecls []string, file string) error { f, err := os.Create(file) if err != nil { return err } defer f.Close() // Add the package dto declaration at the top of the file. _, err = io.WriteString(f, "package dto\n\n") if err != nil { return err } // Write the import declarations to the file. for _, importDecl := range importDecls { _, err = io.WriteString(f, importDecl) if err != nil { return err } } // Write the struct declarations to the file. for _, s := range structDecls { _, err = io.WriteString(f, s) if err != nil { return err } } return nil } // runimports reformats the given file using the goimports tool. func runGoImports(file string) error { cmd := exec.Command("goimports", "-w", file) output, err := cmd.CombinedOutput() if err != nil { return fmt.Errorf("%s: %s", err, output) } return nil }