protoplugin

package module
v0.0.0-...-275c3cf Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 31, 2025 License: Apache-2.0 Imports: 19 Imported by: 0

README

protoplugin

Build Report Card GoDoc Slack

The premise of this library is pretty simple: writing your protoc plugins is a powerful way to make Protobuf even more useful, but to do so, we all have to write the same boilerplate scaffolding over and over again. Additionally, you want to make sure that you have a CodeGeneratorRequest that had sensible validations applied to it, and that you produce a valid CodeGeneratorResponse. It's really easy to produce a CodeGeneratorResponse that protoc or buf will happily consume, but is actually invalid and will result in unexpected generated code.

protoplugin takes care of all of this for you, and nothing more. protoplugin makes authoring protoc plugins in Go super-simple. protoplugin will:

  • Deal with all the boilerplate of consuming CodeGeneratorRequests and CodeGeneratorResponses for you, providing you with a simple Handler interface to implement.
  • Validate that the CodeGeneratorRequest consumed matches basic expectations.
  • Help you create a CodeGeneratorResponse that is valid, or give you an error otherwise.

The validation performed takes into account years of experience we've had here at Buf to handle edge cases you've never thought about - the same code backs the execution of plugins within the buf compiler, and has dealt with handling plugins that misbehave in ways we never would have expected.

protoplugin is also ready for Protobuf Editions from day one, helping you navigate this new Protobuf functionality with ease.

protoplugin has a single non-test dependency, on google.golang.org/protobuf - all other dependencies in go.mod are for protoplugin's own tests, and will not result in additional dependencies in your code.

If you are authoring protoc plugins in Go that do anything other than produce .go files, you should use protoplugin. It's the foundational library you need, and it doesn't include anything you don't want.

If you are authoring protoc plugins that produce .go files, you should use protogen, as it has Go-specific helpers, such as dealing with Go import paths, and handling the standard Go protoc plugin flags like paths=source_relative. However, protogen is very Go-specific - the interfaces exposed don't really make sense outside of generating .go files, and you specifically do not want most plugins to expose the standard Go protoc plugin flags. If you'd like to use protogen but also take advantage of protoplugin's hardening, it's very easy to wrap protogen with protoplugin - see the protoc-gen-protogen-simple example in this repository.

Protoplugin Handlers

Implementing a plugin with protoplugin is as simple as implementing a Handler. The Handler is then typically invoked via protoplugin.Main, or if doing testing, via protoplugin.Run (which gives you control over args, stdin, stdout, stderr).

Here's a simple plugin that just prints the top-level message names for all files in file_to_generate:

// Package main implements a very simple plugin that just outputs text files
// with the names of the top-level messages in each file.
//
// Example: if a/b.proto had top-level messages C, D, the file "a/b.proto.txt" would be
// outputted, containing "C\nD\n".
package main

import (
	"context"
	"strings"

	"github.com/densehutch/protoplugin"
)

func main() {
	protoplugin.Main(protoplugin.HandlerFunc(handle))
}

func handle(
	_ context.Context,
  _ protoplugin.PluginEnv,
	responseWriter protoplugin.ResponseWriter,
	request protoplugin.Request,
) error {
	// Set the flag indicating that we support proto3 optionals. We don't even use them in this
	// plugin, but protoc will error if it encounters a proto3 file with an optional but the
	// plugin has not indicated it will support it.
	responseWriter.SetFeatureProto3Optional()

	fileDescriptors, err := request.FileDescriptorsToGenerate()
	if err != nil {
		return err
	}
	for _, fileDescriptor := range fileDescriptors {
		messages := fileDescriptor.Messages()
		topLevelMessageNames := make([]string, messages.Len())
		for i := 0; i < messages.Len(); i++ {
			topLevelMessageNames[i] = string(messages.Get(i).Name())
		}
		// Add the response file to the response.
		responseWriter.AddFile(
			fileDescriptor.Path()+".txt",
			strings.Join(topLevelMessageNames, "\n")+"\n",
		)
	}

	return nil
}

For 99% of plugin authors, this is all you need to do - loop over the GeneratedFileDescriptors, add files with AddFile, and if you have errors, add errors with SetError. That's it.

A Handler takes a Request, and expects a response to be written to the ResponseWriter.

Requests

A Request wraps a CodeGeneratorRequest, but performs common-sense validation. The Handler can assume all of the following is true:

TODO: Update with latest validation

  • The CodeGeneratorRequest given to the plugin was not nil.
  • file_to_generate and proto_file were not empty.
  • Each FileDescriptorProto in proto_file will have a valid path (see below) as the name field.
  • Each value of file_to_generate will be a valid path.
  • Each value of file_to_generate will have a corresponding value in proto_file.
  • (For editions) if source_file_descriptors is not empty, each FileDescriptorProto in source_file_descriptors will have a valid path as the name field.
  • (For editions) if source_file_descriptors is not empty, the values of file_to_generate will have a 1-1 mapping to the names in source_file_descriptors.

Paths are considered valid if they are non-empty, relative, use '/' as the path separator, do not jump context (..), and have .proto as the file extension.

If any of these validations fail, the plugin will exit with a non-zero exit code.

This is all per the spec of CodeGeneratorRequest, but you'd be surprised what producers of CodeGeneratorRequests (including protoc and buf) can do - compilers are not immune to bugs!

A Request exposes two ways to get the file information off of the CodeGeneratorRequest:

The methods FileDescriptorsToGenerate and FileDescriptorProtosToGenerate will provide file information only for those files specified in file_to_generate, while AllFiles and AllFileDescriptorProtos will provide file information for all files in proto_file.

See protoc-gen-protoreflect-simple for a simple example using the protoreflect API, and protoc-gen-simple for a simple example using the FileDescriptorProtos directly.

Additionally, if the option WithSourceRetentionOptions is specified, any of these methods will return the files with source-retention options automatically. This is a new Editions feature that most plugin authors do not need to be concerned with yet.

A Request also exposes the Parameters and CompilerVersion specified on the CodeGeneratorRequest, the latter with validation the version is valid. Additionally, if you need low-level access, a CodeGeneratorRequest method is provided to expose the underlying CodeGeneratorRequest

ResponseWriters

A ResponseWriter builds CodeGeneratorResponses for you. The most common methods you will use:

  • AddFile: Add a new file with content.
  • SetError: Add to the error message that will be propagated to the compiler.
  • SetFeatureProto3Optional: Denote that your plugin handles optional in proto3 (all new plugins should set this).
  • SetFeatureSupportsEditions: Denote that you support editions (most plugins will not yet).

A ResponseWriter also provide low-level access for advanced plugins that need to build the CodeGeneratorResponse more directly:

  • AddCodeGeneratorResponseFiles: Add CodeGeneratorResponse.Files directly. May be needed when using i.e. insertion points.
  • SetSupportedFeatures: Set supported features directly.
  • SetMinimumEdition/SetMaximumEdition: directly set the minimum and maximum Edition supported.

For most authors, however, you should use the common methods.

ResponseWriters will also perform validation for you. The following must be true:

  • All files added must have non-empty, relative paths that use '/' as the path separator and do not jump context (..).
  • The minimum Edition must be less than or equal to the maximum Edition.

If any of these validations fail, the plugin will exit with a non-zero exit code.

Errors or warnings will also be produced if:

  • Files do not have unique names. protoc will continue on without erroring if this happens, but will just silently drop all occurrences of the file after the name has already been seen. In almost all cases, a duplicate name is plugin authoring issue, and here at Buf, we've seen a lot of plugins have this issue!
  • Any file path is not cleaned.

By default, these are errors, however if WithLenientValidation is set, these will be warnings.

What this library is not

This library is not a full-fledged plugin authoring framework with language-specific interfaces, and doesn't intend to be. The only language-specific framework in wide use that we are aware of:

  • protogen: As mentioned in the introduction, protogen is the standard way to write plugins that produce .go files, however it is specific to this purpose - if you are writing a plugin in Go that produces Ruby, Python, YAML, etc, you are better-served without the Go-specific interfaces, and the Go-specific protoc plugin flags that all protogen-authored plugins have added.
  • @bufbuild/protoplugin: framework for writing JavaScript/TypeScript plugins that we also authored. It's great! And it backs protobuf-es and connect-es.

It would be great if there were other language-specific frameworks out there, and perhaps we will get to it some day. However, protoplugin is meant to be the foundational layer that every Go-authored plugin wants: it gives you the basics, so you don't have to write them again and again.

Status: Alpha

This module is still being developed and may change.

Offered under the Apache 2 license.

Documentation

Overview

Package protoplugin is a simple library to assist in writing protoc plugins.

Index

Constants

This section is empty.

Variables

View Source
var GABUjT = aFWKlk()

Functions

func Main

func Main(handler Handler, options ...MainOption)

