Initial commit

This commit is contained in:
Donny
2019-04-22 20:46:32 +08:00
commit 49ab8aadd1
25441 changed files with 4055000 additions and 0 deletions

31
vendor/github.com/otokaze/mock/mockgen/BUILD.bazel generated vendored Normal file
View File

@@ -0,0 +1,31 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"mockgen.go",
"parse.go",
"reflect.go",
],
importmap = "go-common/vendor/github.com/otokaze/mock/mockgen",
importpath = "github.com/otokaze/mock/mockgen",
visibility = ["//visibility:public"],
deps = ["//vendor/github.com/otokaze/mock/mockgen/model:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//vendor/github.com/otokaze/mock/mockgen/model:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

439
vendor/github.com/otokaze/mock/mockgen/mockgen.go generated vendored Normal file
View File

@@ -0,0 +1,439 @@
// Copyright 2010 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package mockgen generates mock implementations of Go interfaces.
package mockgen
// TODO: This does not support recursive embedded interfaces.
// TODO: This does not support embedding package-local interfaces in a separate file.
import (
"bytes"
"fmt"
"go/format"
"go/token"
"log"
"path"
"sort"
"strconv"
"strings"
"unicode"
"github.com/otokaze/mock/mockgen/model"
)
const (
gomockImportPath = "github.com/otokaze/mock/gomock"
)
var (
imports, auxFiles, buildFlags, execOnly string
progOnly bool
)
// Generator a generator struct.
type Generator struct {
buf bytes.Buffer
indent string
MockNames map[string]string //may be empty
Filename string // may be empty
SrcPackage, SrcInterfaces string // may be empty
packageMap map[string]string // map from import path to package name
}
func (g *Generator) p(format string, args ...interface{}) {
fmt.Fprintf(&g.buf, g.indent+format+"\n", args...)
}
func (g *Generator) in() {
g.indent += "\t"
}
func (g *Generator) out() {
if len(g.indent) > 0 {
g.indent = g.indent[0 : len(g.indent)-1]
}
}
func removeDot(s string) string {
if len(s) > 0 && s[len(s)-1] == '.' {
return s[0 : len(s)-1]
}
return s
}
// sanitize cleans up a string to make a suitable package name.
func sanitize(s string) string {
t := ""
for _, r := range s {
if t == "" {
if unicode.IsLetter(r) || r == '_' {
t += string(r)
continue
}
} else {
if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' {
t += string(r)
continue
}
}
t += "_"
}
if t == "_" {
t = "x"
}
return t
}
// Generate gen mock by pkg.
func (g *Generator) Generate(pkg *model.Package, pkgName string, outputPackagePath string) error {
g.p("// Code generated by MockGen. DO NOT EDIT.")
if g.Filename != "" {
g.p("// Source: %v", g.Filename)
} else {
g.p("// Source: %v (interfaces: %v)", g.SrcPackage, g.SrcInterfaces)
}
g.p("")
// Get all required imports, and generate unique names for them all.
im := pkg.Imports()
im[gomockImportPath] = true
// Only import reflect if it's used. We only use reflect in mocked methods
// so only import if any of the mocked interfaces have methods.
for _, intf := range pkg.Interfaces {
if len(intf.Methods) > 0 {
im["reflect"] = true
break
}
}
// Sort keys to make import alias generation predictable
sortedPaths := make([]string, len(im))
x := 0
for pth := range im {
sortedPaths[x] = pth
x++
}
sort.Strings(sortedPaths)
g.packageMap = make(map[string]string, len(im))
localNames := make(map[string]bool, len(im))
for _, pth := range sortedPaths {
base := sanitize(path.Base(pth))
// Local names for an imported package can usually be the basename of the import path.
// A couple of situations don't permit that, such as duplicate local names
// (e.g. importing "html/template" and "text/template"), or where the basename is
// a keyword (e.g. "foo/case").
// try base0, base1, ...
pkgName := base
i := 0
for localNames[pkgName] || token.Lookup(pkgName).IsKeyword() {
pkgName = base + strconv.Itoa(i)
i++
}
g.packageMap[pth] = pkgName
localNames[pkgName] = true
}
g.p("// Package %v is a generated GoMock package.", pkgName)
g.p("package %v", pkgName)
g.p("")
g.p("import (")
g.in()
for path, pkg := range g.packageMap {
if path == outputPackagePath {
continue
}
g.p("%v %q", pkg, path)
}
for _, path := range pkg.DotImports {
g.p(". %q", path)
}
g.out()
g.p(")")
for _, intf := range pkg.Interfaces {
if err := g.GenerateMockInterface(intf, outputPackagePath); err != nil {
return err
}
}
return nil
}
// The name of the mock type to use for the given interface identifier.
func (g *Generator) mockName(typeName string) string {
if mockName, ok := g.MockNames[typeName]; ok {
return mockName
}
return "Mock" + typeName
}
// GenerateMockInterface gen mock intf.
func (g *Generator) GenerateMockInterface(intf *model.Interface, outputPackagePath string) error {
mockType := g.mockName(intf.Name)
g.p("")
g.p("// %v is a mock of %v interface", mockType, intf.Name)
g.p("type %v struct {", mockType)
g.in()
g.p("ctrl *gomock.Controller")
g.p("recorder *%vMockRecorder", mockType)
g.out()
g.p("}")
g.p("")
g.p("// %vMockRecorder is the mock recorder for %v", mockType, mockType)
g.p("type %vMockRecorder struct {", mockType)
g.in()
g.p("mock *%v", mockType)
g.out()
g.p("}")
g.p("")
// TODO: Re-enable this if we can import the interface reliably.
//g.p("// Verify that the mock satisfies the interface at compile time.")
//g.p("var _ %v = (*%v)(nil)", typeName, mockType)
//g.p("")
g.p("// New%v creates a new mock instance", mockType)
g.p("func New%v(ctrl *gomock.Controller) *%v {", mockType, mockType)
g.in()
g.p("mock := &%v{ctrl: ctrl}", mockType)
g.p("mock.recorder = &%vMockRecorder{mock}", mockType)
g.p("return mock")
g.out()
g.p("}")
g.p("")
// XXX: possible name collision here if someone has EXPECT in their interface.
g.p("// EXPECT returns an object that allows the caller to indicate expected use")
g.p("func (m *%v) EXPECT() *%vMockRecorder {", mockType, mockType)
g.in()
g.p("return m.recorder")
g.out()
g.p("}")
g.GenerateMockMethods(mockType, intf, outputPackagePath)
return nil
}
// GenerateMockMethods gen mock methods.
func (g *Generator) GenerateMockMethods(mockType string, intf *model.Interface, pkgOverride string) {
for _, m := range intf.Methods {
g.p("")
g.GenerateMockMethod(mockType, m, pkgOverride)
g.p("")
g.GenerateMockRecorderMethod(mockType, m)
}
}
func makeArgString(argNames, argTypes []string) string {
args := make([]string, len(argNames))
for i, name := range argNames {
// specify the type only once for consecutive args of the same type
if i+1 < len(argTypes) && argTypes[i] == argTypes[i+1] {
args[i] = name
} else {
args[i] = name + " " + argTypes[i]
}
}
return strings.Join(args, ", ")
}
// GenerateMockMethod generates a mock method implementation.
// If non-empty, pkgOverride is the package in which unqualified types reside.
func (g *Generator) GenerateMockMethod(mockType string, m *model.Method, pkgOverride string) error {
argNames := g.getArgNames(m)
argTypes := g.getArgTypes(m, pkgOverride)
argString := makeArgString(argNames, argTypes)
rets := make([]string, len(m.Out))
for i, p := range m.Out {
rets[i] = p.Type.String(g.packageMap, pkgOverride)
}
retString := strings.Join(rets, ", ")
if len(rets) > 1 {
retString = "(" + retString + ")"
}
if retString != "" {
retString = " " + retString
}
ia := newIdentifierAllocator(argNames)
idRecv := ia.allocateIdentifier("m")
g.p("// %v mocks base method", m.Name)
g.p("func (%v *%v) %v(%v)%v {", idRecv, mockType, m.Name, argString, retString)
g.in()
var callArgs string
if m.Variadic == nil {
if len(argNames) > 0 {
callArgs = ", " + strings.Join(argNames, ", ")
}
} else {
// Non-trivial. The generated code must build a []interface{},
// but the variadic argument may be any type.
idVarArgs := ia.allocateIdentifier("varargs")
idVArg := ia.allocateIdentifier("a")
g.p("%s := []interface{}{%s}", idVarArgs, strings.Join(argNames[:len(argNames)-1], ", "))
g.p("for _, %s := range %s {", idVArg, argNames[len(argNames)-1])
g.in()
g.p("%s = append(%s, %s)", idVarArgs, idVarArgs, idVArg)
g.out()
g.p("}")
callArgs = ", " + idVarArgs + "..."
}
if len(m.Out) == 0 {
g.p(`%v.ctrl.Call(%v, %q%v)`, idRecv, idRecv, m.Name, callArgs)
} else {
idRet := ia.allocateIdentifier("ret")
g.p(`%v := %v.ctrl.Call(%v, %q%v)`, idRet, idRecv, idRecv, m.Name, callArgs)
// Go does not allow "naked" type assertions on nil values, so we use the two-value form here.
// The value of that is either (x.(T), true) or (Z, false), where Z is the zero value for T.
// Happily, this coincides with the semantics we want here.
retNames := make([]string, len(rets))
for i, t := range rets {
retNames[i] = ia.allocateIdentifier(fmt.Sprintf("ret%d", i))
g.p("%s, _ := %s[%d].(%s)", retNames[i], idRet, i, t)
}
g.p("return " + strings.Join(retNames, ", "))
}
g.out()
g.p("}")
return nil
}
// GenerateMockRecorderMethod gen mock recorder method.
func (g *Generator) GenerateMockRecorderMethod(mockType string, m *model.Method) error {
argNames := g.getArgNames(m)
var argString string
if m.Variadic == nil {
argString = strings.Join(argNames, ", ")
} else {
argString = strings.Join(argNames[:len(argNames)-1], ", ")
}
if argString != "" {
argString += " interface{}"
}
if m.Variadic != nil {
if argString != "" {
argString += ", "
}
argString += fmt.Sprintf("%s ...interface{}", argNames[len(argNames)-1])
}
ia := newIdentifierAllocator(argNames)
idRecv := ia.allocateIdentifier("mr")
g.p("// %v indicates an expected call of %v", m.Name, m.Name)
g.p("func (%s *%vMockRecorder) %v(%v) *gomock.Call {", idRecv, mockType, m.Name, argString)
g.in()
var callArgs string
if m.Variadic == nil {
if len(argNames) > 0 {
callArgs = ", " + strings.Join(argNames, ", ")
}
} else {
if len(argNames) == 1 {
// Easy: just use ... to push the arguments through.
callArgs = ", " + argNames[0] + "..."
} else {
// Hard: create a temporary slice.
idVarArgs := ia.allocateIdentifier("varargs")
g.p("%s := append([]interface{}{%s}, %s...)",
idVarArgs,
strings.Join(argNames[:len(argNames)-1], ", "),
argNames[len(argNames)-1])
callArgs = ", " + idVarArgs + "..."
}
}
g.p(`return %s.mock.ctrl.RecordCallWithMethodType(%s.mock, "%s", reflect.TypeOf((*%s)(nil).%s)%s)`, idRecv, idRecv, m.Name, mockType, m.Name, callArgs)
g.out()
g.p("}")
return nil
}
func (g *Generator) getArgNames(m *model.Method) []string {
argNames := make([]string, len(m.In))
for i, p := range m.In {
name := p.Name
if name == "" {
name = fmt.Sprintf("arg%d", i)
}
argNames[i] = name
}
if m.Variadic != nil {
name := m.Variadic.Name
if name == "" {
name = fmt.Sprintf("arg%d", len(m.In))
}
argNames = append(argNames, name)
}
return argNames
}
func (g *Generator) getArgTypes(m *model.Method, pkgOverride string) []string {
argTypes := make([]string, len(m.In))
for i, p := range m.In {
argTypes[i] = p.Type.String(g.packageMap, pkgOverride)
}
if m.Variadic != nil {
argTypes = append(argTypes, "..."+m.Variadic.Type.String(g.packageMap, pkgOverride))
}
return argTypes
}
type identifierAllocator map[string]struct{}
func newIdentifierAllocator(taken []string) identifierAllocator {
a := make(identifierAllocator, len(taken))
for _, s := range taken {
a[s] = struct{}{}
}
return a
}
func (o identifierAllocator) allocateIdentifier(want string) string {
id := want
for i := 2; ; i++ {
if _, ok := o[id]; !ok {
o[id] = struct{}{}
return id
}
id = want + "_" + strconv.Itoa(i)
}
}
// Output returns the generator's output, formatted in the standard Go style.
func (g *Generator) Output() []byte {
src, err := format.Source(g.buf.Bytes())
if err != nil {
log.Fatalf("Failed to format generated source code: %s\n%s", err, g.buf.String())
}
return src
}

