wrapgen

command module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Sep 30, 2017 License: Apache-2.0 Imports: 9 Imported by: 0

README

wrapgen - A code generator for Google-golang interfaces

This project is a fork/derivative of https://github.com/golang/mock which contains a tool called mockgen that can consume any valid Google-golang interface and generate a mock version of it. wrapgen extends that concept to allow for any custom code generation based on interfaces. Given a valid template, using the text/template format, and a valid Google-golang package wrapgen will parse out all interfaces in the package and inject their content into your template.

Usage

go get github.com/kevinconway/wrapgen
go get golang.org/x/tools/cmd/goimports

go run wrapgen.go \
  -t "${GOPATH}/src/github.com/kevinconway/wrapgen/basetemplate.txt" \
  -p "github.com/kevinconway/wrapgen/api" \
  | ${GOPATH}/bin/goimports > wrappers.go

All output are written to stdout. Depending on the template, code may not be rendered with the correct format or with extraneous import statements. Because of this, you very likely will need to run the output through a formatter like gofmt or goimports before the output will build.

Template paths can either be a path on the filesystem or an HTTP(S) location.

Writing Templates

This project comes with a few templates in the root of the repository. The basicdecorator.txt template will create a generic shell that wraps every exposed method of the interfaces found in a package and the gomock.txt template will generate an equivalent ouput to the mockgen command from the gomock project.

In order to make templates that conflict the least amount with actual Google-golang code, the default template delimiters are set to #! and !#. However, these values are only the defaults and can be overridden by using the --rightdelim and --leftdelim flags to match the delimiters in your own template.

The basicdecorator.txt template is provided as a starting point for creating interface decorators. For example, you can wrap your interface in debug logging during development by adding some content like the following:

package wrappers

import (
	"#! .Source !#"
	#! range .Package.Imports !##! .Package !# "#! .Path !#"
	#! end !#
)

#! $pkgName := .Package.Name !##! range .Package.Interfaces !#type Wraps#! .Name !# struct {
	wrapped #! $pkgName !#.#! .Name !#
}
#! $ifaceRef := . !##! range .Methods !#func (w *Wraps#! $ifaceRef.Name !#) #! .Name !#(#! $methodRef := . !##! range $x, $e := .In !##! $e.Name !# #! $e.Type !##! if ne $x (add (len $methodRef.In) -1)!#, #! end !##! end !#) (#! $methodRef := . !##! range $x, $e := .Out !##! $e.Type !##! if ne $x (add (len $methodRef.Out) -1)!#, #! end !##! end !#) {

  var start = time.Now()
  log.Println("starting func #! .Name !#")
  defer func(start time.Time){
      log.Printf("ended func #! .Name !# after %f seconds \n", time.Since(start).Seconds())
  }(start)

	#! if ne (len $methodRef.Out) 0!#return #! end !#w.#! .Name !#(#! $methodRef := . !##! range $x, $e := .In !##! $e.Name !##! if ne $x (add (len $methodRef.In) -1)!#, #! end !##! end !#)
}
#! end !#
#! end !#

That template, given an interface like:

package sourcepkg

type Doer interface {
  Do(r *http.Request) (*http.Response, error)
}

will result in code like:

package wrappers

import (
  "time"
  "net/http"
  "sourcepkg"
)

type DoerWrapper struct {
  wrapped sourcepkg.Doer
}

func (w *DoerWrapper) Do(r *http.Request) (*http.Response, error) {
  var start = time.Now()
  log.Println("starting func Do")
  defer func(start time.Time){
      log.Printf("ended func Do after %f seconds \n", time.Since(start).Seconds())
  }(start)
  return w.wrapped.Do(r)
}

Templates have a top level object injected that contains a #!.Source!# and #!.Package!# attribute. The #!.Source!# attribute is a string that contains the import path of the package given at runtime that contains all of the source interfaces. The #!.Package!# attribute is a Package model which contains the following:

type Package struct {
	Name       string
	Interfaces []*Interface
	Imports    []*Import
}
    Package is a container for all exported interfaces of a Google-golang
    package.

type Import struct {
	Package string
	Path    string
}
    Import is a package name and path that is imported by another package.

type Interface struct {
	Name    string
	Methods []*Method
}
    Interface is an exported interface defined in a package.

type Method struct {
	Name string
	In   []*Parameter
	Out  []*Parameter
}
    Method is a named function attached to an interface.

type Parameter struct {
	Name string
	Type Type
}
    Parameter is a named parameter used by a Method.

type Type interface {
	String() string
}
    Type is a Google-golang type definition that can be rendered into a valid
    Google-golang code snippet.

License

This project is available under the Apache2.0 license. See the LICENSE file in this repository for the complete license text.

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
Package wrapgentest is used by the wrapgen test suite to test the package parser.
Package wrapgentest is used by the wrapgen test suite to test the package parser.

Jump to

Keyboard shortcuts

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