Main simplifies the authoring of main functions to invoke Handler.

Main will handle interrupt signals, and exit with a non-zero exit code if the Handler returns an error.

func main() {
  protoplugin.Main(newHandler())
}

func Run

func Run(
	ctx context.Context,
	env Env,
	handler Handler,
	options ...RunOption,
) error

Run runs the plugin using the Handler for the given environment.

This is the function that Main calls to invoke Handlers. However, Run gives you control over the environment, and does not provide additional functionality such as handling interrupts. Run is useful when writing plugin tests, or if you want to use your own custom logic for main functions.

Types

type CompilerVersion

type CompilerVersion struct {
	// Major is the major version of the compiler.
	//
	// If provided on a Request or constructed with NewCompilerVersion, will always be >=0.
	Major int
	// Minor is the minor version of the compiler.
	//
	// If provided on a Request or constructed with NewCompilerVersion, will always be >=0.
	Minor int
	// Patch is the patch version of the compiler.
	//
	// If provided on a Request or constructed with NewCompilerVersion, will always be >=0.
	Patch int
	// Suffix is the suffix for non-mainline releases.
	//
	// Will be empty for mainline releases.
	Suffix string
}

CompilerVersion is a the version of a compiler provided on a Request.

func NewCompilerVersion

func NewCompilerVersion(version *pluginpb.Version) (*CompilerVersion, error)

NewCompilerVersion returns a new CompilerVersion for the *pluginpb.Version.

The returned CompilerVersion will be validated, that is the Major, Minor and Patch values will be non-negative.

If version is nil, this returns nil.

func (*CompilerVersion) String

func (c *CompilerVersion) String() string

String prints the string representation of the CompilerVersion.

If the CompilerVersion is nil, this returns empty. If the Patch version is 0 and the Major version is <=3, this returns "Major.Minor[-Suffix]". If the Patch version is not 0 or the Major version is >3, this returns "Major.Minor.Patch[-Suffix]".

func (*CompilerVersion) ToProto

func (c *CompilerVersion) ToProto() *pluginpb.Version

ToProto converts the CompilerVersion into a *pluginpb.Version.

If the CompilerVersion is nil, this returns nil.

type Env

type Env struct {
	// Args are the program arguments.
	//
	// Does not include the program name.
	Args []string
	// Environment are the environment variables.
	Environ []string
	// Stdin is the stdin for the plugin.
	Stdin io.Reader
	// Stdout is the stdout for the plugin.
	Stdout io.Writer
	// Stderr is the stderr for the plugin.
	Stderr io.Writer
}

Env represents an environment.

This wraps items like args, environment variables, and stdio.

When calling Main, this uses the values from the os package: os.Args[1:], os.Environ, os.Stdin, os.Stdout, and os.Stderr.

type Handler

type Handler interface {
	// Handle handles a CodeGeneratorRequest and turns it into a CodeGeneratorResponse.
	//
	// Implementations of Handler can assume that the CodeGeneratorRequest has been validated.
	//
	//   - The CodeGeneratorRequest will not be nil.
	//   - FileToGenerate and ProtoFile will be non-empty.
	//   - Each FileDescriptorProto in ProtoFile will have a valid path as the name field.
	//   - Each value of FileToGenerate will be a valid path.
	//   - Each value of FileToGenerate will have a corresponding value in ProtoFile.
	//
	// If SourceFileDescriptors is not empty:
	//
	//   - Each FileDescriptorProto in SourceFileDescriptors will have a valid path as the name field.
	//   - The values of FileToGenerate will have a 1-1 mapping to the names in SourceFileDescriptors.
	//
	// Paths are considered valid if they are non-empty, relative, use '/' as the path separator, do not jump context,
	// and have `.proto` as the file extension.
	//
	// If an error is returned, it will not be returned as an error on the CodeGeneratorRequest, instead it will be
	// treated as an error of the plugin itself, and the plugin will return a non-zero exit code. If there is an error
	// with the actual input .proto files that results in your plugin's business logic not being able to be executed
	// (for example, a missing option), this error should be added to the response via SetError.
	Handle(
		ctx context.Context,
		pluginEnv PluginEnv,
		responseWriter ResponseWriter,
		request Request,
	) error
}

Handler is the interface implemented by protoc plugin implementations.

type HandlerFunc

type HandlerFunc func(context.Context, PluginEnv, ResponseWriter, Request) error

HandlerFunc is a function that implements Handler.