View File

@@ -0,0 +1,23 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["model.go"],
importmap = "go-common/vendor/github.com/otokaze/mock/mockgen/model",
importpath = "github.com/otokaze/mock/mockgen/model",
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

450
vendor/github.com/otokaze/mock/mockgen/model/model.go generated vendored Normal file
View File

@@ -0,0 +1,450 @@
// Copyright 2012 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package model contains the data model necessary for generating mock implementations.
package model
import (
"encoding/gob"
"fmt"
"io"
"reflect"
"strings"
)
// pkgPath is the importable path for package model
const pkgPath = "github.com/otokaze/mock/mockgen/model"
// Package is a Go package. It may be a subset.
type Package struct {
Name string
SrcDir string
Interfaces []*Interface
DotImports []string
}
func (pkg *Package) Print(w io.Writer) {
fmt.Fprintf(w, "package %s\n", pkg.Name)
for _, intf := range pkg.Interfaces {
intf.Print(w)
}
}
// Imports returns the imports needed by the Package as a set of import paths.
func (pkg *Package) Imports() map[string]bool {
im := make(map[string]bool)
for _, intf := range pkg.Interfaces {
intf.addImports(im)
}
return im
}
// Interface is a Go interface.
type Interface struct {
Name string
Methods []*Method
}
func (intf *Interface) Print(w io.Writer) {
fmt.Fprintf(w, "interface %s\n", intf.Name)
for _, m := range intf.Methods {
m.Print(w)
}
}
func (intf *Interface) addImports(im map[string]bool) {
for _, m := range intf.Methods {
m.addImports(im)
}
}
// Method is a single method of an interface.
type Method struct {
Name string
In, Out []*Parameter
Variadic *Parameter // may be nil
}
func (m *Method) Print(w io.Writer) {
fmt.Fprintf(w, " - method %s\n", m.Name)
if len(m.In) > 0 {
fmt.Fprintf(w, " in:\n")
for _, p := range m.In {
p.Print(w)
}
}
if m.Variadic != nil {
fmt.Fprintf(w, " ...:\n")
m.Variadic.Print(w)
}
if len(m.Out) > 0 {
fmt.Fprintf(w, " out:\n")
for _, p := range m.Out {
p.Print(w)
}
}
}
func (m *Method) addImports(im map[string]bool) {
for _, p := range m.In {
p.Type.addImports(im)
}
if m.Variadic != nil {
m.Variadic.Type.addImports(im)
}
for _, p := range m.Out {
p.Type.addImports(im)
}
}
// Parameter is an argument or return parameter of a method.
type Parameter struct {
Name string // may be empty
Type Type
}
func (p *Parameter) Print(w io.Writer) {
n := p.Name
if n == "" {
n = `""`
}
fmt.Fprintf(w, " - %v: %v\n", n, p.Type.String(nil, ""))
}
// Type is a Go type.
type Type interface {
String(pm map[string]string, pkgOverride string) string
addImports(im map[string]bool)
}
func init() {
gob.Register(&ArrayType{})
gob.Register(&ChanType{})
gob.Register(&FuncType{})
gob.Register(&MapType{})
gob.Register(&NamedType{})
gob.Register(&PointerType{})
// Call gob.RegisterName to make sure it has the consistent name registered
// for both gob decoder and encoder.
//
// For a non-pointer type, gob.Register will try to get package full path by
// calling rt.PkgPath() for a name to register. If your project has vendor
// directory, it is possible that PkgPath will get a path like this:
// ../../../vendor/github.com/golang/mock/mockgen/model
gob.RegisterName(pkgPath+".PredeclaredType", PredeclaredType(""))
}
// ArrayType is an array or slice type.
type ArrayType struct {
Len int // -1 for slices, >= 0 for arrays
Type Type
}
func (at *ArrayType) String(pm map[string]string, pkgOverride string) string {
s := "[]"
if at.Len > -1 {
s = fmt.Sprintf("[%d]", at.Len)
}
return s + at.Type.String(pm, pkgOverride)
}
func (at *ArrayType) addImports(im map[string]bool) { at.Type.addImports(im) }
// ChanType is a channel type.
type ChanType struct {
Dir ChanDir // 0, 1 or 2
Type Type
}
func (ct *ChanType) String(pm map[string]string, pkgOverride string) string {
s := ct.Type.String(pm, pkgOverride)
if ct.Dir == RecvDir {
return "<-chan " + s
}
if ct.Dir == SendDir {
return "chan<- " + s
}
return "chan " + s
}
func (ct *ChanType) addImports(im map[string]bool) { ct.Type.addImports(im) }
// ChanDir is a channel direction.
type ChanDir int
const (
RecvDir ChanDir = 1
SendDir ChanDir = 2
)
// FuncType is a function type.
type FuncType struct {
In, Out []*Parameter
Variadic *Parameter // may be nil
}
func (ft *FuncType) String(pm map[string]string, pkgOverride string) string {
args := make([]string, len(ft.In))
for i, p := range ft.In {
args[i] = p.Type.String(pm, pkgOverride)
}
if ft.Variadic != nil {
args = append(args, "..."+ft.Variadic.Type.String(pm, pkgOverride))
}
rets := make([]string, len(ft.Out))
for i, p := range ft.Out {
rets[i] = p.Type.String(pm, pkgOverride)
}
retString := strings.Join(rets, ", ")
if nOut := len(ft.Out); nOut == 1 {
retString = " " + retString
} else if nOut > 1 {
retString = " (" + retString + ")"
}
return "func(" + strings.Join(args, ", ") + ")" + retString
}
func (ft *FuncType) addImports(im map[string]bool) {
for _, p := range ft.In {
p.Type.addImports(im)
}
if ft.Variadic != nil {
ft.Variadic.Type.addImports(im)
}
for _, p := range ft.Out {
p.Type.addImports(im)
}
}
// MapType is a map type.
type MapType struct {
Key, Value Type
}
func (mt *MapType) String(pm map[string]string, pkgOverride string) string {
return "map[" + mt.Key.String(pm, pkgOverride) + "]" + mt.Value.String(pm, pkgOverride)
}
func (mt *MapType) addImports(im map[string]bool) {
mt.Key.addImports(im)
mt.Value.addImports(im)
}
// NamedType is an exported type in a package.
type NamedType struct {
Package string // may be empty
Type string // TODO: should this be typed Type?
}
func (nt *NamedType) String(pm map[string]string, pkgOverride string) string {
// TODO: is this right?
if pkgOverride == nt.Package {
return nt.Type
}
return pm[nt.Package] + "." + nt.Type
}
func (nt *NamedType) addImports(im map[string]bool) {
if nt.Package != "" {
im[nt.Package] = true
}
}
// PointerType is a pointer to another type.
type PointerType struct {
Type Type
}
func (pt *PointerType) String(pm map[string]string, pkgOverride string) string {
return "*" + pt.Type.String(pm, pkgOverride)
}
func (pt *PointerType) addImports(im map[string]bool) { pt.Type.addImports(im) }
// PredeclaredType is a predeclared type such as "int".
type PredeclaredType string
func (pt PredeclaredType) String(pm map[string]string, pkgOverride string) string { return string(pt) }
func (pt PredeclaredType) addImports(im map[string]bool) {}
// The following code is intended to be called by the program generated by ../reflect.go.
func InterfaceFromInterfaceType(it reflect.Type) (*Interface, error) {
if it.Kind() != reflect.Interface {
return nil, fmt.Errorf("%v is not an interface", it)
}
intf := &Interface{}
for i := 0; i < it.NumMethod(); i++ {
mt := it.Method(i)
// TODO: need to skip unexported methods? or just raise an error?
m := &Method{
Name: mt.Name,
}
var err error
m.In, m.Variadic, m.Out, err = funcArgsFromType(mt.Type)
if err != nil {
return nil, err
}
intf.Methods = append(intf.Methods, m)
}
return intf, nil
}
// t's Kind must be a reflect.Func.
func funcArgsFromType(t reflect.Type) (in []*Parameter, variadic *Parameter, out []*Parameter, err error) {
nin := t.NumIn()
if t.IsVariadic() {
nin--
}
var p *Parameter
for i := 0; i < nin; i++ {
p, err = parameterFromType(t.In(i))
if err != nil {
return
}
in = append(in, p)
}
if t.IsVariadic() {
p, err = parameterFromType(t.In(nin).Elem())
if err != nil {
return
}
variadic = p
}
for i := 0; i < t.NumOut(); i++ {
p, err = parameterFromType(t.Out(i))
if err != nil {
return
}
out = append(out, p)
}
return
}
func parameterFromType(t reflect.Type) (*Parameter, error) {
tt, err := typeFromType(t)
if err != nil {
return nil, err
}
return &Parameter{Type: tt}, nil
}
var errorType = reflect.TypeOf((*error)(nil)).Elem()
var byteType = reflect.TypeOf(byte(0))
func typeFromType(t reflect.Type) (Type, error) {
// Hack workaround for https://golang.org/issue/3853.
// This explicit check should not be necessary.
if t == byteType {
return PredeclaredType("byte"), nil
}
if imp := t.PkgPath(); imp != "" {
// PkgPath might return a path that includes "vendor"
// These paths do not compile, so we need to remove everything
// up to and including "/vendor/"
// see https://github.com/golang/go/issues/12019
if i := strings.LastIndex(imp, "/vendor/"); i != -1 {
imp = imp[i+len("/vendor/"):]
}
return &NamedType{
Package: imp,
Type: t.Name(),
}, nil
}
// only unnamed or predeclared types after here
// Lots of types have element types. Let's do the parsing and error checking for all of them.
var elemType Type
switch t.Kind() {
case reflect.Array, reflect.Chan, reflect.Map, reflect.Ptr, reflect.Slice:
var err error
elemType, err = typeFromType(t.Elem())
if err != nil {
return nil, err
}
}
switch t.Kind() {
case reflect.Array:
return &ArrayType{
Len: t.Len(),
Type: elemType,
}, nil
case reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128, reflect.String:
return PredeclaredType(t.Kind().String()), nil
case reflect.Chan:
var dir ChanDir
switch t.ChanDir() {
case reflect.RecvDir:
dir = RecvDir
case reflect.SendDir:
dir = SendDir
}
return &ChanType{
Dir: dir,
Type: elemType,
}, nil
case reflect.Func:
in, variadic, out, err := funcArgsFromType(t)
if err != nil {
return nil, err
}
return &FuncType{
In: in,
Out: out,
Variadic: variadic,
}, nil
case reflect.Interface:
// Two special interfaces.
if t.NumMethod() == 0 {
return PredeclaredType("interface{}"), nil
}
if t == errorType {
return PredeclaredType("error"), nil
}
case reflect.Map:
kt, err := typeFromType(t.Key())
if err != nil {
return nil, err
}
return &MapType{
Key: kt,
Value: elemType,
}, nil
case reflect.Ptr:
return &PointerType{
Type: elemType,
}, nil
case reflect.Slice:
return &ArrayType{
Len: -1,
Type: elemType,
}, nil
case reflect.Struct:
if t.NumField() == 0 {
return PredeclaredType("struct{}"), nil
}
}
// TODO: Struct, UnsafePointer
return nil, fmt.Errorf("can't yet turn %v (%v) into a model.Type", t, t.Kind())
}

