Example #1
0
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)
		}
	}
}
Example #2
0
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
}