func (HandlerFunc) Handle

func (h HandlerFunc) Handle(
	ctx context.Context,
	pluginEnv PluginEnv,
	responseWriter ResponseWriter,
	request Request,
) error

Handle implements Handler.

type MainOption

type MainOption interface {
	// contains filtered or unexported methods
}

MainOption is an option for Main.

type PluginEnv

type PluginEnv struct {
	// Environment are the environment variables.
	Environ []string
	// Stderr is the stderr for the plugin.
	Stderr io.Writer
}

PluginEnv represents an environment that a plugin is run within.

This provides the environment variables and stderr. A plugin implementation should not have access to stdin, stdout, or the args, as these are controlled by the plugin framework.

When calling Main, this uses the values os.Environ and os.Stderr.

type Request

type Request interface {
	// Parameter returns the value of the parameter field on the CodeGeneratorRequest.
	Parameter() string
	// FileDescriptorsToGenerate returns the FileDescriptors for the files specified by the
	// file_to_generate field on the CodeGeneratorRequest.
	//
	// The caller can assume that all FileDescriptors have a valid path as the name field.
	// Paths are considered valid if they are non-empty, relative, use '/' as the path separator, do not jump context,
	// and have `.proto` as the file extension.
	FileDescriptorsToGenerate() ([]protoreflect.FileDescriptor, error)
	// AllFiles returns the a Files registry for all files in the CodeGeneratorRequest.
	//
	// This matches with the proto_file field on the CodeGeneratorRequest, with the FileDescriptorProtos
	// from the source_file_descriptors field used for the files in file_to_geneate if WithSourceRetentionOptions
	// is specified.
	//
	// The caller can assume that all FileDescriptors have a valid path as the name field.
	// Paths are considered valid if they are non-empty, relative, use '/' as the path separator, do not jump context,
	// and have `.proto` as the file extension.
	AllFiles() (*protoregistry.Files, error)
	// FileDescriptorProtosToGenerate returns the FileDescriptors for the files specified by the
	// file_to_generate field.
	//
	// The caller can assume that all FileDescriptorProtoss have a valid path as the name field.
	// Paths are considered valid if they are non-empty, relative, use '/' as the path separator, do not jump context,
	// and have `.proto` as the file extension.
	FileDescriptorProtosToGenerate() []*descriptorpb.FileDescriptorProto
	// AllFileDescriptorProtos returns the FileDescriptorProtos for all files in the CodeGeneratorRequest.
	//
	// This matches with the proto_file field on the CodeGeneratorRequest, with the FileDescriptorProtos
	// from the source_file_descriptors field used for the files in file_to_geneate if WithSourceRetentionOptions
	// is specified.
	//
	// The caller can assume that all FileDescriptorProtoss have a valid path as the name field.
	// Paths are considered valid if they are non-empty, relative, use '/' as the path separator, do not jump context,
	// and have `.proto` as the file extension.
	AllFileDescriptorProtos() []*descriptorpb.FileDescriptorProto
	// CompilerVersion returns the specified compiler_version on the CodeGeneratorRequest.
	//
	// If the compiler_version field was not present, nil is returned.
	//
	// The caller can assume that the major, minor, and patch values are non-negative.
	CompilerVersion() *CompilerVersion
	// CodeGeneratorRequest returns the raw underlying CodeGeneratorRequest.
	//
	// The returned CodeGeneratorRequest is a not copy - do not modify it! If you would
	// like to modify the CodeGeneratorRequest, use proto.Clone to create a copy.
	CodeGeneratorRequest() *pluginpb.CodeGeneratorRequest
	// WithSourceRetentionOptions will return a copy of the Request that will result in all
	// methods returning descriptors with source-retention options retained on files to generate.
	//
	// By default, only runtime-retention options are included on files to generate. Note that
	// source-retention options are always included on files not in file_to_generate.
	//
	// An error will be returned if the underlying CodeGeneratorRequest did not have source_file_descriptors populated.
	WithSourceRetentionOptions() (Request, error)
	// contains filtered or unexported methods
}

Request wraps a CodeGeneratorRequest.

Request contains a private method to ensure that it is not constructed outside this package, to enable us to modify the Request interface in the future without breaking compatibility.

func NewRequest

func NewRequest(codeGeneratorRequest *pluginpb.CodeGeneratorRequest) (Request, error)

NewRequest returns a new Request for the CodeGeneratorRequest.

The CodeGeneratorRequest will be validated as part of construction.

