/protoc-gen-template

A protoc plugin for generic code generation, backed by golang's templates.

Primary LanguageGoApache License 2.0Apache-2.0

protoc-gen-template

A protoc plugin for generic code generation, backed by golang's templates.

protoc --template_out=template_dir:output_dir example.proto

The template_out argument consists of two configuration values delimited by a colon. The first value is a directory or path containing templates to be evaluated and the second value is the output directory.

If the template value refers to a directory its contents (files and directories) will be written to the output directory. If the template value refers to a file, the file will be written to the output directory.

Files with the suffix .associated.tmpl will be parsed as "associated" templates. These templates will be present in the template execution scope but will not generate output files. For instance, if your template directory contains a file named foo/bar.associated.tmpl you can include its output in another template with {{ template "foo/bar" }} - there will be no file named foo.associated in the output.

Files named with the suffix .tmpl will be parsed and evaluated using golang's text/template package, and the output will be written to a file with the .tmpl suffix stripped.

Templates are executed with dot set to a TemplateData describing the plugin.CodeGeneratorRequest generated by protoc.

protoc-gen-template provides some additional parsing of the source structure to make template writing easier:

  • Associates SourceCodeInfo with the described data
  • Options defined in src/template/meta.proto are parsed and associated with the data they describe
  • Mappings from type's canonical names to their definitions are provided.
// docs.md.tpl
# Protobufs

{{ range .Files }}
## File {{ .Name }}

File {{ .Name }} contains the following services:

{{ range $key, $service := .Service }}
* {{ $service }}
{{ end }}

File {{ .Name }} contains the following message types:

{{ range $key, $messageType := .MessageType }}
* {{ $messageType }}
{{ end }}
{{ end }}
protoc --template_out=template.md.tpl:. data/testdata/test.proto

Will generate something like:

// docs.md
# Protobufs

## File test.proto

File test.proto contains the following services:

* Discovery

File test.proto contains the following message types:

* GetImapConfigRequest
* ImapDocumentation
* ImapConfig

Install

go get -u github.com/kerinin/protoc-gen-template

Build

A compile step is necessary for the plugin to handle the annotations defined in meta/extensions.proto. After making changes to this protobuf you'll need to recompile meta.extensions.pb.go for the changes to be recognized:

docker-compose build compile
docker-compose run compile

Testing

For quickly checking output

go build && cat data/testdata/dump.pb | ./protoc-gen-template -template data/testdata/template.tmpl | go run decode/main.go

To update testdata with the contents of testdata/*.proto

docker-compose run app bash -c 'protoc -I=/root/include -I=.  --dump_out=protoc-gen-template/data/testdata protoc-gen-template/data/testdata/*.proto'