protokit

package module
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Feb 15, 2022 License: MIT Imports: 11 Imported by: 108

README

protokit

CI codecov GoDoc Go Report Card

A starter kit for building protoc-plugins. Rather than write your own, you can just use an existing one.

See the examples directory for uh...examples.

Getting Started

package main

import (
    "github.com/golang/protobuf/proto"
    "github.com/golang/protobuf/protoc-gen-go/plugin"
    "github.com/pseudomuto/protokit"
    _ "google.golang.org/genproto/googleapis/api/annotations" // Support (google.api.http) option (from google/api/annotations.proto).

    "log"
)

func main() {
    // all the heavy lifting done for you!
    if err := protokit.RunPlugin(new(plugin)); err != nil {
        log.Fatal(err)
    }
}

// plugin is an implementation of protokit.Plugin
type plugin struct{}

func (p *plugin) Generate(in *plugin_go.CodeGeneratorRequest) (*plugin_go.CodeGeneratorResponse, error) {
    descriptors := protokit.ParseCodeGenRequest(req)

    resp := new(plugin_go.CodeGeneratorResponse)

    for _, d := range descriptors {
        // TODO: YOUR WORK HERE
        fileName := // generate a file name based on d.GetName()
        content := // generate content for the output file

        resp.File = append(resp.File, &plugin_go.CodeGeneratorResponse_File{
            Name:    proto.String(fileName),
            Content: proto.String(content),
        })
    }

    return resp, nil
}

Then invoke your plugin via protoc. For example (assuming your app is called thingy):

protoc --plugin=protoc-gen-thingy=./thingy -I. --thingy_out=. rpc/*.proto

Documentation

Overview

Package protokit is a library that makes it easy to create your own protoc plugins. It has excellent test coverage, and saves you so much time!

There are two main things this library provides; a parser for parsing protobuf files into some well-defined structs, and an abstraction to make it simple to write your own protoc plugins.

Getting Started

For a quick view of how to get started, see https://godoc.org/github.com/pseudomuto/protokit#example-RunPlugin

If you want see/try a working example, check out the examples in https://github.com/pseudomuto/protokit/tree/master/examples.

Index

Examples

Constants

View Source
const Version = "0.2.1"

Version describes the current version of protokit being used

Variables

This section is empty.

Functions

func ContextWithDescriptor

func ContextWithDescriptor(ctx context.Context, d *Descriptor) context.Context

ContextWithDescriptor returns a new context with the specified `Descriptor`

func ContextWithEnumDescriptor

func ContextWithEnumDescriptor(ctx context.Context, d *EnumDescriptor) context.Context

ContextWithEnumDescriptor returns a new context with the specified `EnumDescriptor`

func ContextWithFileDescriptor

func ContextWithFileDescriptor(ctx context.Context, fd *FileDescriptor) context.Context

ContextWithFileDescriptor returns a new context with the attached `FileDescriptor`

func ContextWithServiceDescriptor

func ContextWithServiceDescriptor(ctx context.Context, service *ServiceDescriptor) context.Context

ContextWithServiceDescriptor returns a new context with `service`

func RunPlugin

func RunPlugin(p Plugin) error

RunPlugin runs the supplied plugin by reading input from stdin and generating output to stdout.

Example

An example of running a custom plugin. This would be in your main.go file.

package main

import (
	"github.com/golang/protobuf/proto"
	"github.com/golang/protobuf/protoc-gen-go/plugin"
	"github.com/pseudomuto/protokit"

	"log"
)

type plugin struct{}

func (p *plugin) Generate(r *plugin_go.CodeGeneratorRequest) (*plugin_go.CodeGeneratorResponse, error) {
	descriptors := protokit.ParseCodeGenRequest(r)
	resp := new(plugin_go.CodeGeneratorResponse)

	for _, desc := range descriptors {
		resp.File = append(resp.File, &plugin_go.CodeGeneratorResponse_File{
			Name:    proto.String(desc.GetName() + ".out"),
			Content: proto.String("Some relevant output"),
		})
	}

	return resp, nil
}

// An example of running a custom plugin. This would be in your main.go file.
func main() {
	// in func main() {}
	if err := protokit.RunPlugin(new(plugin)); err != nil {
		log.Fatal(err)
	}
}
Output:

func RunPluginWithIO

func RunPluginWithIO(p Plugin, r io.Reader, w io.Writer) error

RunPluginWithIO runs the supplied plugin using the supplied reader and writer for IO.

Types

type Comment

type Comment struct {
	Leading  string
	Trailing string
	Detached []string
}

A Comment describes the leading, trailing, and detached comments for a proto object. See `SourceCodeInfo_Location` in descriptor.proto for details on what those terms mean

func (*Comment) GetDetached

func (c *Comment) GetDetached() []string

GetDetached returns the detached leading comments

func (*Comment) GetLeading

func (c *Comment) GetLeading() string

GetLeading returns the leading comments

func (*Comment) GetTrailing

func (c *Comment) GetTrailing() string

GetTrailing returns the leading comments

func (*Comment) String

func (c *Comment) String() string

String returns the leading and trailing comments joined by 2 line breaks (`\n\n`). If either are empty, the line breaks are removed.

Example

Join the leading and trailing comments together

package main

import (
	"fmt"

	"github.com/pseudomuto/protokit"
)

func main() {
	c := &protokit.Comment{Leading: "Some leading comment", Trailing: "Some trailing comment"}
	fmt.Println(c.String())
}
Output:

Some leading comment

Some trailing comment

type Comments

type Comments map[string]*Comment

Comments is a map of source location paths to values.

func ParseComments

func ParseComments(fd *descriptor.FileDescriptorProto) Comments

ParseComments parses all comments within a proto file. The locations are encoded into the map by joining the paths with a "." character. E.g. `4.2.3.0`.

Leading/trailing spaces are trimmed for each comment type (leading, trailing, detached)

func (Comments) Get

func (c Comments) Get(path string) *Comment

type Descriptor

type Descriptor struct {
	*descriptor.DescriptorProto
	Parent     *Descriptor
	Comments   *Comment
	Enums      []*EnumDescriptor
	Extensions []*ExtensionDescriptor
	Fields     []*FieldDescriptor
	Messages   []*Descriptor
	// contains filtered or unexported fields
}

A Descriptor describes a message

func DescriptorFromContext

func DescriptorFromContext(ctx context.Context) (*Descriptor, bool)

DescriptorFromContext returns the associated `Descriptor` for the context and whether or not it was found

func (*Descriptor) GetComments

func (m *Descriptor) GetComments() *Comment

GetComments returns a description of the message

func (*Descriptor) GetEnum

func (m *Descriptor) GetEnum(name string) *EnumDescriptor

GetEnum returns the enum with the specified name. The name can be either simple, or fully qualified (returns `nil` if not found)

func (*Descriptor) GetEnums

func (m *Descriptor) GetEnums() []*EnumDescriptor

GetEnums returns the nested enumerations within the message

func (*Descriptor) GetExtensions

func (m *Descriptor) GetExtensions() []*ExtensionDescriptor

GetExtensions returns the message-level extensions defined by this message

func (*Descriptor) GetFile

func (c *Descriptor) GetFile() *FileDescriptor

GetFile returns the FileDescriptor that contains this object

func (*Descriptor) GetFullName

func (c *Descriptor) GetFullName() string

GetFullName returns the `LongName` prefixed with the package this object is in

func (*Descriptor) GetLongName

func (c *Descriptor) GetLongName() string

GetLongName returns the name prefixed with the dot-separated parent descriptor's name (if any)

func (*Descriptor) GetMessage

func (m *Descriptor) GetMessage(name string) *Descriptor

GetMessage returns the nested message with the specified name. The name can be simple or fully qualified (returns `nil` if not found)

func (*Descriptor) GetMessageField

func (m *Descriptor) GetMessageField(name string) *FieldDescriptor

GetMessageField returns the field with the specified name (returns `nil` if not found)

func (*Descriptor) GetMessageFields

func (m *Descriptor) GetMessageFields() []*FieldDescriptor

GetMessageFields returns the message fields

func (*Descriptor) GetMessages

func (m *Descriptor) GetMessages() []*Descriptor

GetMessages returns the nested messages within the message

func (*Descriptor) GetPackage

func (c *Descriptor) GetPackage() string

GetPackage returns the package this object is in

func (*Descriptor) GetParent

func (m *Descriptor) GetParent() *Descriptor

GetParent returns the parent descriptor (if any) that defines this descriptor

func (*Descriptor) IsProto3

func (c *Descriptor) IsProto3() bool

IsProto3 returns whether or not this is a proto3 object

type EnumDescriptor

type EnumDescriptor struct {
	*descriptor.EnumDescriptorProto
	Parent   *Descriptor
	Values   []*EnumValueDescriptor
	Comments *Comment
	// contains filtered or unexported fields
}

An EnumDescriptor describe an enum type

func EnumDescriptorFromContext

func EnumDescriptorFromContext(ctx context.Context) (*EnumDescriptor, bool)

EnumDescriptorFromContext returns the associated `EnumDescriptor` for the context and whether or not it was found

func (*EnumDescriptor) GetComments

func (e *EnumDescriptor) GetComments() *Comment

GetComments returns a description of this enum

func (*EnumDescriptor) GetFile

func (c *EnumDescriptor) GetFile() *FileDescriptor

GetFile returns the FileDescriptor that contains this object

func (*EnumDescriptor) GetFullName

func (c *EnumDescriptor) GetFullName() string

GetFullName returns the `LongName` prefixed with the package this object is in

func (*EnumDescriptor) GetLongName

func (c *EnumDescriptor) GetLongName() string

GetLongName returns the name prefixed with the dot-separated parent descriptor's name (if any)

func (*EnumDescriptor) GetNamedValue

func (e *EnumDescriptor) GetNamedValue(name string) *EnumValueDescriptor

GetNamedValue returns the value with the specified name (returns `nil` if not found)

func (*EnumDescriptor) GetPackage

func (c *EnumDescriptor) GetPackage() string

GetPackage returns the package this object is in

func (*EnumDescriptor) GetParent

func (e *EnumDescriptor) GetParent() *Descriptor

GetParent returns the parent message (if any) that contains this enum

func (*EnumDescriptor) GetValues

func (e *EnumDescriptor) GetValues() []*EnumValueDescriptor

GetValues returns the available values for this enum

func (*EnumDescriptor) IsProto3

func (c *EnumDescriptor) IsProto3() bool

IsProto3 returns whether or not this is a proto3 object

type EnumValueDescriptor

type EnumValueDescriptor struct {
	*descriptor.EnumValueDescriptorProto
	Enum     *EnumDescriptor
	Comments *Comment
	// contains filtered or unexported fields
}

An EnumValueDescriptor describes an enum value

func (*EnumValueDescriptor) GetComments

func (v *EnumValueDescriptor) GetComments() *Comment

GetComments returns a description of the value

func (*EnumValueDescriptor) GetEnum

func (v *EnumValueDescriptor) GetEnum() *EnumDescriptor

GetEnum returns the parent enumeration that contains this value

func (*EnumValueDescriptor) GetFile

func (c *EnumValueDescriptor) GetFile() *FileDescriptor

GetFile returns the FileDescriptor that contains this object

func (*EnumValueDescriptor) GetFullName

func (c *EnumValueDescriptor) GetFullName() string

GetFullName returns the `LongName` prefixed with the package this object is in

func (*EnumValueDescriptor) GetLongName

func (c *EnumValueDescriptor) GetLongName() string

GetLongName returns the name prefixed with the dot-separated parent descriptor's name (if any)

func (*EnumValueDescriptor) GetPackage

func (c *EnumValueDescriptor) GetPackage() string

GetPackage returns the package this object is in

func (*EnumValueDescriptor) IsProto3

func (c *EnumValueDescriptor) IsProto3() bool

IsProto3 returns whether or not this is a proto3 object

type ExtensionDescriptor

type ExtensionDescriptor struct {
	*descriptor.FieldDescriptorProto
	Parent   *Descriptor
	Comments *Comment
	// contains filtered or unexported fields
}

An ExtensionDescriptor describes a protobuf extension. If it's a top-level extension it's parent will be `nil`

func (*ExtensionDescriptor) GetComments

func (e *ExtensionDescriptor) GetComments() *Comment

GetComments returns a description of the extension

func (*ExtensionDescriptor) GetFile

func (c *ExtensionDescriptor) GetFile() *FileDescriptor

GetFile returns the FileDescriptor that contains this object

func (*ExtensionDescriptor) GetFullName

func (c *ExtensionDescriptor) GetFullName() string

GetFullName returns the `LongName` prefixed with the package this object is in

func (*ExtensionDescriptor) GetLongName

func (c *ExtensionDescriptor) GetLongName() string

GetLongName returns the name prefixed with the dot-separated parent descriptor's name (if any)

func (*ExtensionDescriptor) GetPackage

func (c *ExtensionDescriptor) GetPackage() string

GetPackage returns the package this object is in

func (*ExtensionDescriptor) GetParent

func (e *ExtensionDescriptor) GetParent() *Descriptor

GetParent returns the descriptor that defined this extension (if any)

func (*ExtensionDescriptor) IsProto3

func (c *ExtensionDescriptor) IsProto3() bool

IsProto3 returns whether or not this is a proto3 object

type FieldDescriptor

type FieldDescriptor struct {
	*descriptor.FieldDescriptorProto
	Comments *Comment
	Message  *Descriptor
	// contains filtered or unexported fields
}

A FieldDescriptor describes a message field

func (*FieldDescriptor) GetComments

func (mf *FieldDescriptor) GetComments() *Comment

GetComments returns a description of the field

func (*FieldDescriptor) GetFile

func (c *FieldDescriptor) GetFile() *FileDescriptor

GetFile returns the FileDescriptor that contains this object

func (*FieldDescriptor) GetFullName

func (c *FieldDescriptor) GetFullName() string

GetFullName returns the `LongName` prefixed with the package this object is in

func (*FieldDescriptor) GetLongName

func (c *FieldDescriptor) GetLongName() string

GetLongName returns the name prefixed with the dot-separated parent descriptor's name (if any)

func (*FieldDescriptor) GetMessage

func (mf *FieldDescriptor) GetMessage() *Descriptor

GetMessage returns the descriptor that defines this field

func (*FieldDescriptor) GetPackage

func (c *FieldDescriptor) GetPackage() string

GetPackage returns the package this object is in

func (*FieldDescriptor) IsProto3

func (c *FieldDescriptor) IsProto3() bool

IsProto3 returns whether or not this is a proto3 object

type FileDescriptor

type FileDescriptor struct {
	*descriptor.FileDescriptorProto

	Comments        *Comment // Deprecated: see PackageComments
	PackageComments *Comment
	SyntaxComments  *Comment

	Enums      []*EnumDescriptor
	Extensions []*ExtensionDescriptor
	Imports    []*ImportedDescriptor
	Messages   []*Descriptor
	Services   []*ServiceDescriptor

	OptionExtensions map[string]interface{}
	// contains filtered or unexported fields
}

A FileDescriptor describes a single proto file with all of its messages, enums, services, etc.

func FileDescriptorFromContext

func FileDescriptorFromContext(ctx context.Context) (*FileDescriptor, bool)

FileDescriptorFromContext returns the `FileDescriptor` from the context and whether or not the key was found.

func ParseCodeGenRequest

func ParseCodeGenRequest(req *plugin_go.CodeGeneratorRequest) []*FileDescriptor

ParseCodeGenRequest parses the given request into `FileDescriptor` objects. Only the `req.FilesToGenerate` will be returned.

For example, given the following invocation, only booking.proto will be returned even if it imports other protos:

protoc --plugin=protoc-gen-test=./test -I. protos/booking.proto

func (*FileDescriptor) GetComments deprecated

func (f *FileDescriptor) GetComments() *Comment

GetComments returns the file's package comments.

Deprecated: please see GetPackageComments

func (*FileDescriptor) GetEnum

func (f *FileDescriptor) GetEnum(name string) *EnumDescriptor

GetEnum returns the enumeration with the specified name (returns `nil` if not found)

func (*FileDescriptor) GetEnums

func (f *FileDescriptor) GetEnums() []*EnumDescriptor

GetEnums returns the top-level enumerations defined in this file

func (*FileDescriptor) GetExtensions

func (f *FileDescriptor) GetExtensions() []*ExtensionDescriptor

GetExtensions returns the top-level (file) extensions defined in this file

func (*FileDescriptor) GetImports

func (f *FileDescriptor) GetImports() []*ImportedDescriptor

GetImports returns the proto files imported by this file

func (*FileDescriptor) GetMessage

func (f *FileDescriptor) GetMessage(name string) *Descriptor

GetMessage returns the message with the specified name (returns `nil` if not found)

func (*FileDescriptor) GetMessages

func (f *FileDescriptor) GetMessages() []*Descriptor

GetMessages returns the top-level messages defined in this file

func (*FileDescriptor) GetPackageComments

func (f *FileDescriptor) GetPackageComments() *Comment

GetPackageComments returns the file's package comments

func (*FileDescriptor) GetService

func (f *FileDescriptor) GetService(name string) *ServiceDescriptor

GetService returns the service with the specified name (returns `nil` if not found)

func (*FileDescriptor) GetServices

func (f *FileDescriptor) GetServices() []*ServiceDescriptor

GetServices returns the services defined in this file

func (*FileDescriptor) GetSyntaxComments

func (f *FileDescriptor) GetSyntaxComments() *Comment

GetSyntaxComments returns the file's syntax comments

func (*FileDescriptor) IsProto3

func (f *FileDescriptor) IsProto3() bool

IsProto3 returns whether or not this file is a proto3 file

type ImportedDescriptor

type ImportedDescriptor struct {
	// contains filtered or unexported fields
}

An ImportedDescriptor describes a type that was imported by a FileDescriptor.

func (*ImportedDescriptor) GetFile

func (c *ImportedDescriptor) GetFile() *FileDescriptor

GetFile returns the FileDescriptor that contains this object

func (*ImportedDescriptor) GetFullName

func (c *ImportedDescriptor) GetFullName() string

GetFullName returns the `LongName` prefixed with the package this object is in

func (*ImportedDescriptor) GetLongName

func (c *ImportedDescriptor) GetLongName() string

GetLongName returns the name prefixed with the dot-separated parent descriptor's name (if any)

func (*ImportedDescriptor) GetPackage

func (c *ImportedDescriptor) GetPackage() string

GetPackage returns the package this object is in

func (*ImportedDescriptor) IsProto3

func (c *ImportedDescriptor) IsProto3() bool

IsProto3 returns whether or not this is a proto3 object

type MethodDescriptor

type MethodDescriptor struct {
	*descriptor.MethodDescriptorProto
	Comments *Comment
	Service  *ServiceDescriptor
	// contains filtered or unexported fields
}

A MethodDescriptor describes a method in a service

func (*MethodDescriptor) GetComments

func (m *MethodDescriptor) GetComments() *Comment

GetComments returns a description of the method

func (*MethodDescriptor) GetFile

func (c *MethodDescriptor) GetFile() *FileDescriptor

GetFile returns the FileDescriptor that contains this object

func (*MethodDescriptor) GetFullName

func (c *MethodDescriptor) GetFullName() string

GetFullName returns the `LongName` prefixed with the package this object is in

func (*MethodDescriptor) GetLongName

func (c *MethodDescriptor) GetLongName() string

GetLongName returns the name prefixed with the dot-separated parent descriptor's name (if any)

func (*MethodDescriptor) GetPackage

func (c *MethodDescriptor) GetPackage() string

GetPackage returns the package this object is in

func (*MethodDescriptor) GetService

func (m *MethodDescriptor) GetService() *ServiceDescriptor

GetService returns the service descriptor that defines this method

func (*MethodDescriptor) IsProto3

func (c *MethodDescriptor) IsProto3() bool

IsProto3 returns whether or not this is a proto3 object

type Plugin

type Plugin interface {
	Generate(req *plugin_go.CodeGeneratorRequest) (*plugin_go.CodeGeneratorResponse, error)
}

Plugin describes an interface for running protoc code generator plugins

type ServiceDescriptor

type ServiceDescriptor struct {
	*descriptor.ServiceDescriptorProto
	Comments *Comment
	Methods  []*MethodDescriptor
	// contains filtered or unexported fields
}

A ServiceDescriptor describes a service

func ServiceDescriptorFromContext

func ServiceDescriptorFromContext(ctx context.Context) (*ServiceDescriptor, bool)

ServiceDescriptorFromContext returns the `Service` from the context and whether or not the key was found.

func (*ServiceDescriptor) GetComments

func (s *ServiceDescriptor) GetComments() *Comment

GetComments returns a description of the service

func (*ServiceDescriptor) GetFile

func (c *ServiceDescriptor) GetFile() *FileDescriptor

GetFile returns the FileDescriptor that contains this object

func (*ServiceDescriptor) GetFullName

func (c *ServiceDescriptor) GetFullName() string

GetFullName returns the `LongName` prefixed with the package this object is in

func (*ServiceDescriptor) GetLongName

func (c *ServiceDescriptor) GetLongName() string

GetLongName returns the name prefixed with the dot-separated parent descriptor's name (if any)

func (*ServiceDescriptor) GetMethods

func (s *ServiceDescriptor) GetMethods() []*MethodDescriptor

GetMethods returns the methods for the service

func (*ServiceDescriptor) GetNamedMethod

func (s *ServiceDescriptor) GetNamedMethod(name string) *MethodDescriptor

GetNamedMethod returns the method with the specified name (if found)

func (*ServiceDescriptor) GetPackage

func (c *ServiceDescriptor) GetPackage() string

GetPackage returns the package this object is in

func (*ServiceDescriptor) IsProto3

func (c *ServiceDescriptor) IsProto3() bool

IsProto3 returns whether or not this is a proto3 object

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

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