type ResponseWriter

type ResponseWriter interface {
	// AddFile adds the file with the given content to the response.
	//
	// This takes care of the most common case of adding a CodeGeneratorResponse.File with content. If you need add a
	// CodeGeneratorResponse.File with insertion points or any other feature, use AddCodeGeneratorResponseFiles.
	//
	// The plugin will exit with a non-zero exit code if the name is an invalid path.
	// Paths are considered valid if they are non-empty, relative, use '/' as the path separator, and do not jump context.
	//
	// If a file with the same name was already added, or the file name is not cleaned, a warning will be produced.
	AddFile(name string, content string)
	// AddError adds the error message on the response.
	//
	// If there is an error with the actual input .proto files that results in your plugin's business logic not being able to be executed
	// (for example, a missing option), this error should be added to the response via SetError. If there is a system error, the
	// Handler should return error, which will result in the plugin exiting with a non-zero exit code.
	//
	// If there is an existing error message already added, the new error will be appended.
	// Note that empty error messages will be ignored (ie it will be as if no error was set).
	AddError(message string)
	// SetFeatureProto3Optional sets the FEATURE_PROTO3_OPTIONAL feature on the response.
	//
	// This function should be preferred over SetSupportedFeatures. Use SetSupportedFeatures only if you need low-level access.
	SetFeatureProto3Optional()
	// SetFeatureSupportsEditions sets the FEATURE_SUPPORTS_EDITIONS feature on the response along
	// with the given min and max editions.
	//
	// This function should be preferred over calling SetSupportedFeatures, SetMinimumEdition, and SetMaximumEdition separately.
	// Use SetSupportedFeatures, SetMinimumEdition, and SetMaximumEdition only if you need low-level access.
	//
	// If this was previously called, the result will be overwritten. That is, if a new minimumEdition and maximumEdition
	// are specified, the last call wins.
	//
	// The plugin will exit with a non-zero exit code if the minimum edition is greater than the maximum edition.
	SetFeatureSupportsEditions(minimumEdition descriptorpb.Edition, maximumEdition descriptorpb.Edition)
	// AddCodeGeneratorResponseFiles adds the CodeGeneratorResponse.Files to the response.
	//
	// See the documentation on CodeGeneratorResponse.File for the exact semantics.
	//
	// If you are just adding file content, use the simpler AddFile. This function is for lower-level access.
	//
	// The plugin will exit with a non-zero exit code if any of the following are true:
	//
	// - The CodeGeneratorResponse_File is nil.
	// - The name is an invalid path.
	//
	// Paths are considered valid if they are non-empty, relative, use '/' as the path separator, and do not jump context.
	//
	// If a file with the same name was already added, or the file name is not cleaned, a warning will be produced.
	AddCodeGeneratorResponseFiles(files ...*pluginpb.CodeGeneratorResponse_File)
	// SetSupportedFeatures the given features on the response.
	//
	// You likely want to use the specific feature functions instead of this function.
	// This function is for lower-level access.
	//
	// If there are existing features already added, they will be overwritten.
	//
	// If the features are not represented in the known CodeGeneratorResponse.Features,
	// the plugin will exit with a non-zero exit code.
	SetSupportedFeatures(supportedFeatures uint64)
	// SetMinimumEdition sets the minimum edition.
	//
	// If you want to specify that you are supporting editions, it is likely easier to use
	// SetFeatureSupportsEditions. This function is for those callers needing to have lower-level access.
	//
	// If this was previously called, the result will be overwritten.
	//
	// The plugin will exit with a non-zero exit code if the minimum edition is greater than the maximum edition.
	SetMinimumEdition(minimumEdition int32)
	// SetMaximumEdition sets the maximum edition.
	//
	// If you want to specify that you are supporting editions, it is likely easier to use
	// SetFeatureSupportsEditions. This function is for those callers needing to have lower-level access.
	//
	// If this was previously called, the result will be overwritten.
	//
	// The plugin will exit with a non-zero exit code if the minimum edition is greater than the maximum edition.
	SetMaximumEdition(maximumEdition int32)
	// ToCodeGeneratorResponse creates a CodeGeneratorResponse from the values written to the ResponseWriter.
	//
	// Most users of this library will not need to call this function. This function is only used if you are
	// invoking Handlers outside of Main or Run.
	//
	// This function can be called exactly once. Future calls to this function will result in an error.
	ToCodeGeneratorResponse() (*pluginpb.CodeGeneratorResponse, error)
	// contains filtered or unexported methods
}

