pgs

package module
v2.0.3 Latest Latest
Warning

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

Go to latest
Published: Mar 24, 2023 License: Apache-2.0 Imports: 22 Imported by: 130

README

protoc-gen-star (PG*) Build Status GoDoc

!!! THIS PROJECT IS A WORK-IN-PROGRESS | THE API SHOULD BE CONSIDERED UNSTABLE !!!

PG* is a protoc plugin library for efficient proto-based code generation

package main

import "github.com/lyft/protoc-gen-star/v2"

func main() {
  pgs.Init(pgs.DebugEnv("DEBUG")).
    RegisterModule(&myPGSModule{}).
    RegisterPostProcessor(&myPostProcessor{}).
    Render()
}

Features

Documentation

While this README seeks to describe many of the nuances of protoc plugin development and using PG*, the true documentation source is the code itself. The Go language is self-documenting and provides tools for easily reading through it and viewing examples. The docs can be viewed on GoDoc or locally by running make docs, which will start a godoc server and open them in the default browser.

Roadmap
  • Interface-based and fully-linked dependency graph with access to raw descriptors
  • Built-in context-aware debugging capabilities
  • Exhaustive, near 100% unit test coverage
  • End-to-end testable via overrideable IO & Interface based API
  • Visitor pattern and helpers for efficiently walking the dependency graph
  • BuildContext to facilitate complex generation
  • Parsed, typed command-line Parameters access
  • Extensible ModuleBase for quickly creating Modules and facilitating code generation
  • Configurable post-processing (eg, gofmt) of generated files
  • Support processing proto files from multiple packages
  • Load comments (via SourceCodeInfo) from proto files into gathered AST for easy access
  • Language-specific helper subpackages for handling common, nuanced generation tasks
  • Load plugins/modules at runtime using Go shared libraries
Examples

protoc-gen-example, can be found in the testdata directory. It includes two Module implementations using a variety of the features available. It's protoc execution is included in the testdata/generated Makefile target. Examples are also accessible via the documentation by running make docs.

How It Works

The protoc Flow

Because the process is somewhat confusing, this section will cover the entire flow of how proto files are converted to generated code, using a hypothetical PG* plugin: protoc-gen-myplugin. A typical execution looks like this:

protoc \
  -I . \
  --myplugin_out="foo=bar:../generated" \
  ./pkg/*.proto

protoc, the PB compiler, is configured using a set of flags (documented under protoc -h) and handed a set of files as arguments. In this case, the I flag can be specified multiple times and is the lookup path it uses for imported dependencies in a proto file. By default, the official descriptor protos are already included.

myplugin_out tells protoc to use the protoc-gen-myplugin protoc-plugin. These plugins are automatically resolved from the system's PATH environment variable, or can be explicitly specified with another flag. The official protoc-plugins (eg, protoc-gen-python) are already registered with protoc. The flag's value is specific to the particular plugin, with the exception of the :../generated suffix. This suffix indicates the root directory in which protoc will place the generated files from that package (relative to the current working directory). This generated output directory is not propagated to protoc-gen-myplugin, however, so it needs to be duplicated in the left-hand side of the flag. PG* supports this via an output_path parameter.

protoc parses the passed in proto files, ensures they are syntactically correct, and loads any imported dependencies. It converts these files and the dependencies into descriptors (which are themselves PB messages) and creates a CodeGeneratorRequest (yet another PB). protoc serializes this request and then executes each configured protoc-plugin, sending the payload via stdin.

protoc-gen-myplugin starts up, receiving the request payload, which it unmarshals. There are two phases to a PG*-based protoc-plugin. First, PG* unmarshals the CodeGeneratorRequest received from protoc, and creates a fully connected abstract syntax tree (AST) of each file and all its contained entities. Any parameters specified for this plugin are also parsed for later consumption.

When this step is complete, PG* then executes any registered Modules, handing it the constructed AST. Modules can be written to generate artifacts (eg, files) or just performing some form of validation over the provided graph without any other side effects. Modules provide the great flexibility in terms of operating against the PBs.

Once all Modules are run, PG* writes any custom artifacts to the file system or serializes generator-specific ones into a CodeGeneratorResponse and sends the data to its stdout. protoc receives this payload, unmarshals it, and persists any requested files to disk after all its plugins have returned. This whole flow looks something like this:

foo.proto → protoc → CodeGeneratorRequest → protoc-gen-myplugin → CodeGeneratorResponse → protoc → foo.pb.go

The PG* library hides away nearly all of this complexity required to implement a protoc-plugin!

Modules

PG* Modules are handed a complete AST for those files that are targeted for generation as well as all dependencies. A Module can then add files to the protoc CodeGeneratorResponse or write files directly to disk as Artifacts.

PG* provides a ModuleBase struct to simplify developing modules. Out of the box, it satisfies the interface for a Module, only requiring the creation of Name and Execute methods. ModuleBase is best used as an anonyomous embedded field of a wrapping Module implementation. A minimal module would look like the following:

// ReportModule creates a report of all the target messages generated by the
// protoc run, writing the file into the /tmp directory.
type reportModule struct {
  *pgs.ModuleBase
}

// New configures the module with an instance of ModuleBase
func New() pgs.Module { return &reportModule{&pgs.ModuleBase{}} }

// Name is the identifier used to identify the module. This value is
// automatically attached to the BuildContext associated with the ModuleBase.
func (m *reportModule) Name() string { return "reporter" }

// Execute is passed the target files as well as its dependencies in the pkgs
// map. The implementation should return a slice of Artifacts that represent
// the files to be generated. In this case, "/tmp/report.txt" will be created
// outside of the normal protoc flow.
func (m *reportModule) Execute(targets map[string]pgs.File, pkgs map[string]pgs.Package) []pgs.Artifact {
  buf := &bytes.Buffer{}

  for _, f := range targets {
    m.Push(f.Name().String()).Debug("reporting")

    fmt.Fprintf(buf, "--- %v ---", f.Name())

    for i, msg := range f.AllMessages() {
      fmt.Fprintf(buf, "%03d. %v\n", i, msg.Name())
    }

    m.Pop()
  }

  m.OverwriteCustomFile(
    "/tmp/report.txt",
    buf.String(),
    0644,
  )

  return m.Artifacts()
}

ModuleBase exposes a PG* BuildContext instance, already prefixed with the module's name. Calling Push and Pop allows adding further information to error and debugging messages. Above, each file from the target package is pushed onto the context before logging the "reporting" debug message.

The base also provides helper methods for adding or overwriting both protoc-generated and custom files. The above execute method creates a custom file at /tmp/report.txt specifying that it should overwrite an existing file with that name. If it instead called AddCustomFile and the file existed, no file would have been generated (though a debug message would be logged out). Similar methods exist for adding generator files, appends, and injections. Likewise, methods such as AddCustomTemplateFile allows for Templates to be rendered instead.

After all modules have been executed, the returned Artifacts are either placed into the CodeGenerationResponse payload for protoc or written out to the file system. For testing purposes, the file system has been abstracted such that a custom one (such as an in-memory FS) can be provided to the PG* generator with the FileSystem InitOption.

Post Processing

Artifacts generated by Modules sometimes require some mutations prior to writing to disk or sending in the response to protoc. This could range from running gofmt against Go source or adding copyright headers to all generated source files. To simplify this task in PG*, a PostProcessor can be utilized. A minimal looking PostProcessor implementation might look like this:

// New returns a PostProcessor that adds a copyright comment to the top
// of all generated files.
func New(owner string) pgs.PostProcessor { return copyrightPostProcessor{owner} }

type copyrightPostProcessor struct {
  owner string
}

// Match returns true only for Custom and Generated files (including templates).
func (cpp copyrightPostProcessor) Match(a pgs.Artifact) bool {
  switch a := a.(type) {
  case pgs.GeneratorFile, pgs.GeneratorTemplateFile,
    pgs.CustomFile, pgs.CustomTemplateFile:
      return true
  default:
      return false
  }
}

// Process attaches the copyright header to the top of the input bytes
func (cpp copyrightPostProcessor) Process(in []byte) (out []byte, err error) {
  cmt := fmt.Sprintf("// Copyright © %d %s. All rights reserved\n",
    time.Now().Year(),
    cpp.owner)

  return append([]byte(cmt), in...), nil
}

The copyrightPostProcessor struct satisfies the PostProcessor interface by implementing the Match and Process methods. After PG* recieves all Artifacts, each is handed in turn to each registered processor's Match method. In the above case, we return true if the file is a part of the targeted Artifact types. If true is returned, Process is immediately called with the rendered contents of the file. This method mutates the input, returning the modified value to out or an error if something goes wrong. Above, the notice is prepended to the input.

PostProcessors are registered with PG* similar to Modules:

g := pgs.Init(pgs.IncludeGo())
g.RegisterModule(some.NewModule())
g.RegisterPostProcessor(copyright.New("PG* Authors"))

Protocol Buffer AST

While protoc ensures that all the dependencies required to generate a proto file are loaded in as descriptors, it's up to the protoc-plugins to recognize the relationships between them. To get around this, PG* uses constructs an abstract syntax tree (AST) of all the Entities loaded into the plugin. This AST is provided to every Module to facilitate code generation.

Hierarchy

The hierarchy generated by the PG* gatherer is fully linked, starting at a top-level Package down to each individual Field of a Message. The AST can be represented with the following digraph:

A Package describes a set of Files loaded within the same namespace. As would be expected, a File represents a single proto file, which contains any number of Message, Enum or Service entities. An Enum describes an integer-based enumeration type, containing each individual EnumValue. A Service describes a set of RPC Methods, which in turn refer to their input and output Messages.

A Message can contain other nested Messages and Enums as well as each of its Fields. For non-scalar types, a Field may also reference its Message or Enum type. As a mechanism for achieving union types, a Message can also contain OneOf entities that refer to some of its Fields.

Visitor Pattern

The structure of the AST can be fairly complex and unpredictable. Likewise, Module's are typically concerned with only a subset of the entities in the graph. To separate the Module's algorithm from understanding and traversing the structure of the AST, PG* implements the Visitor pattern to decouple the two. Implementing this interface is straightforward and can greatly simplify code generation.

Two base Visitor structs are provided by PG* to simplify developing implementations. First, the NilVisitor returns an instance that short-circuits execution for all Entity types. This is useful when certain branches of the AST are not interesting to code generation. For instance, if the Module is only concerned with Services, it can use a NilVisitor as an anonymous field and only implement the desired interface methods:

// ServiceVisitor logs out each Method's name
type serviceVisitor struct {
  pgs.Visitor
  pgs.DebuggerCommon
}

func New(d pgs.DebuggerCommon) pgs.Visitor {
  return serviceVistor{
    Visitor:        pgs.NilVisitor(),
    DebuggerCommon: d,
  }
}

// Passthrough Packages, Files, and Services. All other methods can be
// ignored since Services can only live in Files and Files can only live in a
// Package.
func (v serviceVisitor) VisitPackage(pgs.Package) (pgs.Visitor, error) { return v, nil }
func (v serviceVisitor) VisitFile(pgs.File) (pgs.Visitor, error)       { return v, nil }
func (v serviceVisitor) VisitService(pgs.Service) (pgs.Visitor, error) { return v, nil }

// VisitMethod logs out ServiceName#MethodName for m.
func (v serviceVisitor) VisitMethod(m pgs.Method) (pgs.Vistitor, error) {
  v.Logf("%v#%v", m.Service().Name(), m.Name())
  return nil, nil
}

If access to deeply nested Nodes is desired, a PassthroughVisitor can be used instead. Unlike NilVisitor and as the name suggests, this implementation passes through all nodes instead of short-circuiting on the first unimplemented interface method. Setup of this type as an anonymous field is a bit more complex but avoids implementing each method of the interface explicitly:

type fieldVisitor struct {
  pgs.Visitor
  pgs.DebuggerCommon
}

func New(d pgs.DebuggerCommon) pgs.Visitor {
  v := &fieldVisitor{DebuggerCommon: d}
  v.Visitor = pgs.PassThroughVisitor(v)
  return v
}

func (v *fieldVisitor) VisitField(f pgs.Field) (pgs.Visitor, error) {
  v.Logf("%v.%v", f.Message().Name(), f.Name())
  return nil, nil
}

Walking the AST with any Visitor is straightforward:

v := visitor.New(d)
err := pgs.Walk(v, pkg)

All Entity types and Package can be passed into Walk, allowing for starting a Visitor lower than the top-level Package if desired.

Build Context

Modules registered with the PG* Generator are initialized with an instance of BuildContext that encapsulates contextual paths, debugging, and parameter information.

Output Paths

The BuildContext's OutputPath method returns the output directory that the PG* plugin is targeting. This path is also initially . but refers to the directory in which protoc is executed. This default behavior can be overridden by providing an output_path in the flag.

The OutputPath can be used to create file names for Artifacts, using JoinPath(name ...string) which is essentially an alias for filepath.Join(ctx.OutputPath(), name...). Manually tracking directories relative to the OutputPath can be tedious, especially if the names are dynamic. Instead, a BuildContext can manage these, via PushDir and PopDir.

ctx.OutputPath()                // foo
ctx.JoinPath("fizz", "buzz.go") // foo/fizz/buzz.go

ctx = ctx.PushDir("bar/baz")
ctx.OutputPath()                // foo/bar/baz
ctx.JoinPath("quux.go")         // foo/bar/baz/quux.go

ctx = ctx.PopDir()
ctx.OutputPath()                // foo

ModuleBase wraps these methods to mutate their underlying BuildContexts. Those methods should be used instead of the ones on the contained BuildContext directly.

Debugging

The BuildContext exposes a DebuggerCommon interface which provides utilities for logging, error checking, and assertions. Log and the formatted Logf print messages to os.Stderr, typically prefixed with the Module name. Debug and Debugf behave the same, but only print if enabled via the DebugMode or DebugEnv InitOptions.

Fail and Failf immediately stops execution of the protoc-plugin and causes protoc to fail generation with the provided message. CheckErr and Assert also fail with the provided messages if an error is passed in or if an expression evaluates to false, respectively.

Additional contextual prefixes can be provided by calling Push and Pop on the BuildContext. This behavior is similar to PushDir and PopDir but only impacts log messages. ModuleBase wraps these methods to mutate their underlying BuildContexts. Those methods should be used instead of the ones on the contained BuildContext directly.

Parameters

The BuildContext also provides access to the pre-processed Parameters from the specified protoc flag. The only PG*-specific key expected is "output_path", which is utilized by a module's BuildContext for its OutputPath.

PG* permits mutating the Parameters via the MutateParams InitOption. By passing in a ParamMutator function here, these KV pairs can be modified or verified prior to the PGG workflow begins.

Language-Specific Subpackages

While implemented in Go, PG* seeks to be language agnostic in what it can do. Therefore, beyond the pre-generated base descriptor types, PG* has no dependencies on the protoc-gen-go (PGG) package. However, there are many nuances that each language's protoc-plugin introduce that can be generalized. For instance, PGG package naming, import paths, and output paths are a complex interaction of the proto package name, the go_package file option, and parameters passed to protoc. While PG*'s core API should not be overloaded with many language-specific methods, subpackages can be provided that can operate on Parameters and Entities to derive the appropriate results.

PG* currently implements the pgsgo subpackage to provide these utilities to plugins targeting the Go language. Future subpackages are planned to support a variety of languages.

PG* Development & Make Targets

PG* seeks to provide all the tools necessary to rapidly and ergonomically extend and build on top of the Protocol Buffer IDL. Whether the goal is to modify the official protoc-gen-go output or create entirely new files and packages, this library should offer a user-friendly wrapper around the complexities of the PB descriptors and the protoc-plugin workflow.

Setup

PG* can be installed and developed like any standard Go module:

go get -u github.com/lyft/protoc-gen-star/v2
Linting & Static Analysis

To avoid style nits and also to enforce some best practices for Go packages, PG* requires passing golint, go vet, and go fmt -s for all code changes.

make lint
Testing

PG* strives to have near 100% code coverage by unit tests. Most unit tests are run in parallel to catch potential race conditions. There are three ways of running unit tests, each taking longer than the next but providing more insight into test coverage:

# run code generation for the data used by the tests
make testdata

# run unit tests without race detection or code coverage reporting
make quick

# run unit tests with race detection and code coverage
make tests

# run unit tests with race detection and generates a code coverage report, opening in a browser
make cover
protoc-gen-debug

PG* comes with a specialized protoc-plugin, protoc-gen-debug. This plugin captures the CodeGeneratorRequest from a protoc execution and saves the serialized PB to disk. These files can be used as inputs to prevent calling protoc from tests.

Documentation

Go is a self-documenting language, and provides a built in utility to view locally: godoc. The following command starts a godoc server and opens a browser window to this package's documentation. If you see a 404 or unavailable page initially, just refresh.

make docs
Demo

PG* comes with a "kitchen sink" example: protoc-gen-example. This protoc plugin built on top of PG* prints out the target package's AST as a tree to stderr. This provides an end-to-end way of validating each of the nuanced types and nesting in PB descriptors:

# create the example PG*-based plugin
make bin/protoc-gen-example

# run protoc-gen-example against the demo protos
make testdata/generated
CI

PG* uses TravisCI to validate all code changes. Please view the configuration for what tests are involved in the validation.

Documentation

Overview

Package pgs provides a library for building protoc plugins

Index

Examples

Constants

View Source
const (
	// Optional (in the context of Proto2 syntax) identifies that the field may
	// be unset in the proto message. In Proto3 syntax, all fields are considered
	// Optional and default to their zero value.
	Optional = ProtoLabel(descriptor.FieldDescriptorProto_LABEL_OPTIONAL)

	// Required (in the context of Proto2 syntax) identifies that the field must
	// be set in the proto message. In Proto3 syntax, no fields can be identified
	// as Required.
	Required = ProtoLabel(descriptor.FieldDescriptorProto_LABEL_REQUIRED)

	// Repeated identifies that the field either permits multiple entries
	// (repeated) or is a map (map<key,val>). Determining which requires further
	// evaluation of the descriptor and whether or not the embedded message is
	// identified as a MapEntry (see IsMap on FieldType).
	Repeated = ProtoLabel(descriptor.FieldDescriptorProto_LABEL_REPEATED)
)

1-to-1 mapping of FieldDescriptorProto_Type enum to ProtoType. While all are listed here, group types are not supported by this library.

Variables

This section is empty.

Functions

func C

func C(wrap int, args ...interface{}) string

C returns a comment block, wrapping when the line's length will exceed wrap.

func C80

func C80(args ...interface{}) string

C80 is an alias for C(80, args...)

func ID

func ID(s string) string

ID is a NameTransformer that does not mutate the string.

func Walk

func Walk(v Visitor, n Node) error

Walk applies a depth-first visitor pattern with v against Node n.

Types

type AST

type AST interface {
	// Targets returns a map of the files specified in the protoc execution. For
	// all Entities contained in these files, BuildTarget will return true.
	Targets() map[string]File

	// Packages returns all the imported packages (including those for the target
	// Files). This is limited to just the files that were imported by target
	// protos, either directly or transitively.
	Packages() map[string]Package

	// Lookup allows getting an Entity from the graph by its fully-qualified name
	// (FQN). The FQN uses dot notation of the form ".{package}.{entity}", or the
	// input path for Files.
	Lookup(name string) (Entity, bool)
}

AST encapsulates the entirety of the input CodeGeneratorRequest from protoc, parsed to build the Entity graph used by PG*.

func ProcessCodeGeneratorRequest

func ProcessCodeGeneratorRequest(debug Debugger, req *plugin_go.CodeGeneratorRequest) AST

ProcessCodeGeneratorRequest converts a CodeGeneratorRequest from protoc into a fully connected AST entity graph. An error is returned if the input is malformed.

func ProcessCodeGeneratorRequestBidirectional

func ProcessCodeGeneratorRequestBidirectional(debug Debugger, req *plugin_go.CodeGeneratorRequest) AST

ProcessCodeGeneratorRequestBidirectional has the same functionality as ProcessCodeGeneratorRequest, but builds the AST so that files, messages, and enums have references to any files or messages that directly or transitively depend on them.

func ProcessDescriptors

func ProcessDescriptors(debug Debugger, req *plugin_go.CodeGeneratorRequest) AST

ProcessDescriptors is deprecated; use ProcessCodeGeneratorRequest instead

func ProcessFileDescriptorSet

func ProcessFileDescriptorSet(debug Debugger, fdset *descriptor.FileDescriptorSet) AST

ProcessFileDescriptorSet converts a FileDescriptorSet from protoc into a fully connected AST entity graph. An error is returned if the input is malformed or missing dependencies. To generate a self-contained FileDescriptorSet, run the following command:

protoc -o path/to/fdset.bin --include_imports $PROTO_FILES

The emitted AST will have no values in the Targets map, but Packages will be populated. If used for testing purposes, the Targets map can be manually populated.

func ProcessFileDescriptorSetBidirectional

func ProcessFileDescriptorSetBidirectional(debug Debugger, fdset *descriptor.FileDescriptorSet) AST

ProcessFileDescriptorSetBidirectional has the same functionality as ProcessFileDescriptorSet, but builds the AST so that files, messages, and enums have references to any files or messages that directly or transitively depend on them.

type Artifact

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

An Artifact describes the output for a Module. Typically this is the creation of a file either directly against the file system or via protoc.

type BuildContext

type BuildContext interface {
	DebuggerCommon

	// OutputPath is the path where files should be generated to. This path may
	// be relative or absolute, if it is relative, the path is based off the
	// (unknown) output destination specified during execution of protoc. If it
	// is absolute, the path may be outside of the target directory for protoc.
	OutputPath() string

	// JoinPath returns name relative to the value of OutputPath.
	JoinPath(name ...string) string

	// Push adds an arbitrary prefix to the Debugger output. The Outpath value is
	// unchanged.
	Push(prefix string) BuildContext

	// PushDir changes the BuildContext's OutputPath to dir. If dir is relative,
	// it is applied relative to the current value of OutputPath.
	PushDir(dir string) BuildContext

	// Pop returns the previous state of the BuildContext. This may or may not
	// change the value of OutputPath. This method will cause the plugin to fail
	// if the root context is popped.
	Pop() BuildContext

	// PopDir behaves like Pop but returns the last previous state of OutputPath,
	// skipping over any prefix changes in-between. If at the root context, this
	// method will always return the root context.
	PopDir() BuildContext

	// Parameters returns the command line parameters passed in from protoc,
	// mutated with any provided ParamMutators via InitOptions.
	Parameters() Parameters
}

BuildContext tracks code generation relative to an output path. By default, BuildContext's path is relative to the output location specified when executing protoc (an absolute path to this location is not available within protoc plugins). Specifying a custom output path permits using an absolute path and or a different location from protoc's designated output location.

func Context

func Context(d Debugger, params Parameters, output string) BuildContext

Context creates a new BuildContext with the provided debugger and initial output path. For protoc-gen-go plugins, output is typically ".", while Module's may use a custom path.

type CustomFile

type CustomFile struct {
	Artifact

	// Name of the file to generate. If relative, the file is created relative to
	// the directory in which protoc is executed. If absolute, the file is
	// created as specified.
	Name string

	// Contents are the body of the file.
	Contents string

	// Perms are the file permission to generate the file with. Note that the
	// umask of the process will be applied against these permissions.
	Perms os.FileMode

	// Overwrite indicates if an existing file on disk should be overwritten by
	// this file.
	Overwrite bool
}

CustomFile Artifacts are files generated directly against the file system, and do not use protoc for the generation. CustomFiles should be used over GeneratorFiles when custom permissions need to be set (such as executable scripts or read-only configs) or when the file needs to be created outside of the protoc-plugin's generation output directory.

type CustomTemplateFile

type CustomTemplateFile struct {
	Artifact
	TemplateArtifact

	// Name of the file to generate. If relative, the file is created relative to
	// the directory in which protoc is executed. If absolute, the file is
	// created as specified.
	Name string

	// Perms are the file permission to generate the file with. Note that the
	// umask of the process will be applied against these permissions.
	Perms os.FileMode

	// Overwrite indicates if an existing file on disk should be overwritten by
	// this file.
	Overwrite bool
}

CustomTemplateFile Artifacts are files generated from a Template directly against the file system, and do not use protoc for the generation. CustomFiles should be used over GeneratorFiles when custom permissions need to be set (such as executable scripts or read-only configs) or when the file needs to be created outside of the protoc-plugin's generation output directory.

type Debugger

type Debugger interface {
	DebuggerCommon

	// Push returns a new Debugger with the provided prefix. When entering a new
	// context, this method should be used.
	Push(prefix string) Debugger

	// Pop returns the parent for the current Debugger. When exiting a context,
	// this method should be used.
	Pop() Debugger
}

A Debugger provides utility methods to provide context-aware logging, error-checking, and assertions. The Debugger is used extensively within the protoc-gen-star generator, and is provided in a module's build context.

type DebuggerCommon

type DebuggerCommon interface {
	// Log writes v to the underlying logging location (typically, os.Stderr). It
	// uses the same behavior as log.Print, with all prefixes already attached.
	Log(v ...interface{})

	// Logf formats v and writes it to the underlying logging location
	// (typically, os.Stderr). It uses the same behavior as log.Printf, with all
	// prefixes already attached.
	Logf(format string, v ...interface{})

	// Debug behaves the same as Log, but only writes its output if debugging is
	// enabled for this Debugger.
	Debug(v ...interface{})

	// Debugf behaves the same as Logf, but only writes its output if debugging
	// is enabled for this Debugger.
	Debugf(format string, v ...interface{})

	// Fail behaves the same as Log, but also terminates the process. This method
	// should be used if an un-recoverable error is encountered.
	Fail(v ...interface{})

	// Failf behaves the same as Logf, but also terminates the process. This
	// method should be used if an un-recoverable error is encountered.
	Failf(format string, v ...interface{})

	// CheckErr ensures that err is nil. If err is not nil, Fail is called with
	// err and the provided v.
	CheckErr(err error, v ...interface{})

	// Assert ensures that expr evaluates to true. If expr is false, Fail is
	// called with the provided v.
	Assert(expr bool, v ...interface{})

	// Exit should terminate the current process with the provided code.
	Exit(code int)
}

DebuggerCommon contains shared features of Debugger and Debugger-like types (such as BuildContext).

type Entity

type Entity interface {
	Node

	// The Name of the entity
	Name() Name

	// The fully qualified name of the entity. For example, a message
	// 'HelloRequest' in a 'helloworld' package takes the form of
	// '.helloworld.HelloRequest'.
	FullyQualifiedName() string

	// Syntax identifies whether this entity is encoded with proto2 or proto3
	// syntax.
	Syntax() Syntax

	// Package returns the container package for this entity.
	Package() Package

	// Imports includes external files directly required by this entity. Call
	// TransitiveImports on File to get all transitive dependencies.
	Imports() []File

	// File returns the File containing this entity.
	File() File

	// Extension extracts an extension from the entity's options, described by
	// desc and populates the value ext. Ext must be a pointer type. An error
	// will only be returned if there is a type mismatch between desc and ext.
	// The ok value will be true if the extension was found. If the extension
	// is NOT found, ok will be false and err will be nil.
	Extension(desc *protoimpl.ExtensionInfo, ext interface{}) (ok bool, err error)

	// BuildTarget identifies whether or not generation should be performed on
	// this entity. Use this flag to determine if the file was targeted in the
	// protoc run or if it was loaded as an external dependency.
	BuildTarget() bool

	// SourceCodeInfo returns the SourceCodeInfo associated with the entity.
	// Primarily, this struct contains the comments associated with the Entity.
	SourceCodeInfo() SourceCodeInfo
	// contains filtered or unexported methods
}

Entity describes any member of the proto AST that is extensible via options. All components of a File are considered entities.

type Enum

type Enum interface {
	Entity

	// Descriptor returns the proto descriptor for this Enum
	Descriptor() *descriptor.EnumDescriptorProto

	// Parent resolves to either a Message or File that directly contains this
	// Enum.
	Parent() ParentEntity

	// Values returns each defined enumeration value.
	Values() []EnumValue

	// Dependents returns all of the messages where Enum is directly or
	// transitively used.
	Dependents() []Message
	// contains filtered or unexported methods
}

Enum describes an enumeration type. Its parent can be either a Message or a File.

type EnumValue

type EnumValue interface {
	Entity

	// Descriptor returns the proto descriptor for this Enum Value
	Descriptor() *descriptor.EnumValueDescriptorProto

	// Enum returns the parent Enum for this value
	Enum() Enum

	// Value returns the numeric enum value associated with this type
	Value() int32
	// contains filtered or unexported methods
}

An EnumValue describes a name-value pair for an entry in an enum.

type Extension

type Extension interface {
	Field

	// ParentEntity returns the ParentEntity where the Extension is defined
	DefinedIn() ParentEntity

	// Extendee returns the Message that the Extension is extending
	Extendee() Message
	// contains filtered or unexported methods
}

An Extension is a custom option annotation that can be applied to an Entity to provide additional semantic details and metadata about the Entity.

type Field

type Field interface {
	Entity

	// Descriptor returns the proto descriptor for this field
	Descriptor() *descriptor.FieldDescriptorProto

	// Message returns the Message containing this Field.
	Message() Message

	// InOneOf returns true if the field is in a OneOf of the parent Message.
	// This will return true for synthetic oneofs (proto3 field presence) as well.
	InOneOf() bool

	// InRealOneOf returns true if the field is in a OneOf of the parent Message.
	// This will return false for synthetic oneofs, and will only include 'real' oneofs.
	// See: https://github.com/protocolbuffers/protobuf/blob/v3.17.0/docs/field_presence.md
	InRealOneOf() bool

	// OneOf returns the OneOf that this field is a part of. Nil is returned if
	// the field is not within a OneOf.
	OneOf() OneOf

	// Type returns the FieldType of this Field.
	Type() FieldType

	// HasPresence returns true for all fields that have explicit presence as defined by:
	// See: https://github.com/protocolbuffers/protobuf/blob/v3.17.0/docs/field_presence.md
	HasPresence() bool

	// HasOptionalKeyword returns whether the field is labeled as optional.
	HasOptionalKeyword() bool

	// Required returns whether the field is labeled as required. This
	// will only be true if the syntax is proto2.
	Required() bool
	// contains filtered or unexported methods
}

A Field describes a member of a Message. A field may also be a member of a OneOf on the Message.

type FieldType

type FieldType interface {
	// Field returns the parent Field of this type. While two FieldTypes might be
	// equivalent, each instance of a FieldType is tied to its Field.
	Field() Field

	// IsRepeated returns true if and only if the field is marked as "repeated".
	// While map fields may be labeled as repeated, this method will not return
	// true for them.
	IsRepeated() bool

	// IsMap returns true if the field is a map type.
	IsMap() bool

	// IsEnum returns true if the field is a singular enum value. Maps or
	// repeated fields containing enums will still return false.
	IsEnum() bool

	// IsEmbed returns true if the field is a singular message value. Maps or
	// repeated fields containing embeds will still return false.
	IsEmbed() bool

	// IsOptional returns true if the field is prefixed as optional.
	IsOptional() bool

	// IsRequired returns true if and only if the field is prefixed as required.
	IsRequired() bool

	// ProtoType returns the ProtoType value for this field.
	ProtoType() ProtoType

	// ProtoLabel returns the ProtoLabel value for this field.
	ProtoLabel() ProtoLabel

	// Imports includes all external proto files required by this field.
	Imports() []File

	// Enum returns the Enum associated with this FieldType. If IsEnum returns
	// false, this value will be nil.
	Enum() Enum

	// Embed returns the embedded Message associated with this FieldType. If
	// IsEmbed returns false, this value will be nil.
	Embed() Message

	// Element returns the FieldTypeElem representing the element component of
	// the type.
	//
	// For repeated fields, the returned type describes the type being repeated (i.e.,
	// the element type in the list implied by the repeated field).
	//
	// For maps, the returned type describes the type of values in the map.
	//
	// Nil will be returned if IsRepeated and IsMap both return false.
	Element() FieldTypeElem

	// Key returns the FieldTypeElem representing the key component of the type (i.e,
	// the type of keys in a map).
	//
	// Nil will be returned if IsMap returns false.
	Key() FieldTypeElem
	// contains filtered or unexported methods
}

FieldType describes the type of a Field.

type FieldTypeElem

type FieldTypeElem interface {
	// ParentType returns the parent FieldType that holds this element.
	ParentType() FieldType

	// ProtoType returns the ProtoType describing this component.
	ProtoType() ProtoType

	// IsEmbed returns true if the component is an embedded message.
	IsEmbed() bool

	// IsEnum returns true if the component is an enum value.
	IsEnum() bool

	// Imports includes all external Files required by this field.
	Imports() []File

	// Enum returns the Enum associated with this FieldTypeElem. If IsEnum
	// returns false, this value will be nil.
	Enum() Enum

	// Embed returns the embedded Message associated with this FieldTypeElem. If
	// IsEmbed returns false, this value will be nil.
	Embed() Message
	// contains filtered or unexported methods
}

FieldTypeElem describes a component of a FieldType. This type only shows up in repeated and map FieldTypes.

type File

type File interface {
	ParentEntity

	// InputPath returns the input FilePath. This is equivalent to the value
	// returned by Name.
	InputPath() FilePath

	// Descriptor returns the underlying descriptor for the proto file
	Descriptor() *descriptor.FileDescriptorProto

	// TransitiveImports returns all direct and transitive dependencies of this
	// File. Use Imports to obtain only direct dependencies.
	TransitiveImports() []File

	// UnusedImports returns all imported files that aren't used by the current
	// File. Public imports are not included in this list.
	UnusedImports() []File

	// Dependents returns all files where the given file was directly or
	// transitively imported.
	Dependents() []File

	// Services returns the services from this proto file.
	Services() []Service

	// SyntaxSourceCodeInfo returns the comment info attached to the `syntax`
	// stanza of the file. This method is an alias of the SourceCodeInfo method.
	SyntaxSourceCodeInfo() SourceCodeInfo

	// PackageSourceCodeInfo returns the comment info attached to the `package`
	// stanza of the file.
	PackageSourceCodeInfo() SourceCodeInfo
	// contains filtered or unexported methods
}

File describes the contents of a single proto file.

type FilePath

type FilePath string

A FilePath describes the name of a file or directory. This type simplifies path related operations.

func JoinPaths

func JoinPaths(elem ...string) FilePath

JoinPaths is an convenient alias around filepath.Join, to easily create FilePath types.

func (FilePath) Base

func (n FilePath) Base() string

Base returns the base of the current FilePath (the last element in the path). This method is an alias around filepath.Base.

func (FilePath) BaseName

func (n FilePath) BaseName() string

BaseName returns the Base of the current FilePath without Ext.

func (FilePath) Dir

func (n FilePath) Dir() FilePath

Dir returns the parent directory of the current FilePath. This method is an alias around filepath.Dir.

func (FilePath) Ext

func (n FilePath) Ext() string

Ext returns the extension of the current FilePath (starting at and including the last '.' in the FilePath). This method is an alias around filepath.Ext.

func (FilePath) Pop

func (n FilePath) Pop() FilePath

Pop returns a new FilePath with the last element removed. Pop is an alias for the Dir method.

func (FilePath) Push

func (n FilePath) Push(elem string) FilePath

Push returns a new FilePath with elem added to the end

func (FilePath) SetBase

func (n FilePath) SetBase(base string) FilePath

SetBase returns a new FilePath with the base element replaced with base.

func (FilePath) SetExt

func (n FilePath) SetExt(ext string) FilePath

SetExt returns a new FilePath with the extension replaced with ext.

func (FilePath) String

func (n FilePath) String() string

String satisfies the strings.Stringer interface.

type Generator

type Generator struct {
	Debugger
	// contains filtered or unexported fields
}

Generator configures and executes a protoc plugin's lifecycle.

func Init

func Init(opts ...InitOption) *Generator

Init configures a new Generator. InitOptions may be provided as well to modify the behavior of the generator.

func (*Generator) AST

func (g *Generator) AST() AST

AST returns the constructed AST graph from the gatherer. This method is idempotent, can be called multiple times (before and after calls to Render, even), and is particularly useful in testing.

func (*Generator) RegisterModule

func (g *Generator) RegisterModule(m ...Module) *Generator

RegisterModule should be called before Render to attach a custom Module to the Generator. This method can be called multiple times.

func (*Generator) RegisterPostProcessor

func (g *Generator) RegisterPostProcessor(p ...PostProcessor) *Generator

RegisterPostProcessor should be called before Render to attach PostProcessors to the Generator. This method can be called multiple times. PostProcessors are executed against their matches in the order in which they are registered.

func (*Generator) Render

func (g *Generator) Render()

Render executes the protoc plugin flow, gathering the AST from the input io.Reader (typically stdin via protoc), running all the registered modules, and persisting the generated artifacts to the output io.Writer (typically stdout to protoc + direct file system writes for custom artifacts). This method is idempotent, in that subsequent calls to Render will have no effect.

type GeneratorAppend

type GeneratorAppend struct {
	GeneratorArtifact

	// Filename of the file to append to, relative to the protoc-plugin's generation
	// output directory.
	FileName string

	// Contents to be appended to the file
	Contents string
}

A GeneratorAppend Artifact appends content to the end of the specified protoc generated file. This Artifact can only be used if another Module generates a file with the same name.

func (GeneratorAppend) ProtoFile

ProtoFile satisfies the GeneratorArtifact interface. An error is returned if the name field is not a path relative to and within the protoc-plugin's generation output directory.

type GeneratorArtifact

type GeneratorArtifact interface {
	Artifact

	// ProtoFile converts the GeneratorArtifact to a CodeGeneratorResponse_File,
	// which is handed to protoc to actually write the file to disk. An error is
	// returned if Artifact cannot be converted.
	ProtoFile() (*plugin_go.CodeGeneratorResponse_File, error)
}

GeneratorArtifact describes an Artifact that uses protoc for code generation. GeneratorArtifacts must be valid UTF8. To create binary files, use one of the "custom" Artifact types.

type GeneratorError

type GeneratorError struct {
	Artifact

	Message string
}

GeneratorError Artifacts are strings describing errors that happened in the code generation, but have not been fatal. They'll be used to populate the CodeGeneratorResponse's `error` field. Since that field is a string, multiple GeneratorError Artifacts will be concatenated.

type GeneratorFile

type GeneratorFile struct {
	GeneratorArtifact

	// Name of the file to generate, relative to the protoc-plugin's generation
	// output directory.
	Name string

	// Contents are the body of the file.
	Contents string

	// Overwrite specifies whether or not this file should replace another file
	// with the same name if a prior Plugin or Module has created one.
	Overwrite bool
}

A GeneratorFile Artifact describes a file to be generated using protoc.

func (GeneratorFile) ProtoFile

ProtoFile satisfies the GeneratorArtifact interface. An error is returned if the name field is not a path relative to and within the protoc-plugin's generation output directory.

type GeneratorInjection

type GeneratorInjection struct {
	GeneratorArtifact

	// Filename of the file to inject into, relative to the protoc-plugin's
	// generation output directory.
	FileName string

	// The name of the insertion point to inject into
	InsertionPoint string

	// Contents to be inject into the file
	Contents string
}

A GeneratorInjection Artifact inserts content into a protoc-generated file at the specified insertion point. The target file does not need to be generated by this protoc-plugin but must be generated by a prior plugin executed by protoc.

func (GeneratorInjection) ProtoFile

ProtoFile satisfies the GeneratorArtifact interface. An error is returned if the name field is not a path relative to and within the protoc-plugin's generation output directory.

type GeneratorTemplateAppend

type GeneratorTemplateAppend struct {
	GeneratorArtifact
	TemplateArtifact

	// Filename of the file to append to, relative to the protoc-plugin's generation
	// output directory.
	FileName string
}

A GeneratorTemplateAppend appends content to a protoc-generated file from a Template. See GeneratorAppend for limitations.

func (GeneratorTemplateAppend) ProtoFile

ProtoFile satisfies the GeneratorArtifact interface. An error is returned if the name field is not a path relative to and within the protoc-plugin's generation output directory or if there is an error executing the Template.

type GeneratorTemplateFile

type GeneratorTemplateFile struct {
	GeneratorArtifact
	TemplateArtifact

	// Name of the file to generate, relative to the protoc-plugin's generation
	// output directory.
	Name string

	// Overwrite specifies whether or not this file should replace another file
	// with the same name if a prior Plugin or Module has created one.
	Overwrite bool
}

A GeneratorTemplateFile describes a file to be generated using protoc from a Template.

func (GeneratorTemplateFile) ProtoFile

ProtoFile satisfies the GeneratorArtifact interface. An error is returned if the name field is not a path relative to and within the protoc-plugin's generation output directory or if there is an error executing the Template.

type GeneratorTemplateInjection

type GeneratorTemplateInjection struct {
	GeneratorArtifact
	TemplateArtifact

	// Filename of the file to inject into, relative to the protoc-plugin's
	// generation output directory.
	FileName string

	// The name of the insertion point to inject into
	InsertionPoint string
}

A GeneratorTemplateInjection Artifact inserts content rendered from a Template into protoc-generated file at the specified insertion point. The target file does not need to be generated by this protoc-plugin but must be generated by a prior plugin executed by protoc.

func (GeneratorTemplateInjection) ProtoFile

ProtoFile satisfies the GeneratorArtifact interface. An error is returned if the name field is not a path relative to and within the protoc-plugin's generation output directory or if there is an error executing the Template.

type InitOption

type InitOption func(g *Generator)

An InitOption modifies the behavior of a Generator at initialization.

func BiDirectional

func BiDirectional() InitOption

BiDirectional instructs the Generator to build the AST graph in both directions (ie, accessing dependents of an entity, not just dependencies).

func DebugEnv

func DebugEnv(f string) InitOption

DebugEnv enables verbose logging only if the passed in environment variable is non-empty.

func DebugMode

func DebugMode() InitOption

DebugMode enables verbose logging for module development and debugging.

func FileSystem

func FileSystem(fs afero.Fs) InitOption

FileSystem overrides the default file system used to write Artifacts to disk. By default, the OS's file system is used. This option currently only impacts CustomFile and CustomTemplateFile artifacts generated by modules.

func MutateParams

func MutateParams(pm ...ParamMutator) InitOption

MutateParams applies pm to the parameters passed in from protoc.

func ProtocInput

func ProtocInput(r io.Reader) InitOption

ProtocInput changes the input io.Reader source. This value is where the serialized CodeGeneratorRequest is received from protoc. By default, os.Stdin is used.

func ProtocOutput

func ProtocOutput(w io.Writer) InitOption

ProtocOutput changes the output io.Writer destination. This value is where the serialized CodeGeneratorResponse is sent to protoc. By default, os.Stdout is used.

type Message

type Message interface {
	ParentEntity

	// Descriptor returns the underlying proto descriptor for this message
	Descriptor() *descriptor.DescriptorProto

	// Parent returns either the File or Message that directly contains this
	// Message.
	Parent() ParentEntity

	// Fields returns all fields on the message, including those contained within
	// OneOf blocks.
	Fields() []Field

	// NonOneOfFields returns all fields not contained within OneOf blocks.
	NonOneOfFields() []Field

	// OneOfFields returns only the fields contained within OneOf blocks.
	OneOfFields() []Field

	// SyntheticOneOfFields returns only the fields contained within synthetic OneOf blocks.
	// See: https://github.com/protocolbuffers/protobuf/blob/v3.17.0/docs/field_presence.md
	SyntheticOneOfFields() []Field

	// OneOfs returns the OneOfs contained within this Message.
	OneOfs() []OneOf

	// RealOneOfs returns the OneOfs contained within this Message.
	// This excludes synthetic OneOfs.
	// See: https://github.com/protocolbuffers/protobuf/blob/v3.17.0/docs/field_presence.md
	RealOneOfs() []OneOf

	// Extensions returns all of the Extensions applied to this Message.
	Extensions() []Extension

	// Dependents returns all of the messages where message is directly or
	// transitively used.
	Dependents() []Message

	// IsMapEntry identifies this message as a MapEntry. If true, this message is
	// not generated as code, and is used exclusively when marshaling a map field
	// to the wire format.
	IsMapEntry() bool

	// IsWellKnown identifies whether or not this Message is a WKT from the
	// `google.protobuf` package. Most official plugins special case these types
	// and they usually need to be handled differently.
	IsWellKnown() bool

	// WellKnownType returns the WellKnownType associated with this field. If
	// IsWellKnown returns false, UnknownWKT is returned.
	WellKnownType() WellKnownType
	// contains filtered or unexported methods
}

Message describes a proto message. Messages can be contained in either another Message or File, and may house further Messages and/or Enums. While all Fields technically live on the Message, some may be contained within OneOf blocks.

type Method

type Method interface {
	Entity

	// Descriptor returns the underlying proto descriptor for this.
	Descriptor() *descriptor.MethodDescriptorProto

	// Service returns the parent service for this.
	Service() Service

	// Input returns the Message representing the input type for this.
	Input() Message

	// Output returns the Message representing the output type for this.
	Output() Message

	// ClientStreaming indicates if this method allows clients to stream inputs.
	ClientStreaming() bool

	// ServerStreaming indicates if this method allows servers to stream outputs.
	ServerStreaming() bool
	// contains filtered or unexported methods
}

Method describes a method on a proto service

type MockDebugger

type MockDebugger interface {
	Debugger

	// Output returns a reader of all logged data.
	Output() io.Reader

	// Failed returns true if Fail or Failf has been called on this debugger or a
	// descendant of it (via Push).
	Failed() bool

	// Err returns the error passed to CheckErr.
	Err() error

	// Exited returns true if this Debugger (or a descendant of it) would have
	// called os.Exit.
	Exited() bool

	// ExitCode returns the code this Debugger (or a descendant of it) passed to
	// os.Exit. If Exited() returns false, this value is meaningless.
	ExitCode() int
}

MockDebugger serves as a root Debugger instance for usage in tests. Unlike an actual Debugger, MockDebugger will not exit the program, but will track failures, checked errors, and exit codes.

func InitMockDebugger

func InitMockDebugger() MockDebugger

InitMockDebugger creates a new MockDebugger for usage in tests.

type Module

type Module interface {
	// The Name of the Module, used when establishing the build context and used
	// as the base prefix for all debugger output.
	Name() string

	// InitContext is called on a Module with a pre-configured BuildContext that
	// should be stored and used by the Module.
	InitContext(c BuildContext)

	// Execute is called on the module with the target Files as well as all
	// loaded Packages from the gatherer. The module should return a slice of
	// Artifacts that it would like to be generated.
	Execute(targets map[string]File, packages map[string]Package) []Artifact
}

Module describes the interface for a domain-specific code generation module that can be registered with the PG* generator.

type ModuleBase

type ModuleBase struct {
	BuildContext
	// contains filtered or unexported fields
}

ModuleBase provides utility methods and a base implementation for a protoc-gen-star Module. ModuleBase should be used as an anonymously embedded field of an actual Module implementation. The only methods that need to be overridden are Name and Execute.

type MyModule {
    *pgs.ModuleBase
}

func InitMyModule() *MyModule { return &MyModule{ &pgs.ModuleBase{} } }

func (m *MyModule) Name() string { return "MyModule" }

func (m *MyModule) Execute(...) []pgs.Artifact { ... }

func (*ModuleBase) AddArtifact

func (m *ModuleBase) AddArtifact(a ...Artifact)

AddArtifact adds an Artifact to this Module's collection of generation artifacts. This method is available as a convenience but the other Add & Overwrite methods should be used preferentially.

func (*ModuleBase) AddCustomFile

func (m *ModuleBase) AddCustomFile(name, content string, perms os.FileMode)

AddCustomFile creates a file directly on the file system with the provided content and perms. Unlike AddGeneratorFile, this method does not use protoc to generate the file. If name is a relative path, it is related to the directory in which protoc was executed; name can also be an absolute path. If a file already exists with the specified name, the file will not be created and there will be no generation error.

func (*ModuleBase) AddCustomTemplateFile

func (m *ModuleBase) AddCustomTemplateFile(name string, tpl Template, data interface{}, perms os.FileMode)

AddCustomTemplateFile behaves the same as AddCustomFile, however the contents are rendered from the provided tpl and data.

func (*ModuleBase) AddError

func (m *ModuleBase) AddError(message string)

AddError adds a string to the `errors` field of the created CodeGeneratorResponse. Multiple calls to AddError will cause the errors to be concatenated (separated by "; ").

func (*ModuleBase) AddGeneratorAppend

func (m *ModuleBase) AddGeneratorAppend(name, content string)

AddGeneratorAppend attempts to append content to the specified file name. Name must be a path relative to and within the protoc-plugin's output destination, which may differ from the BuildContext's OutputPath value. If the file is not generated by this protoc-plugin, execution will fail.

func (*ModuleBase) AddGeneratorFile

func (m *ModuleBase) AddGeneratorFile(name, content string)

AddGeneratorFile adds a file with the provided name and contents to the code generation response payload to protoc. Name must be a path relative to and within the protoc-plugin's output destination, which may differ from the BuildContext's OutputPath value. If another Module or Plugin has added a file with the same name, protoc will produce an error.

func (*ModuleBase) AddGeneratorInjection

func (m *ModuleBase) AddGeneratorInjection(name, point, content string)

AddGeneratorInjection attempts to inject content into the file with name at the specified insertion point. Name must be a path relative to and within the protoc-plugin's output destination, which may differ from the BuildContext's OutputPath value. The file does not need to be generated by this protoc-plugin but the generating plugin must be called first in the protoc execution.

See: https://godoc.org/github.com/golang/protobuf/protoc-gen-go/plugin#CodeGeneratorResponse_File

func (*ModuleBase) AddGeneratorTemplateAppend

func (m *ModuleBase) AddGeneratorTemplateAppend(name string, tpl Template, data interface{})

AddGeneratorTemplateAppend behaves the same as AddGeneratorAppend, however the contents are rendered from the provided tpl and data.

func (*ModuleBase) AddGeneratorTemplateFile

func (m *ModuleBase) AddGeneratorTemplateFile(name string, tpl Template, data interface{})

AddGeneratorTemplateFile behaves the same as AddGeneratorFile, however the contents are rendered from the provided tpl and data.

func (*ModuleBase) AddGeneratorTemplateInjection

func (m *ModuleBase) AddGeneratorTemplateInjection(name, point string, tpl Template, data interface{})

AddGeneratorTemplateInjection behaves the same as AddGeneratorInjection, however the contents are rendered from the provided tpl and data.

func (*ModuleBase) Artifacts

func (m *ModuleBase) Artifacts() []Artifact

Artifacts returns the slice of generation artifacts that have been captured by the Module. This method should/can be the return value of its Execute method. Subsequent calls will return a nil slice until more artifacts are added.

func (*ModuleBase) Execute

func (m *ModuleBase) Execute(targets map[string]File, packages map[string]Package) []Artifact

Execute satisfies the Module interface, however this method will fail and must be overridden by a parent struct.

func (*ModuleBase) InitContext

func (m *ModuleBase) InitContext(c BuildContext)

InitContext populates this Module with the BuildContext from the parent Generator, allowing for easy debug logging, error checking, and output path management. This method is called prior to Execute for modules registered with the generator.

func (*ModuleBase) Name

func (m *ModuleBase) Name() string

Name satisfies the Module interface, however this method will panic and must be overridden by a parent struct.

func (*ModuleBase) OverwriteCustomFile

func (m *ModuleBase) OverwriteCustomFile(name, content string, perms os.FileMode)

OverwriteCustomFile behaves the same as AddCustomFile, however if the file already exists, it will be overwritten with this one.

func (*ModuleBase) OverwriteCustomTemplateFile

func (m *ModuleBase) OverwriteCustomTemplateFile(name string, tpl Template, data interface{}, perms os.FileMode)

OverwriteCustomTemplateFile behaves the same as OverwriteCustomFile, however the contents are rendered from the provided tpl and data.

func (*ModuleBase) OverwriteGeneratorFile

func (m *ModuleBase) OverwriteGeneratorFile(name, content string)

OverwriteGeneratorFile behaves the same as AddGeneratorFile, however if a previously executed Module has created a file with the same name, it will be overwritten with this one.

func (*ModuleBase) OverwriteGeneratorTemplateFile

func (m *ModuleBase) OverwriteGeneratorTemplateFile(name string, tpl Template, data interface{})

OverwriteGeneratorTemplateFile behaves the same as OverwriteGeneratorFile, however the contents are rendered from the provided tpl and data.

func (*ModuleBase) Pop

func (m *ModuleBase) Pop() BuildContext

Pop removes the last push from the Module's BuildContext. This method should only be called after a paired Push or PushDir.

func (*ModuleBase) PopDir

func (m *ModuleBase) PopDir() BuildContext

PopDir removes the last PushDir from the Module's BuildContext. This method should only be called after a paired PushDir.

func (*ModuleBase) Push

func (m *ModuleBase) Push(prefix string) BuildContext

Push adds a prefix to the Module's BuildContext. Pop should be called when the context is complete.

func (*ModuleBase) PushDir

func (m *ModuleBase) PushDir(dir string) BuildContext

PushDir changes the OutputPath of the Module's BuildContext. Pop (or PopDir) should be called when that context is complete.

type Name

type Name string

A Name describes an identifier of an Entity (Message, Field, Enum, Service, Field). It can be converted to multiple forms using the provided helper methods, or a custom transform can be used to modify its behavior.

const WellKnownTypePackage Name = "google.protobuf"

WellKnownTypePackage is the proto package name where all Well Known Types currently reside.

func (Name) LowerCamelCase

func (n Name) LowerCamelCase() Name

LowerCamelCase converts Name n to lower camelcase, where each part is title-cased and concatenated with no separator except the first which is lower-cased.

Example
names := []string{
	"foo_bar",
	"myJSON",
	"PDFTemplate",
}

for _, n := range names {
	fmt.Println(Name(n).LowerCamelCase())
}
Output:

fooBar
myJSON
pdfTemplate

func (Name) LowerDotNotation

func (n Name) LowerDotNotation() Name

LowerDotNotation converts Name n to lower dot notation, where each part is lower-cased and concatenated with periods.

Example
names := []string{
	"foo_bar",
	"myJSON",
	"PDFTemplate",
}

for _, n := range names {
	fmt.Println(Name(n).LowerDotNotation())
}
Output:

foo.bar
my.json
pdf.template

func (Name) LowerSnakeCase

func (n Name) LowerSnakeCase() Name

LowerSnakeCase converts Name n to lower-snake-case, where each part is lower-cased and concatenated with underscores.

Example
names := []string{
	"foo_bar",
	"myJSON",
	"PDFTemplate",
}

for _, n := range names {
	fmt.Println(Name(n).LowerSnakeCase())
}
Output:

foo_bar
my_json
pdf_template

func (Name) ScreamingSnakeCase

func (n Name) ScreamingSnakeCase() Name

ScreamingSnakeCase converts Name n to screaming-snake-case, where each part is all-caps and concatenated with underscores.

Example
names := []string{
	"foo_bar",
	"myJSON",
	"PDFTemplate",
}

for _, n := range names {
	fmt.Println(Name(n).ScreamingSnakeCase())
}
Output:

FOO_BAR
MY_JSON
PDF_TEMPLATE

func (Name) SnakeCase

func (n Name) SnakeCase() Name

SnakeCase converts Name n to snake-case, where each part preserves its capitalization and concatenated with underscores.

Example
names := []string{
	"foo_bar",
	"myJSON",
	"PDFTemplate",
}

for _, n := range names {
	fmt.Println(Name(n).SnakeCase())
}
Output:

foo_bar
my_JSON
PDF_Template

func (Name) Split

func (n Name) Split() (parts []string)

Split breaks apart Name n into its constituent components. Precedence follows dot notation, then underscores (excluding underscore prefixes), then camelcase. Numbers are treated as standalone components.

func (Name) String

func (n Name) String() string

String satisfies the strings.Stringer interface.

func (Name) Transform

func (n Name) Transform(mod, first NameTransformer, sep string) Name

Transform applies a transformation to the parts of Name n, returning a new Name. Transformer first is applied to the first part, with mod applied to all subsequent ones. The parts are then concatenated with the separator sep. For optimal efficiency, multiple NameTransformers should be Chained together before calling Transform.

func (Name) UpperCamelCase

func (n Name) UpperCamelCase() Name

UpperCamelCase converts Name n to upper camelcase, where each part is title-cased and concatenated with no separator.

Example
names := []string{
	"foo_bar",
	"myJSON",
	"PDFTemplate",
}

for _, n := range names {
	fmt.Println(Name(n).UpperCamelCase())
}
Output:

FooBar
MyJSON
PDFTemplate

func (Name) UpperDotNotation

func (n Name) UpperDotNotation() Name

UpperDotNotation converts Name n to upper dot notation, where each part is title-cased and concatenated with periods.

Example
names := []string{
	"foo_bar",
	"myJSON",
	"PDFTemplate",
}

for _, n := range names {
	fmt.Println(Name(n).UpperDotNotation())
}
Output:

Foo.Bar
My.JSON
PDF.Template

func (Name) UpperSnakeCase

func (n Name) UpperSnakeCase() Name

UpperSnakeCase converts Name n to upper-snake-case, where each part is title-cased and concatenated with underscores.

Example
names := []string{
	"foo_bar",
	"myJSON",
	"PDFTemplate",
}

for _, n := range names {
	fmt.Println(Name(n).UpperSnakeCase())
}
Output:

Foo_Bar
My_JSON
PDF_Template

type NameTransformer

type NameTransformer func(string) string

NameTransformer is a function that mutates a string. Many of the methods in the standard strings package satisfy this signature.

func (NameTransformer) Chain

Chain combines the behavior of two Transformers into one. If multiple transformations need to be performed on a Name, this method should be used to reduce it to a single transformation before applying.

type Node

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

Node represents any member of the proto descriptor AST. Typically, the highest level Node is the Package.

type OneOf

type OneOf interface {
	Entity

	// Descriptor returns the underlying proto descriptor for this OneOf
	Descriptor() *descriptor.OneofDescriptorProto

	// Message returns the parent message for this OneOf.
	Message() Message

	// Fields returns all fields contained within this OneOf.
	Fields() []Field

	// IsSynthetic returns true if this is a proto3 synthetic oneof.
	// See: https://github.com/protocolbuffers/protobuf/blob/v3.17.0/docs/field_presence.md
	IsSynthetic() bool
	// contains filtered or unexported methods
}

OneOf describes a OneOf block within a Message. OneOfs behave like C++ unions, where only one of the contained fields will exist on the Message.

type Package

type Package interface {
	Node

	// The name of the proto package.
	ProtoName() Name

	// All the files loaded for this Package
	Files() []File
	// contains filtered or unexported methods
}

Package is a container that encapsulates all the files under a single package namespace.

type ParamMutator

type ParamMutator func(p Parameters)

ParamMutator is a method that modifies Parameters p in-place. These are typically applied before code generation begins, and configurable via the MutateParams InitOption.

type Parameters

type Parameters map[string]string

Parameters provides a convenience for accessing and modifying the parameters passed into the protoc-gen-star plugin.

func ParseParameters

func ParseParameters(p string) (params Parameters)

ParseParameters converts the raw params string provided by protoc into a representative mapping.

func (Parameters) Bool

func (p Parameters) Bool(name string) (bool, error)

Bool returns the parameter with name, returning false if it is not set. An error is returned if the value cannot be parsed as a boolean. Empty values are considered true.

func (Parameters) BoolDefault

func (p Parameters) BoolDefault(name string, def bool) (bool, error)

BoolDefault returns the parameter with name, or if it is unset, returns the def default value. An error is returned if the value cannot be parsed as a boolean. Empty values are considered true.

func (Parameters) Clone

func (p Parameters) Clone() Parameters

Clone creates an independent copy of Parameters p.

func (Parameters) Duration

func (p Parameters) Duration(name string) (time.Duration, error)

Duration returns the parameter with name, returning zero if it is not set. An error is returned if the value cannot be parsed as a time.Duration.

func (Parameters) DurationDefault

func (p Parameters) DurationDefault(name string, def time.Duration) (time.Duration, error)

DurationDefault returns the parameter with name, or if it is unset, returns the def default value. An error is returned if the value cannot be parsed as a time.Duration.

func (Parameters) Float

func (p Parameters) Float(name string) (float64, error)

Float returns the parameter with name, returning zero if it is not set. An error is returned if the value cannot be parsed as a float64

func (Parameters) FloatDefault

func (p Parameters) FloatDefault(name string, def float64) (float64, error)

FloatDefault returns the parameter with name, or if it is unset, returns the def default value. An error is returned if the value cannot be parsed as a float64.

func (Parameters) Int

func (p Parameters) Int(name string) (int, error)

Int returns the parameter with name, returning zero if it is not set. An error is returned if the value cannot be parsed as an int.

func (Parameters) IntDefault

func (p Parameters) IntDefault(name string, def int) (int, error)

IntDefault returns the parameter with name, or if it is unset, returns the def default value. An error is returned if the value cannot be parsed as an int.

func (Parameters) OutputPath

func (p Parameters) OutputPath() string

OutputPath returns the protoc-gen-star special parameter. If not set in the execution of protoc, "." is returned, indicating that output is relative to the (unknown) output location for sub-plugins or the directory where protoc is executed for a Module. Setting "output_path" during the protoc execution ensures that Modules can know absolutely where to generate code.

func (Parameters) SetBool

func (p Parameters) SetBool(name string, b bool)

SetBool sets the parameter name to b.

func (Parameters) SetDuration

func (p Parameters) SetDuration(name string, d time.Duration)

SetDuration sets the parameter name to d.

func (Parameters) SetFloat

func (p Parameters) SetFloat(name string, f float64)

SetFloat sets the parameter name to f.

func (Parameters) SetInt

func (p Parameters) SetInt(name string, i int)

SetInt sets the parameter name to i.

func (Parameters) SetOutputPath

func (p Parameters) SetOutputPath(path string)

SetOutputPath sets the protoc-gen-star OutputPath parameter. This is useful for overriding the behavior of the ImportPath at runtime.

func (Parameters) SetStr

func (p Parameters) SetStr(name string, s string)

SetStr sets the parameter name to s.

func (Parameters) SetUint

func (p Parameters) SetUint(name string, ui uint)

SetUint sets the parameter name to ui.

func (Parameters) Str

func (p Parameters) Str(name string) string

Str returns the parameter with name, returning an empty string if it is not set.

func (Parameters) StrDefault

func (p Parameters) StrDefault(name string, def string) string

StrDefault returns the parameter with name, or if it is unset, returns the def default value.

func (Parameters) String

func (p Parameters) String() string

String satisfies the string.Stringer interface. This method returns p in the format it is provided to the protoc execution. Output of this function is always stable; parameters are sorted before the string is emitted.

func (Parameters) Uint

func (p Parameters) Uint(name string) (uint, error)

Uint returns the parameter with name, returning zero if it is not set. An error is returned if the value cannot be parsed as a base-10 uint.

func (Parameters) UintDefault

func (p Parameters) UintDefault(name string, def uint) (uint, error)

UintDefault returns the parameter with name, or if it is unset, returns the def default value. An error is returned if the value cannot be parsed as a base-10 uint.

type ParentEntity

type ParentEntity interface {
	Entity

	// Messages returns the top-level messages from this entity. Nested
	// messages are not included.
	Messages() []Message

	// AllMessages returns all the top-level and nested messages from this Entity.
	AllMessages() []Message

	// MapEntries returns the MapEntry message types contained within this
	// Entity. These messages are not returned by the Messages or AllMessages
	// methods. Map Entry messages are typically not exposed to the end user.
	MapEntries() []Message

	// Enums returns the top-level enums from this entity. Nested enums
	// are not included.
	Enums() []Enum

	// AllEnums returns all top-level and nested enums from this entity.
	AllEnums() []Enum

	// DefinedExtensions returns all Extensions defined on this entity.
	DefinedExtensions() []Extension
	// contains filtered or unexported methods
}

A ParentEntity is any Entity type that can contain messages and/or enums. File and Message types implement ParentEntity.

type PostProcessor

type PostProcessor interface {
	// Match returns true if the PostProcess should be applied to the Artifact.
	// Process is called immediately after Match for the same Artifact.
	Match(a Artifact) bool

	// Process receives the rendered artifact and returns the processed bytes or
	// an error if something goes wrong.
	Process(in []byte) ([]byte, error)
}

A PostProcessor modifies the output of an Artifact before final rendering.

type ProtoLabel

ProtoLabel wraps the FieldDescriptorProto_Label enum for better readability. It is a 1-to-1 conversion.

func (ProtoLabel) Proto

Proto returns the FieldDescriptorProto_Label for this ProtoLabel. This method is exclusively used to improve readability without having to switch the types.

func (ProtoLabel) ProtoPtr

ProtoPtr returns a pointer to the FieldDescriptorProto_Label for this ProtoLabel.

func (ProtoLabel) String

func (pl ProtoLabel) String() string

String returns a string representation of the proto label.

type ProtoType

ProtoType wraps the FieldDescriptorProto_Type enum for better readability and utility methods. It is a 1-to-1 conversion.

func (ProtoType) IsInt

func (pt ProtoType) IsInt() bool

IsInt returns true if pt maps to an integer-like type. While EnumT types in Go are aliases of uint32, to correctly accommodate other languages with non-numeric enums, IsInt returns false for EnumT.

func (ProtoType) IsNumeric

func (pt ProtoType) IsNumeric() bool

IsNumeric returns true if pt maps to a numeric type. While EnumT types in Go are aliases of uint32, to correctly accommodate other languages with non-numeric enums, IsNumeric returns false for EnumT.

func (ProtoType) Proto

Proto returns the FieldDescriptorProto_Type for this ProtoType. This method is exclusively used to improve readability without having to switch the types.

func (ProtoType) ProtoPtr

ProtoPtr returns a pointer to the FieldDescriptorProto_Type for this ProtoType.

func (ProtoType) String

func (pt ProtoType) String() string

String returns a string representation of the proto type.

type Service

type Service interface {
	Entity

	// Descriptor returns the underlying proto descriptor for this service
	Descriptor() *descriptor.ServiceDescriptorProto

	// Methods returns each rpc method exposed by this service
	Methods() []Method
	// contains filtered or unexported methods
}

Service describes a proto service definition (typically, gRPC)

type SourceCodeInfo

type SourceCodeInfo interface {
	// Location returns the SourceCodeInfo_Location from the file descriptor.
	Location() *descriptor.SourceCodeInfo_Location

	// LeadingComments returns any comment immediately preceding the entity,
	// without any whitespace between it and the comment.
	LeadingComments() string

	// LeadingDetachedComments returns each comment block or line above the
	// entity but separated by whitespace.
	LeadingDetachedComments() []string

	// TrailingComments returns any comment immediately following the entity,
	// without any whitespace between it and the comment. If the comment would be
	// a leading comment for another entity, it won't be considered a trailing
	// comment.
	TrailingComments() string
}

SourceCodeInfo represents data about an entity from the source. Currently this only contains information about comments protoc associates with entities.

All comments have their // or /* */ stripped by protoc. See the SourceCodeInfo documentation for more details about how comments are associated with entities.

type Syntax

type Syntax string

Syntax describes the proto syntax used to encode the proto file

const (
	// Proto2 syntax permits the use of "optional" and "required" prefixes on
	// fields. Most of the field types in the generated go structs are pointers.
	// See: https://developers.google.com/protocol-buffers/docs/proto
	Proto2 Syntax = ""

	// Proto3 syntax permits the use of "optional" field presence. Non optional fields default to the zero
	// 	value of that particular type if not defined.
	// Most of the field types in the generated go structs are value types.
	// See: https://github.com/protocolbuffers/protobuf/blob/v3.17.0/docs/field_presence.md#presence-in-proto3-apis
	Proto3 Syntax = "proto3"
)

func (Syntax) String

func (s Syntax) String() string

String returns a string representation of the syntax.

func (Syntax) SupportsRequiredPrefix

func (s Syntax) SupportsRequiredPrefix() bool

SupportsRequiredPrefix returns true if s supports "optional" and "required" identifiers on message fields. Only Proto2 syntax supports this feature.

type Template

type Template interface {
	Execute(w io.Writer, data interface{}) error
}

A Template to use for rendering artifacts. Either text/template or html/template Template types satisfy this interface.

type TemplateArtifact

type TemplateArtifact struct {
	// The Template to use for rendering. Either text/template or html/template
	// Template types are supported.
	Template Template

	// Data is arbitrary data passed into the Template's Execute method.
	Data interface{}
}

TemplateArtifact contains the shared logic used by Artifacts that render their contents using a Template.

type Visitor

type Visitor interface {
	VisitPackage(Package) (v Visitor, err error)
	VisitFile(File) (v Visitor, err error)
	VisitMessage(Message) (v Visitor, err error)
	VisitEnum(Enum) (v Visitor, err error)
	VisitEnumValue(EnumValue) (v Visitor, err error)
	VisitField(Field) (v Visitor, err error)
	VisitExtension(Extension) (v Visitor, err error)
	VisitOneOf(OneOf) (v Visitor, err error)
	VisitService(Service) (v Visitor, err error)
	VisitMethod(Method) (v Visitor, err error)
}

A Visitor exposes methods to walk an AST Node and its children in a depth- first manner. If the returned Visitor v is non-nil, it will be used to descend into the children of the current node. If nil, those children will be skipped. Any error returned will immediately halt execution.

func NilVisitor

func NilVisitor() Visitor

NilVisitor returns a Visitor that always responds with (nil, nil) for all methods. This is useful as an anonymous embedded struct to satisfy the Visitor interface for implementations that don't require visiting every Node type. NilVisitor should be used over PassThroughVisitor if short-circuiting behavior is desired.

Example
package main

import (
	"fmt"

	"google.golang.org/protobuf/proto"
	descriptor "google.golang.org/protobuf/types/descriptorpb"
)

type enumPrinter struct {
	Visitor
}

func EnumPrinter() Visitor { return enumPrinter{NilVisitor()} }

func (p enumPrinter) VisitMessage(m Message) (Visitor, error) { return p, nil }

func (p enumPrinter) VisitEnum(e Enum) (Visitor, error) {
	fmt.Println(e.Name())
	return nil, nil
}

func main() {
	n := enumNode()
	p := EnumPrinter()

	if err := Walk(p, n); err != nil {
		panic(err)
	}

}

func enumNode() Node {
	// simulating the following proto file:
	//
	// syntax="proto3";
	//
	// package fizz;
	//
	// message Gadget {
	//
	//   enum Bar {
	//     // ...
	//   }
	//
	//   message Gizmo {
	//     enum Foo {
	//       // ...
	//     }
	//   }
	// }

	sm := &msg{}
	sm.addEnum(&enum{desc: &descriptor.EnumDescriptorProto{Name: proto.String("Foo")}})

	m := &msg{}
	m.addMessage(sm)
	m.addEnum(&enum{desc: &descriptor.EnumDescriptorProto{Name: proto.String("Bar")}})

	return m
}
Output:

Bar
Foo

func PassThroughVisitor

func PassThroughVisitor(v Visitor) Visitor

PassThroughVisitor returns a Visitor that always responds with (v, nil) for all methods. This is useful as an anonymous embedded struct to satisfy the Visitor interface for implementations that need access to deep child nodes (eg, EnumValue, Field, Method) without implementing each method of the interface explicitly.

Example
package main

import (
	"fmt"

	"google.golang.org/protobuf/proto"
	descriptor "google.golang.org/protobuf/types/descriptorpb"
)

type fieldPrinter struct {
	Visitor
}

func FieldPrinter() Visitor {
	p := &fieldPrinter{}
	p.Visitor = PassThroughVisitor(p)
	return p
}

func (p fieldPrinter) VisitField(f Field) (Visitor, error) {
	fmt.Println(f.Name())
	return nil, nil
}

func main() {
	n := fieldNode()
	p := FieldPrinter()

	if err := Walk(p, n); err != nil {
		panic(err)
	}

}

func fieldNode() Node {
	// simulating the following proto file:
	//
	// syntax="proto3";
	//
	// package fizz;
	//
	// message Gadget {
	//   string Bar = 1;
	//
	//   message Gizmo {
	//     int Foo = 1;
	//   }
	// }

	sm := &msg{}
	sm.addField(&field{desc: &descriptor.FieldDescriptorProto{Name: proto.String("Foo")}})

	m := &msg{}
	m.addMessage(sm)
	m.addField(&field{desc: &descriptor.FieldDescriptorProto{Name: proto.String("Bar")}})

	f := &file{}
	f.addMessage(m)

	p := &pkg{}
	p.addFile(f)

	return p
}
Output:

Foo
Bar

type WellKnownType

type WellKnownType Name

WellKnownType (WKT) encapsulates the Name of a Message from the `google.protobuf` package. Most official protoc plugins special case code generation on these messages.

const (
	// UnknownWKT indicates that the type is not a known WKT. This value may be
	// returned erroneously mapping a Name to a WellKnownType or if a WKT is
	// added to the `google.protobuf` package but this library is outdated.
	UnknownWKT WellKnownType = "Unknown"

	AnyWKT         WellKnownType = "Any"
	DurationWKT    WellKnownType = "Duration"
	EmptyWKT       WellKnownType = "Empty"
	StructWKT      WellKnownType = "Struct"
	TimestampWKT   WellKnownType = "Timestamp"
	ValueWKT       WellKnownType = "Value"
	ListValueWKT   WellKnownType = "ListValue"
	DoubleValueWKT WellKnownType = "DoubleValue"
	FloatValueWKT  WellKnownType = "FloatValue"
	Int64ValueWKT  WellKnownType = "Int64Value"
	UInt64ValueWKT WellKnownType = "UInt64Value"
	Int32ValueWKT  WellKnownType = "Int32Value"
	UInt32ValueWKT WellKnownType = "UInt32Value"
	BoolValueWKT   WellKnownType = "BoolValue"
	StringValueWKT WellKnownType = "StringValue"
	BytesValueWKT  WellKnownType = "BytesValue"
)

1-to-1 mapping of the WKT names to WellKnownTypes.

func LookupWKT

func LookupWKT(n Name) WellKnownType

LookupWKT returns the WellKnownType related to the provided Name. If the name is not recognized, UnknownWKT is returned.

func (WellKnownType) Name

func (wkt WellKnownType) Name() Name

Name converts the WellKnownType to a Name. This is a convenience method.

func (WellKnownType) Valid

func (wkt WellKnownType) Valid() bool

Valid returns true if the WellKnownType is recognized by this library.

Directories

Path Synopsis
lang
go
Package pgsgo contains Go-specific helpers for use with PG* based protoc-plugins
Package pgsgo contains Go-specific helpers for use with PG* based protoc-plugins
protoc-gen-debug emits the raw encoded CodeGeneratorRequest from a protoc execution to a file.
protoc-gen-debug emits the raw encoded CodeGeneratorRequest from a protoc execution to a file.

Jump to

Keyboard shortcuts

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