github.com/containers/podman/v4@v4.9.4/pkg/bindings/generator/generator.go (about) 1 //go:build ignore 2 // +build ignore 3 4 package main 5 6 // This program generates *_options_.go files to be used by the bindings calls to API service. 7 // It can be invoked by running go generate 8 9 import ( 10 "errors" 11 "fmt" 12 "go/ast" 13 "go/parser" 14 "go/token" 15 "os" 16 "os/exec" 17 "strings" 18 "text/template" 19 "unicode" 20 "unicode/utf8" 21 ) 22 23 var bodyTmpl = `// Code generated by go generate; DO NOT EDIT. 24 package {{.PackageName}} 25 26 import ( 27 {{range $import := .Imports}} {{$import}} 28 {{end}} 29 ) 30 31 // Changed returns true if named field has been set 32 func (o *{{.StructName}}) Changed(fieldName string) bool { 33 return util.Changed(o, fieldName) 34 } 35 36 // ToParams formats struct fields to be passed to API service 37 func (o *{{.StructName}}) ToParams() (url.Values, error) { 38 return util.ToParams(o) 39 } 40 41 {{range $field := .Fields}} 42 // With{{.Name}} set {{if .Comment}}{{.Comment}}{{else}}field {{.Name}} to given value{{end}} 43 func(o *{{.StructName}}) With{{.Name}}(value {{.Type}}) *{{.StructName}} { 44 o.{{.Name}} = {{if not .Composite}}&{{end}}value 45 return o 46 } 47 48 // Get{{.Name}} returns value of {{if .Comment}}{{.Comment}}{{else}}field {{.Name}}{{end}} 49 func(o *{{.StructName}}) Get{{.Name}}() {{.Type}} { 50 if o.{{.Name}} == nil { 51 var z {{.Type}} 52 return z 53 } 54 return {{if not .Composite}}*{{end}}o.{{.Name}} 55 } 56 {{end}} 57 ` 58 59 type fieldStruct struct { 60 Comment string 61 Composite bool 62 Name string 63 StructName string 64 Type string 65 } 66 67 func main() { 68 var ( 69 closed bool 70 fieldStructs []fieldStruct 71 ) 72 srcFile := os.Getenv("GOFILE") 73 inputStructName := os.Args[1] 74 b, err := os.ReadFile(srcFile) 75 if err != nil { 76 panic(err) 77 } 78 fset := token.NewFileSet() // positions are relative to fset 79 f, err := parser.ParseFile(fset, "", b, parser.ParseComments) 80 if err != nil { 81 panic(err) 82 } 83 84 // always add reflect 85 imports := []string{"\"reflect\"", "\"github.com/containers/podman/v4/pkg/bindings/internal/util\""} 86 for _, imp := range f.Imports { 87 imports = append(imports, imp.Path.Value) 88 } 89 90 out, err := os.Create(strings.TrimRight(srcFile, ".go") + "_" + strings.Replace(strings.ToLower(inputStructName), "options", "_options", 1) + ".go") 91 if err != nil { 92 panic(err) 93 } 94 defer func() { 95 if !closed { 96 out.Close() 97 } 98 }() 99 100 body := template.Must(template.New("body").Parse(bodyTmpl)) 101 102 ast.Inspect(f, func(n ast.Node) bool { 103 ref, refOK := n.(*ast.TypeSpec) 104 if !(refOK && ref.Name.Name == inputStructName) { 105 return true 106 } 107 108 x := ref.Type.(*ast.StructType) 109 for _, field := range x.Fields.List { 110 var name string 111 if len(field.Names) > 0 { 112 name = field.Names[0].Name 113 if len(name) < 1 { 114 panic(errors.New("bad name")) 115 } 116 } 117 118 var composite bool 119 switch field.Type.(type) { 120 case *ast.MapType, *ast.StructType, *ast.ArrayType: 121 composite = true 122 } 123 124 //sub := "*" 125 typeExpr := field.Type 126 start := typeExpr.Pos() - 1 127 end := typeExpr.End() - 1 128 fieldType := strings.Replace(string(b[start:end]), "*", "", 1) 129 130 fieldStructs = append(fieldStructs, fieldStruct{ 131 Comment: fmtComment(field.Comment.Text()), 132 Composite: composite, 133 Name: name, 134 StructName: inputStructName, 135 Type: fieldType, 136 }) 137 } // for 138 139 bodyStruct := struct { 140 PackageName string 141 Imports []string 142 StructName string 143 Fields []fieldStruct 144 }{ 145 PackageName: os.Getenv("GOPACKAGE"), 146 Imports: imports, 147 StructName: inputStructName, 148 Fields: fieldStructs, 149 } 150 151 // create the body 152 if err := body.Execute(out, bodyStruct); err != nil { 153 fmt.Println(err) 154 os.Exit(1) 155 } 156 157 // close out file 158 if err := out.Close(); err != nil { 159 fmt.Println(err) 160 os.Exit(1) 161 } 162 closed = true 163 164 // go fmt file 165 gofmt := exec.Command("go", "fmt", out.Name()) 166 gofmt.Stderr = os.Stdout 167 if err := gofmt.Run(); err != nil { 168 fmt.Println(err) 169 os.Exit(1) 170 } 171 172 // go import file 173 goimport := exec.Command("../../../test/tools/build/goimports", "-w", out.Name()) 174 goimport.Stderr = os.Stdout 175 if err := goimport.Run(); err != nil { 176 fmt.Println(err) 177 os.Exit(1) 178 } 179 return true 180 }) 181 } 182 183 func fmtComment(comment string) string { 184 r, n := utf8.DecodeRuneInString(comment) 185 if r != utf8.RuneError { 186 comment = string(unicode.ToLower(r)) + comment[n:] 187 } 188 comment = strings.TrimSpace(comment) 189 return comment 190 }