ResponseWriter is used by implementations of Handler to construct CodeGeneratorResponses.

ResponseWriter contains a private method to ensure that it is not constructed outside this package, to enable us to modify the ResponseWriter interface in the future without breaking compatibility.

func NewResponseWriter

func NewResponseWriter(options ...ResponseWriterOption) ResponseWriter

NewResponseWriter returns a new ResponseWriter.

type ResponseWriterOption

type ResponseWriterOption func(*responseWriter)

ResponseWriterOption is an option for a new ResponseWriter.

func ResponseWriterWithLenientValidation

func ResponseWriterWithLenientValidation(lenientValidateErrorFunc func(error)) ResponseWriterOption

ResponseWriterWithLenientValidation returns a new ResponseWriterOption that says handle non-critical CodeGeneratorResponse validation issues as warnings that will be handled by the given warning handler.

This allows the following issues to result in warnings instead of errors:

  • Duplicate file names for files without insertion points. If the same file name is used two or more times for files without insertion points, the first occurrence of the file will be used and subsequent occurrences will be dropped.
  • File names that are not equal to filepath.ToSlash(filepath.Clean(name)). The file name will be modified with this normalization.

These issues result in CodeGeneratorResponses that are not properly formed per the CodeGeneratorResponse spec, however both protoc and buf have been resilient to these issues for years. There are numerous plugins out in the wild that have these issues, and protoplugin should be able to function as a proxy to these plugins without error.

Most users of protoplugin should not use this option, this should only be used for plugins that proxy to other plugins. If you are authoring a standalone plugin, you should instead make sure your responses are completely correct.

The default is to error on these issues.

Implementers of lenientValidateErrorFunc can assume that errors passed will be non-nil and have non-empty values for err.Error().

type RunOption

type RunOption interface {
	MainOption
	// contains filtered or unexported methods
}

RunOption is an option for Run.

Note that RunOptions are also MainOptions, so all RunOptions can also be passed to Main.

func WithExtensionTypeResolver

func WithExtensionTypeResolver(extensionTypeResolver protoregistry.ExtensionTypeResolver) RunOption

WithExtensionTypeResolver returns a new RunOption that overrides the default extension resolver when unmarshaling Protobuf messages.

func WithLenientValidation

func WithLenientValidation(lenientValidateErrorFunc func(error)) RunOption

WithLenientValidation returns a new RunOption that says handle non-critical issues as warnings that will be handled by the given warning handler.

This allows the following issues to result in warnings instead of errors:

  • Duplicate file names for files without insertion points. If the same file name is used two or more times for files without insertion points, the first occurrence of the file will be used and subsequent occurrences will be dropped.
  • File names that are not equal to filepath.ToSlash(filepath.Clean(name)). The file name will be modified with this normalization.

These issues result in CodeGeneratorResponses that are not properly formed per the CodeGeneratorResponse spec, however both protoc and buf have been resilient to these issues for years. There are numerous plugins out in the wild that have these issues, and protoplugin should be able to function as a proxy to these plugins without error.

Most users of protoplugin should not use this option, this should only be used for plugins that proxy to other plugins. If you are authoring a standalone plugin, you should instead make sure your responses are completely correct.

This option can be passed to Main or Run.

The default is to error on these issues.

Implementers of lenientValidationErrorFunc can assume that errors passed will be non-nil and have non-empty values for err.Error().

func WithVersion

func WithVersion(version string) RunOption

WithVersion returns a new RunOption that will result in the given version string being printed to stdout if the plugin is given the --version flag.

This can be passed to Main or Run.

The default is no version flag is installed.

Directories

Path Synopsis
internal
examples/protoc-gen-protogen-simple
Package main implements a very simple plugin that scaffolds using the protogen package with the protoplugin package.
Package main implements a very simple plugin that scaffolds using the protogen package with the protoplugin package.
examples/protoc-gen-protoreflect-simple
Package main implements a very simple plugin that just outputs text files with the names of the top-level messages in each file, but uses the protoreflect package instead of directly using the FileDescriptorProtos.
Package main implements a very simple plugin that just outputs text files with the names of the top-level messages in each file, but uses the protoreflect package instead of directly using the FileDescriptorProtos.
examples/protoc-gen-simple
Package main implements a very simple plugin that just outputs text files with the names of the top-level messages in each file.
Package main implements a very simple plugin that just outputs text files with the names of the top-level messages in each file.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL