func main() { flag.Parse() if len(*typeNames) == 0 { log.Fatalf("the flag -type must be set") } types := strings.Split(*typeNames, ",") // Only one directory at a time can be processed, and the default is ".". dir := "." if args := flag.Args(); len(args) == 1 { dir = args[0] } else if len(args) > 1 { log.Fatalf("only one directory at a time") } pkg, err := parser.ParsePackage(dir, *outputPrefix, *outputSuffix+".go") if err != nil { log.Fatalf("parsing package: %v", err) } var analysis = struct { Command string PackageName string TypesAndValues map[string][]string }{ Command: strings.Join(os.Args[1:], " "), PackageName: pkg.Name, TypesAndValues: make(map[string][]string), } // Run generate for each type. for _, typeName := range types { values, err := pkg.ValuesOfType(typeName) if err != nil { log.Fatalf("finding values for type %v: %v", typeName, err) } analysis.TypesAndValues[typeName] = values var buf bytes.Buffer if err := generatedTmpl.Execute(&buf, analysis); err != nil { log.Fatalf("generating code: %v", err) } src, err := format.Source(buf.Bytes()) if err != nil { // Should never happen, but can arise when developing this code. // The user can compile the output to see the error. log.Printf("warning: internal error: invalid Go generated: %s", err) log.Printf("warning: compile the package to analyze the error") src = buf.Bytes() } output := strings.ToLower(*outputPrefix + typeName + *outputSuffix + ".go") outputPath := filepath.Join(dir, output) if err := ioutil.WriteFile(outputPath, src, 0644); err != nil { log.Fatalf("writing output: %s", err) } } }
func generateHandler(w http.ResponseWriter, r *http.Request) error { if r.Method != "GET" { return codeError{fmt.Errorf("only GET accepted"), http.StatusMethodNotAllowed} } code := r.FormValue("code") if code == "" { return codeError{fmt.Errorf("no code to be parsed"), http.StatusBadRequest} } typ := r.FormValue("type") if typ == "" { return codeError{fmt.Errorf("no type to be analyzed"), http.StatusBadRequest} } dir, err := createDir(code) if err != nil { return err } defer os.RemoveAll(dir) pkg, err := parser.ParsePackage(dir, "", "") if err != nil { return fmt.Errorf("parse package: %v", err) } values, err := pkg.ValuesOfType(typ) if err != nil { return fmt.Errorf("find values: %v", err) } t, err := template.New("code").Parse(r.FormValue("template")) if err != nil { return codeError{fmt.Errorf("parse template: %v", err), http.StatusBadRequest} } var data = struct { PackageName string TypeName string Values []string }{pkg.Name, typ, values} var buf bytes.Buffer if err := t.Execute(&buf, data); err != nil { return codeError{fmt.Errorf("execute template: %v", err), http.StatusBadRequest} } src, err := format.Source(buf.Bytes()) if err != nil { return codeError{fmt.Errorf("code generated is not valid: %v\n%v", err, buf.String()), http.StatusBadRequest} } w.Write(src) return nil }