model.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. // Copyright 2012 Google Inc.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // Package model contains the data model necessary for generating mock implementations.
  15. package model
  16. import (
  17. "encoding/gob"
  18. "fmt"
  19. "io"
  20. "reflect"
  21. "strings"
  22. )
  23. // pkgPath is the importable path for package model
  24. const pkgPath = "github.com/otokaze/mock/mockgen/model"
  25. // Package is a Go package. It may be a subset.
  26. type Package struct {
  27. Name string
  28. SrcDir string
  29. Interfaces []*Interface
  30. DotImports []string
  31. }
  32. func (pkg *Package) Print(w io.Writer) {
  33. fmt.Fprintf(w, "package %s\n", pkg.Name)
  34. for _, intf := range pkg.Interfaces {
  35. intf.Print(w)
  36. }
  37. }
  38. // Imports returns the imports needed by the Package as a set of import paths.
  39. func (pkg *Package) Imports() map[string]bool {
  40. im := make(map[string]bool)
  41. for _, intf := range pkg.Interfaces {
  42. intf.addImports(im)
  43. }
  44. return im
  45. }
  46. // Interface is a Go interface.
  47. type Interface struct {
  48. Name string
  49. Methods []*Method
  50. }
  51. func (intf *Interface) Print(w io.Writer) {
  52. fmt.Fprintf(w, "interface %s\n", intf.Name)
  53. for _, m := range intf.Methods {
  54. m.Print(w)
  55. }
  56. }
  57. func (intf *Interface) addImports(im map[string]bool) {
  58. for _, m := range intf.Methods {
  59. m.addImports(im)
  60. }
  61. }
  62. // Method is a single method of an interface.
  63. type Method struct {
  64. Name string
  65. In, Out []*Parameter
  66. Variadic *Parameter // may be nil
  67. }
  68. func (m *Method) Print(w io.Writer) {
  69. fmt.Fprintf(w, " - method %s\n", m.Name)
  70. if len(m.In) > 0 {
  71. fmt.Fprintf(w, " in:\n")
  72. for _, p := range m.In {
  73. p.Print(w)
  74. }
  75. }
  76. if m.Variadic != nil {
  77. fmt.Fprintf(w, " ...:\n")
  78. m.Variadic.Print(w)
  79. }
  80. if len(m.Out) > 0 {
  81. fmt.Fprintf(w, " out:\n")
  82. for _, p := range m.Out {
  83. p.Print(w)
  84. }
  85. }
  86. }
  87. func (m *Method) addImports(im map[string]bool) {
  88. for _, p := range m.In {
  89. p.Type.addImports(im)
  90. }
  91. if m.Variadic != nil {
  92. m.Variadic.Type.addImports(im)
  93. }
  94. for _, p := range m.Out {
  95. p.Type.addImports(im)
  96. }
  97. }
  98. // Parameter is an argument or return parameter of a method.
  99. type Parameter struct {
  100. Name string // may be empty
  101. Type Type
  102. }
  103. func (p *Parameter) Print(w io.Writer) {
  104. n := p.Name
  105. if n == "" {
  106. n = `""`
  107. }
  108. fmt.Fprintf(w, " - %v: %v\n", n, p.Type.String(nil, ""))
  109. }
  110. // Type is a Go type.
  111. type Type interface {
  112. String(pm map[string]string, pkgOverride string) string
  113. addImports(im map[string]bool)
  114. }
  115. func init() {
  116. gob.Register(&ArrayType{})
  117. gob.Register(&ChanType{})
  118. gob.Register(&FuncType{})
  119. gob.Register(&MapType{})
  120. gob.Register(&NamedType{})
  121. gob.Register(&PointerType{})
  122. // Call gob.RegisterName to make sure it has the consistent name registered
  123. // for both gob decoder and encoder.
  124. //
  125. // For a non-pointer type, gob.Register will try to get package full path by
  126. // calling rt.PkgPath() for a name to register. If your project has vendor
  127. // directory, it is possible that PkgPath will get a path like this:
  128. // ../../../vendor/github.com/golang/mock/mockgen/model
  129. gob.RegisterName(pkgPath+".PredeclaredType", PredeclaredType(""))
  130. }
  131. // ArrayType is an array or slice type.
  132. type ArrayType struct {
  133. Len int // -1 for slices, >= 0 for arrays
  134. Type Type
  135. }
  136. func (at *ArrayType) String(pm map[string]string, pkgOverride string) string {
  137. s := "[]"
  138. if at.Len > -1 {
  139. s = fmt.Sprintf("[%d]", at.Len)
  140. }
  141. return s + at.Type.String(pm, pkgOverride)
  142. }
  143. func (at *ArrayType) addImports(im map[string]bool) { at.Type.addImports(im) }
  144. // ChanType is a channel type.
  145. type ChanType struct {
  146. Dir ChanDir // 0, 1 or 2
  147. Type Type
  148. }
  149. func (ct *ChanType) String(pm map[string]string, pkgOverride string) string {
  150. s := ct.Type.String(pm, pkgOverride)
  151. if ct.Dir == RecvDir {
  152. return "<-chan " + s
  153. }
  154. if ct.Dir == SendDir {
  155. return "chan<- " + s
  156. }
  157. return "chan " + s
  158. }
  159. func (ct *ChanType) addImports(im map[string]bool) { ct.Type.addImports(im) }
  160. // ChanDir is a channel direction.
  161. type ChanDir int
  162. const (
  163. RecvDir ChanDir = 1
  164. SendDir ChanDir = 2
  165. )
  166. // FuncType is a function type.
  167. type FuncType struct {
  168. In, Out []*Parameter
  169. Variadic *Parameter // may be nil
  170. }
  171. func (ft *FuncType) String(pm map[string]string, pkgOverride string) string {
  172. args := make([]string, len(ft.In))
  173. for i, p := range ft.In {
  174. args[i] = p.Type.String(pm, pkgOverride)
  175. }
  176. if ft.Variadic != nil {
  177. args = append(args, "..."+ft.Variadic.Type.String(pm, pkgOverride))
  178. }
  179. rets := make([]string, len(ft.Out))
  180. for i, p := range ft.Out {
  181. rets[i] = p.Type.String(pm, pkgOverride)
  182. }
  183. retString := strings.Join(rets, ", ")
  184. if nOut := len(ft.Out); nOut == 1 {
  185. retString = " " + retString
  186. } else if nOut > 1 {
  187. retString = " (" + retString + ")"
  188. }
  189. return "func(" + strings.Join(args, ", ") + ")" + retString
  190. }
  191. func (ft *FuncType) addImports(im map[string]bool) {
  192. for _, p := range ft.In {
  193. p.Type.addImports(im)
  194. }
  195. if ft.Variadic != nil {
  196. ft.Variadic.Type.addImports(im)
  197. }
  198. for _, p := range ft.Out {
  199. p.Type.addImports(im)
  200. }
  201. }
  202. // MapType is a map type.
  203. type MapType struct {
  204. Key, Value Type
  205. }
  206. func (mt *MapType) String(pm map[string]string, pkgOverride string) string {
  207. return "map[" + mt.Key.String(pm, pkgOverride) + "]" + mt.Value.String(pm, pkgOverride)
  208. }
  209. func (mt *MapType) addImports(im map[string]bool) {
  210. mt.Key.addImports(im)
  211. mt.Value.addImports(im)
  212. }
  213. // NamedType is an exported type in a package.
  214. type NamedType struct {
  215. Package string // may be empty
  216. Type string // TODO: should this be typed Type?
  217. }
  218. func (nt *NamedType) String(pm map[string]string, pkgOverride string) string {
  219. // TODO: is this right?
  220. if pkgOverride == nt.Package {
  221. return nt.Type
  222. }
  223. return pm[nt.Package] + "." + nt.Type
  224. }
  225. func (nt *NamedType) addImports(im map[string]bool) {
  226. if nt.Package != "" {
  227. im[nt.Package] = true
  228. }
  229. }
  230. // PointerType is a pointer to another type.
  231. type PointerType struct {
  232. Type Type
  233. }
  234. func (pt *PointerType) String(pm map[string]string, pkgOverride string) string {
  235. return "*" + pt.Type.String(pm, pkgOverride)
  236. }
  237. func (pt *PointerType) addImports(im map[string]bool) { pt.Type.addImports(im) }
  238. // PredeclaredType is a predeclared type such as "int".
  239. type PredeclaredType string
  240. func (pt PredeclaredType) String(pm map[string]string, pkgOverride string) string { return string(pt) }
  241. func (pt PredeclaredType) addImports(im map[string]bool) {}
  242. // The following code is intended to be called by the program generated by ../reflect.go.
  243. func InterfaceFromInterfaceType(it reflect.Type) (*Interface, error) {
  244. if it.Kind() != reflect.Interface {
  245. return nil, fmt.Errorf("%v is not an interface", it)
  246. }
  247. intf := &Interface{}
  248. for i := 0; i < it.NumMethod(); i++ {
  249. mt := it.Method(i)
  250. // TODO: need to skip unexported methods? or just raise an error?
  251. m := &Method{
  252. Name: mt.Name,
  253. }
  254. var err error
  255. m.In, m.Variadic, m.Out, err = funcArgsFromType(mt.Type)
  256. if err != nil {
  257. return nil, err
  258. }
  259. intf.Methods = append(intf.Methods, m)
  260. }
  261. return intf, nil
  262. }
  263. // t's Kind must be a reflect.Func.
  264. func funcArgsFromType(t reflect.Type) (in []*Parameter, variadic *Parameter, out []*Parameter, err error) {
  265. nin := t.NumIn()
  266. if t.IsVariadic() {
  267. nin--
  268. }
  269. var p *Parameter
  270. for i := 0; i < nin; i++ {
  271. p, err = parameterFromType(t.In(i))
  272. if err != nil {
  273. return
  274. }
  275. in = append(in, p)
  276. }
  277. if t.IsVariadic() {
  278. p, err = parameterFromType(t.In(nin).Elem())
  279. if err != nil {
  280. return
  281. }
  282. variadic = p
  283. }
  284. for i := 0; i < t.NumOut(); i++ {
  285. p, err = parameterFromType(t.Out(i))
  286. if err != nil {
  287. return
  288. }
  289. out = append(out, p)
  290. }
  291. return
  292. }
  293. func parameterFromType(t reflect.Type) (*Parameter, error) {
  294. tt, err := typeFromType(t)
  295. if err != nil {
  296. return nil, err
  297. }
  298. return &Parameter{Type: tt}, nil
  299. }
  300. var errorType = reflect.TypeOf((*error)(nil)).Elem()
  301. var byteType = reflect.TypeOf(byte(0))
  302. func typeFromType(t reflect.Type) (Type, error) {
  303. // Hack workaround for https://golang.org/issue/3853.
  304. // This explicit check should not be necessary.
  305. if t == byteType {
  306. return PredeclaredType("byte"), nil
  307. }
  308. if imp := t.PkgPath(); imp != "" {
  309. // PkgPath might return a path that includes "vendor"
  310. // These paths do not compile, so we need to remove everything
  311. // up to and including "/vendor/"
  312. // see https://github.com/golang/go/issues/12019
  313. if i := strings.LastIndex(imp, "/vendor/"); i != -1 {
  314. imp = imp[i+len("/vendor/"):]
  315. }
  316. return &NamedType{
  317. Package: imp,
  318. Type: t.Name(),
  319. }, nil
  320. }
  321. // only unnamed or predeclared types after here
  322. // Lots of types have element types. Let's do the parsing and error checking for all of them.
  323. var elemType Type
  324. switch t.Kind() {
  325. case reflect.Array, reflect.Chan, reflect.Map, reflect.Ptr, reflect.Slice:
  326. var err error
  327. elemType, err = typeFromType(t.Elem())
  328. if err != nil {
  329. return nil, err
  330. }
  331. }
  332. switch t.Kind() {
  333. case reflect.Array:
  334. return &ArrayType{
  335. Len: t.Len(),
  336. Type: elemType,
  337. }, nil
  338. case reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
  339. reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
  340. reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128, reflect.String:
  341. return PredeclaredType(t.Kind().String()), nil
  342. case reflect.Chan:
  343. var dir ChanDir
  344. switch t.ChanDir() {
  345. case reflect.RecvDir:
  346. dir = RecvDir
  347. case reflect.SendDir:
  348. dir = SendDir
  349. }
  350. return &ChanType{
  351. Dir: dir,
  352. Type: elemType,
  353. }, nil
  354. case reflect.Func:
  355. in, variadic, out, err := funcArgsFromType(t)
  356. if err != nil {
  357. return nil, err
  358. }
  359. return &FuncType{
  360. In: in,
  361. Out: out,
  362. Variadic: variadic,
  363. }, nil
  364. case reflect.Interface:
  365. // Two special interfaces.
  366. if t.NumMethod() == 0 {
  367. return PredeclaredType("interface{}"), nil
  368. }
  369. if t == errorType {
  370. return PredeclaredType("error"), nil
  371. }
  372. case reflect.Map:
  373. kt, err := typeFromType(t.Key())
  374. if err != nil {
  375. return nil, err
  376. }
  377. return &MapType{
  378. Key: kt,
  379. Value: elemType,
  380. }, nil
  381. case reflect.Ptr:
  382. return &PointerType{
  383. Type: elemType,
  384. }, nil
  385. case reflect.Slice:
  386. return &ArrayType{
  387. Len: -1,
  388. Type: elemType,
  389. }, nil
  390. case reflect.Struct:
  391. if t.NumField() == 0 {
  392. return PredeclaredType("struct{}"), nil
  393. }
  394. }
  395. // TODO: Struct, UnsafePointer
  396. return nil, fmt.Errorf("can't yet turn %v (%v) into a model.Type", t, t.Kind())
  397. }