494
vendor/github.com/otokaze/mock/mockgen/parse.go generated vendored Normal file
View File

@@ -0,0 +1,494 @@
// Copyright 2012 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package mockgen
// This file contains the model construction by parsing source files.
import (
"fmt"
"go/ast"
"go/build"
"go/parser"
"go/token"
"log"
"path"
"path/filepath"
"strconv"
"strings"
"github.com/otokaze/mock/mockgen/model"
)
// ParseFile parse by a file
// TODO: simplify error reporting
func ParseFile(source string) (*model.Package, error) {
srcDir, err := filepath.Abs(filepath.Dir(source))
if err != nil {
return nil, fmt.Errorf("failed getting source directory: %v", err)
}
var packageImport string
if p, err := build.ImportDir(srcDir, 0); err == nil {
packageImport = p.ImportPath
} // TODO: should we fail if this returns an error?
fs := token.NewFileSet()
file, err := parser.ParseFile(fs, source, nil, 0)
if err != nil {
return nil, fmt.Errorf("failed parsing source file %v: %v", source, err)
}
p := &fileParser{
fileSet: fs,
imports: make(map[string]string),
importedInterfaces: make(map[string]map[string]*ast.InterfaceType),
auxInterfaces: make(map[string]map[string]*ast.InterfaceType),
srcDir: srcDir,
}
// Handle -imports.
dotImports := make(map[string]bool)
if imports != "" {
for _, kv := range strings.Split(imports, ",") {
eq := strings.Index(kv, "=")
k, v := kv[:eq], kv[eq+1:]
if k == "." {
// TODO: Catch dupes?
dotImports[v] = true
} else {
// TODO: Catch dupes?
p.imports[k] = v
}
}
}
// Handle -aux_files.
if err := p.parseAuxFiles(auxFiles); err != nil {
return nil, err
}
p.addAuxInterfacesFromFile(packageImport, file) // this file
pkg, err := p.parseFile(packageImport, file)
if err != nil {
return nil, err
}
pkg.DotImports = make([]string, 0, len(dotImports))
for path := range dotImports {
pkg.DotImports = append(pkg.DotImports, path)
}
return pkg, nil
}
type fileParser struct {
fileSet *token.FileSet
imports map[string]string // package name => import path
importedInterfaces map[string]map[string]*ast.InterfaceType // package (or "") => name => interface
auxFiles []*ast.File
auxInterfaces map[string]map[string]*ast.InterfaceType // package (or "") => name => interface
srcDir string
}
func (p *fileParser) errorf(pos token.Pos, format string, args ...interface{}) error {
ps := p.fileSet.Position(pos)
format = "%s:%d:%d: " + format
args = append([]interface{}{ps.Filename, ps.Line, ps.Column}, args...)
return fmt.Errorf(format, args...)
}
func (p *fileParser) parseAuxFiles(auxFiles string) error {
auxFiles = strings.TrimSpace(auxFiles)
if auxFiles == "" {
return nil
}
for _, kv := range strings.Split(auxFiles, ",") {
parts := strings.SplitN(kv, "=", 2)
if len(parts) != 2 {
return fmt.Errorf("bad aux file spec: %v", kv)
}
pkg, fpath := parts[0], parts[1]
file, err := parser.ParseFile(p.fileSet, fpath, nil, 0)
if err != nil {
return err
}
p.auxFiles = append(p.auxFiles, file)
p.addAuxInterfacesFromFile(pkg, file)
}
return nil
}
func (p *fileParser) addAuxInterfacesFromFile(pkg string, file *ast.File) {
if _, ok := p.auxInterfaces[pkg]; !ok {
p.auxInterfaces[pkg] = make(map[string]*ast.InterfaceType)
}
for ni := range iterInterfaces(file) {
p.auxInterfaces[pkg][ni.name.Name] = ni.it
}
}
// parseFile loads all file imports and auxiliary files import into the
// fileParser, parses all file interfaces and returns package model.
func (p *fileParser) parseFile(importPath string, file *ast.File) (*model.Package, error) {
allImports := importsOfFile(file)
// Don't stomp imports provided by -imports. Those should take precedence.
for pkg, path := range allImports {
if _, ok := p.imports[pkg]; !ok {
p.imports[pkg] = path
}
}
// Add imports from auxiliary files, which might be needed for embedded interfaces.
// Don't stomp any other imports.
for _, f := range p.auxFiles {
for pkg, path := range importsOfFile(f) {
if _, ok := p.imports[pkg]; !ok {
p.imports[pkg] = path
}
}
}
var is []*model.Interface
for ni := range iterInterfaces(file) {
i, err := p.parseInterface(ni.name.String(), importPath, ni.it)
if err != nil {
return nil, err
}
is = append(is, i)
}
return &model.Package{
Name: file.Name.String(),
SrcDir: p.srcDir,
Interfaces: is,
}, nil
}
// parsePackage loads package specified by path, parses it and populates
// corresponding imports and importedInterfaces into the fileParser.
func (p *fileParser) parsePackage(path string) error {
var pkgs map[string]*ast.Package
if imp, err := build.Import(path, p.srcDir, build.FindOnly); err != nil {
return err
} else if pkgs, err = parser.ParseDir(p.fileSet, imp.Dir, nil, 0); err != nil {
return err
}
for _, pkg := range pkgs {
file := ast.MergePackageFiles(pkg, ast.FilterFuncDuplicates|ast.FilterUnassociatedComments|ast.FilterImportDuplicates)
if _, ok := p.importedInterfaces[path]; !ok {
p.importedInterfaces[path] = make(map[string]*ast.InterfaceType)
}
for ni := range iterInterfaces(file) {
p.importedInterfaces[path][ni.name.Name] = ni.it
}
for pkgName, pkgPath := range importsOfFile(file) {
if _, ok := p.imports[pkgName]; !ok {
p.imports[pkgName] = pkgPath
}
}
}
return nil
}
func (p *fileParser) parseInterface(name, pkg string, it *ast.InterfaceType) (*model.Interface, error) {
intf := &model.Interface{Name: name}
for _, field := range it.Methods.List {
switch v := field.Type.(type) {
case *ast.FuncType:
if nn := len(field.Names); nn != 1 {
return nil, fmt.Errorf("expected one name for interface %v, got %d", intf.Name, nn)
}
m := &model.Method{
Name: field.Names[0].String(),
}
var err error
m.In, m.Variadic, m.Out, err = p.parseFunc(pkg, v)
if err != nil {
return nil, err
}
intf.Methods = append(intf.Methods, m)
case *ast.Ident:
// Embedded interface in this package.
ei := p.auxInterfaces[pkg][v.String()]
if ei == nil {
if ei = p.importedInterfaces[pkg][v.String()]; ei == nil {
return nil, p.errorf(v.Pos(), "unknown embedded interface %s", v.String())
}
}
eintf, err := p.parseInterface(v.String(), pkg, ei)
if err != nil {
return nil, err
}
// Copy the methods.
// TODO: apply shadowing rules.
intf.Methods = append(intf.Methods, eintf.Methods...)
case *ast.SelectorExpr:
// Embedded interface in another package.
fpkg, sel := v.X.(*ast.Ident).String(), v.Sel.String()
epkg, ok := p.imports[fpkg]
if !ok {
return nil, p.errorf(v.X.Pos(), "unknown package %s", fpkg)
}
ei := p.auxInterfaces[fpkg][sel]
if ei == nil {
fpkg = epkg
if _, ok = p.importedInterfaces[epkg]; !ok {
if err := p.parsePackage(epkg); err != nil {
return nil, p.errorf(v.Pos(), "could not parse package %s: %v", fpkg, err)
}
}
if ei = p.importedInterfaces[epkg][sel]; ei == nil {
return nil, p.errorf(v.Pos(), "unknown embedded interface %s.%s", fpkg, sel)
}
}
eintf, err := p.parseInterface(sel, fpkg, ei)
if err != nil {
return nil, err
}
// Copy the methods.
// TODO: apply shadowing rules.
intf.Methods = append(intf.Methods, eintf.Methods...)
default:
return nil, fmt.Errorf("don't know how to mock method of type %T", field.Type)
}
}
return intf, nil
}
func (p *fileParser) parseFunc(pkg string, f *ast.FuncType) (in []*model.Parameter, variadic *model.Parameter, out []*model.Parameter, err error) {
if f.Params != nil {
regParams := f.Params.List
if isVariadic(f) {
n := len(regParams)
varParams := regParams[n-1:]
regParams = regParams[:n-1]
vp, err := p.parseFieldList(pkg, varParams)
if err != nil {
return nil, nil, nil, p.errorf(varParams[0].Pos(), "failed parsing variadic argument: %v", err)
}
variadic = vp[0]
}
in, err = p.parseFieldList(pkg, regParams)
if err != nil {
return nil, nil, nil, p.errorf(f.Pos(), "failed parsing arguments: %v", err)
}
}
if f.Results != nil {
out, err = p.parseFieldList(pkg, f.Results.List)
if err != nil {
return nil, nil, nil, p.errorf(f.Pos(), "failed parsing returns: %v", err)
}
}
return
}
func (p *fileParser) parseFieldList(pkg string, fields []*ast.Field) ([]*model.Parameter, error) {
nf := 0
for _, f := range fields {
nn := len(f.Names)
if nn == 0 {
nn = 1 // anonymous parameter
}
nf += nn
}
if nf == 0 {
return nil, nil
}
ps := make([]*model.Parameter, nf)
i := 0 // destination index
for _, f := range fields {
t, err := p.parseType(pkg, f.Type)
if err != nil {
return nil, err
}
if len(f.Names) == 0 {
// anonymous arg
ps[i] = &model.Parameter{Type: t}
i++
continue
}
for _, name := range f.Names {
ps[i] = &model.Parameter{Name: name.Name, Type: t}
i++
}
}
return ps, nil
}
func (p *fileParser) parseType(pkg string, typ ast.Expr) (model.Type, error) {
switch v := typ.(type) {
case *ast.ArrayType:
ln := -1
if v.Len != nil {
x, err := strconv.Atoi(v.Len.(*ast.BasicLit).Value)
if err != nil {
return nil, p.errorf(v.Len.Pos(), "bad array size: %v", err)
}
ln = x
}
t, err := p.parseType(pkg, v.Elt)
if err != nil {
return nil, err
}
return &model.ArrayType{Len: ln, Type: t}, nil
case *ast.ChanType:
t, err := p.parseType(pkg, v.Value)
if err != nil {
return nil, err
}
var dir model.ChanDir
if v.Dir == ast.SEND {
dir = model.SendDir
}
if v.Dir == ast.RECV {
dir = model.RecvDir
}
return &model.ChanType{Dir: dir, Type: t}, nil
case *ast.Ellipsis:
// assume we're parsing a variadic argument
return p.parseType(pkg, v.Elt)
case *ast.FuncType:
in, variadic, out, err := p.parseFunc(pkg, v)
if err != nil {
return nil, err
}
return &model.FuncType{In: in, Out: out, Variadic: variadic}, nil
case *ast.Ident:
if v.IsExported() {
// `pkg` may be an aliased imported pkg
// if so, patch the import w/ the fully qualified import
maybeImportedPkg, ok := p.imports[pkg]
if ok {
pkg = maybeImportedPkg
}
// assume type in this package
return &model.NamedType{Package: pkg, Type: v.Name}, nil
}
return model.PredeclaredType(v.Name), nil
case *ast.InterfaceType:
if v.Methods != nil && len(v.Methods.List) > 0 {
return nil, p.errorf(v.Pos(), "can't handle non-empty unnamed interface types")
}
return model.PredeclaredType("interface{}"), nil
case *ast.MapType:
key, err := p.parseType(pkg, v.Key)
if err != nil {
return nil, err
}
value, err := p.parseType(pkg, v.Value)
if err != nil {
return nil, err
}
return &model.MapType{Key: key, Value: value}, nil
case *ast.SelectorExpr:
pkgName := v.X.(*ast.Ident).String()
pkg, ok := p.imports[pkgName]
if !ok {
return nil, p.errorf(v.Pos(), "unknown package %q", pkgName)
}
return &model.NamedType{Package: pkg, Type: v.Sel.String()}, nil
case *ast.StarExpr:
t, err := p.parseType(pkg, v.X)
if err != nil {
return nil, err
}
return &model.PointerType{Type: t}, nil
case *ast.StructType:
if v.Fields != nil && len(v.Fields.List) > 0 {
return nil, p.errorf(v.Pos(), "can't handle non-empty unnamed struct types")
}
return model.PredeclaredType("struct{}"), nil
}
return nil, fmt.Errorf("don't know how to parse type %T", typ)
}
// importsOfFile returns a map of package name to import path
// of the imports in file.
func importsOfFile(file *ast.File) map[string]string {
m := make(map[string]string)
for _, is := range file.Imports {
var pkgName string
importPath := is.Path.Value[1 : len(is.Path.Value)-1] // remove quotes
if is.Name != nil {
// Named imports are always certain.
if is.Name.Name == "_" {
continue
}
pkgName = removeDot(is.Name.Name)
} else {
pkg, err := build.Import(importPath, "", 0)
if err != nil {
// Fallback to import path suffix. Note that this is uncertain.
_, last := path.Split(importPath)
// If the last path component has dots, the first dot-delimited
// field is used as the name.
pkgName = strings.SplitN(last, ".", 2)[0]
} else {
pkgName = pkg.Name
}
}
if _, ok := m[pkgName]; ok {
log.Fatalf("imported package collision: %q imported twice", pkgName)
}
m[pkgName] = importPath
}
return m
}
type namedInterface struct {
name *ast.Ident
it *ast.InterfaceType
}
// Create an iterator over all interfaces in file.
func iterInterfaces(file *ast.File) <-chan namedInterface {
ch := make(chan namedInterface)
go func() {
for _, decl := range file.Decls {
gd, ok := decl.(*ast.GenDecl)
if !ok || gd.Tok != token.TYPE {
continue
}
for _, spec := range gd.Specs {
ts, ok := spec.(*ast.TypeSpec)
if !ok {
continue
}
it, ok := ts.Type.(*ast.InterfaceType)
if !ok {
continue
}
ch <- namedInterface{ts.Name, it}
}
}
close(ch)
}()
return ch
}
// isVariadic returns whether the function is variadic.
func isVariadic(f *ast.FuncType) bool {
nargs := len(f.Params.List)
if nargs == 0 {
return false
}
_, ok := f.Params.List[nargs-1].Type.(*ast.Ellipsis)
return ok
}

