Beispiel #1
0
func getFlatTypes(req *compiler.CodeGeneratorRequest, exported bool, out *FlatTypes) *FlatTypes {
	include := func(string) bool { return true }
	if exported {
		include = func(name string) bool {
			for _, n := range req.GetFileToGenerate() {
				if n == name {
					return true
				}
			}
			return false
		}
	}

	for _, pkg := range req.GetProtoFile() {
		if !include(pkg.GetName()) {
			continue
		}

		out = flatTypesForFile(pkg, out)
	}

	return out
}
Beispiel #2
0
func main() {
	log.SetPrefix("pinktxt: ")
	log.SetFlags(0)

	var resp = new(compiler.CodeGeneratorResponse)
	defer func() {
		output, err := proto.Marshal(resp)
		if err != nil {
			log.Fatalf("Error encoding %T: %v", resp, err)
			return
		}

		if resp.Error != nil {
			log.Printf("Error in response: %s", *resp.Error)
		}

		for len(output) > 0 {
			n, err := os.Stdout.Write(output)
			if n > len(output) {
				n = len(output)
			}
			output = output[n:]

			if err != nil {
				time.Sleep(time.Millisecond * 500)
				log.Printf("Error writing output to standard out: %v", err)
			}
		}
	}()

	var req compiler.CodeGeneratorRequest
	{
		var input bytes.Buffer
		if n, err := input.ReadFrom(os.Stdin); err != nil {
			resp.Error = heapString("error reading from standard input: " + err.Error())
			return
		} else if n == 0 {
			resp.Error = heapString("no input provided")
			return
		}

		if err := proto.Unmarshal(input.Bytes(), &req); err != nil {
			resp.Error = heapString("error unmarshalling from standard input: " + err.Error())
			return
		}
	}

	params := parseParameters(req.GetParameter())
	files := make(map[string]*bytes.Buffer)
	root := FlatTypeRoot{
		Request:   &req,
		Visible:   getFlatTypes(&req, false, nil),
		Exported:  getFlatTypes(&req, true, nil),
		Params:    params,
		HasData:   false,
		ExecParam: nil,
	}

	left, right := "(*", "*)"
	if p := params.Get("left"); len(p) > 0 {
		left = p
	}
	if p := params.Get("right"); len(p) > 0 {
		right = p
	}

	// This code is all awful but at least it gets the job done right now.
	var tx *template.Template
	funcs := template.FuncMap{
		"find": (typeFinder{root.Request}).Find,
		"fexec": func(name, outfile string, data ...interface{}) error {
			subroot := root
			if len(data) == 1 {
				d := data[0]
				if _, ok := d.(FlatTypeRoot); !ok {
					subroot.ExecParam = d
				}
			} else if len(data) > 1 {
				subroot.ExecParam = data
			}

			var out io.Writer = ioutil.Discard
			if len(name) > 0 {
				b, ok := files[outfile]
				if !ok {
					b = &bytes.Buffer{}
					files[outfile] = b
				}
				out = b
				subroot.HasData = b.Len() > 0
			}

			if name != "" {
				return tx.ExecuteTemplate(out, name, subroot)
			} else {
				return tx.Execute(out, subroot)
			}
		},

		"exec": func(name string, dot ...interface{}) (string, error) {
			var data interface{} = dot
			if len(dot) == 1 {
				data = dot[0]
			} else if len(dot) == 0 {
				data = nil
			}

			var buf bytes.Buffer
			var err error
			if name != "" {
				err = tx.ExecuteTemplate(&buf, name, data)
			} else {
				err = tx.Execute(&buf, data)
			}

			return buf.String(), err
		},
	}

	tx = template.New("").Delims(left, right).Funcs(mergeTypeChecks(copyDefaultTemplateFuncs(funcs)))

	tx, err := tx.ParseFiles(params["template"]...)
	if err != nil {
		resp.Error = heapString("error parsing template(s): " + err.Error())
		return
	}

	templates := params["template"]
	if tn := params["exec"]; len(tn) > 0 {
		templates = tn
	}

	for _, name := range templates {
		if err := tx.ExecuteTemplate(ioutil.Discard, name, root); err != nil {
			resp.Error = heapString(err.Error())
			return
		}
	}

	for name, buf := range files {
		f := &compiler.CodeGeneratorResponse_File{
			Name:    heapString(name),
			Content: heapString(buf.String()),
		}

		log.Printf("OUT=%q", name)
		resp.File = append(resp.File, f)
	}
}