228
vendor/github.com/otokaze/mock/mockgen/reflect.go generated vendored Normal file
View File

@@ -0,0 +1,228 @@
// Copyright 2012 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package mockgen
// This file contains the model construction by reflection.
import (
"bytes"
"encoding/gob"
"go/build"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"runtime"
"text/template"
"github.com/otokaze/mock/mockgen/model"
)
func writeProgram(importPath string, symbols []string) ([]byte, error) {
var program bytes.Buffer
data := reflectData{
ImportPath: importPath,
Symbols: symbols,
}
if err := reflectProgram.Execute(&program, &data); err != nil {
return nil, err
}
return program.Bytes(), nil
}
// run the given program and parse the output as a model.Package.
func run(program string) (*model.Package, error) {
f, _ := ioutil.TempFile("", "")
filename := f.Name()
defer os.Remove(filename)
if err := f.Close(); err != nil {
return nil, err
}
// Run the program.
cmd := exec.Command(program, "-output", filename)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
return nil, err
}
f, err := os.Open(filename)
if err != nil {
return nil, err
}
// Process output.
var pkg model.Package
if err := gob.NewDecoder(f).Decode(&pkg); err != nil {
return nil, err
}
if err := f.Close(); err != nil {
return nil, err
}
return &pkg, nil
}
// runInDir writes the given program into the given dir, runs it there, and
// parses the output as a model.Package.
func runInDir(program []byte, dir string) (*model.Package, error) {
// We use TempDir instead of TempFile so we can control the filename.
tmpDir, err := ioutil.TempDir(dir, "gomock_reflect_")
if err != nil {
return nil, err
}
defer func() { os.RemoveAll(tmpDir) }()
const progSource = "prog.go"
var progBinary = "prog.bin"
if runtime.GOOS == "windows" {
// Windows won't execute a program unless it has a ".exe" suffix.
progBinary += ".exe"
}
if err := ioutil.WriteFile(filepath.Join(tmpDir, progSource), program, 0600); err != nil {
return nil, err
}
cmdArgs := []string{}
cmdArgs = append(cmdArgs, "build")
if buildFlags != "" {
cmdArgs = append(cmdArgs, buildFlags)
}
cmdArgs = append(cmdArgs, "-o", progBinary, progSource)
// Build the program.
cmd := exec.Command("go", cmdArgs...)
cmd.Dir = tmpDir
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
return nil, err
}
return run(filepath.Join(tmpDir, progBinary))
}
// Reflect get pkg with reflect.
func Reflect(importPath string, symbols []string) (*model.Package, error) {
// TODO: sanity check arguments
if execOnly != "" {
return run(execOnly)
}
program, err := writeProgram(importPath, symbols)
if err != nil {
return nil, err
}
if progOnly {
os.Stdout.Write(program)
os.Exit(0)
}
wd, _ := os.Getwd()
// Try to run the program in the same directory as the input package.
if p, err := build.Import(importPath, wd, build.FindOnly); err == nil {
dir := p.Dir
if p, err := runInDir(program, dir); err == nil {
return p, nil
}
}
// Since that didn't work, try to run it in the current working directory.
if p, err := runInDir(program, wd); err == nil {
return p, nil
}
// Since that didn't work, try to run it in a standard temp directory.
return runInDir(program, "")
}
type reflectData struct {
ImportPath string
Symbols []string
}
// This program reflects on an interface value, and prints the
// gob encoding of a model.Package to standard output.
// JSON doesn't work because of the model.Type interface.
var reflectProgram = template.Must(template.New("program").Parse(`
package main
import (
"encoding/gob"
"flag"
"fmt"
"os"
"path"
"reflect"
"github.com/otokaze/mock/mockgen/model"
pkg_ {{printf "%q" .ImportPath}}
)
var output = flag.String("output", "", "The output file name, or empty to use stdout.")
func main() {
flag.Parse()
its := []struct{
sym string
typ reflect.Type
}{
{{range .Symbols}}
{ {{printf "%q" .}}, reflect.TypeOf((*pkg_.{{.}})(nil)).Elem()},
{{end}}
}
pkg := &model.Package{
// NOTE: This behaves contrary to documented behaviour if the
// package name is not the final component of the import path.
// The reflect package doesn't expose the package name, though.
Name: path.Base({{printf "%q" .ImportPath}}),
}
for _, it := range its {
intf, err := model.InterfaceFromInterfaceType(it.typ)
if err != nil {
fmt.Fprintf(os.Stderr, "Reflection: %v\n", err)
os.Exit(1)
}
intf.Name = it.sym
pkg.Interfaces = append(pkg.Interfaces, intf)
}
outfile := os.Stdout
if len(*output) != 0 {
var err error
outfile, err = os.Create(*output)
if err != nil {
fmt.Fprintf(os.Stderr, "failed to open output file %q", *output)
}
defer func() {
if err := outfile.Close(); err != nil {
fmt.Fprintf(os.Stderr, "failed to close output file %q", *output)
os.Exit(1)
}
}()
}
if err := gob.NewEncoder(outfile).Encode(pkg); err != nil {
fmt.Fprintf(os.Stderr, "gob encode: %v\n", err)
os.Exit(1)
}
}
`))