-
Notifications
You must be signed in to change notification settings - Fork 1
/
interface.go
131 lines (114 loc) · 4.32 KB
/
interface.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package gomocker
import (
"fmt"
"github.com/dave/jennifer/jen"
"github.com/jauhararifin/gotype"
)
type interfaceMockerGenerator struct {
funcMockerNamer FuncMockerNamer
interfaceMockerNamer InterfaceMockerNamer
}
func (f *interfaceMockerGenerator) GenerateInterfaceMocker(name string, interfaceType gotype.InterfaceType) jen.Code {
generator := &interfaceMockerGeneratorHelper{
interfaceName: name,
interfaceType: interfaceType,
funcMockerNamer: f.funcMockerNamer,
interfaceMockerNamer: f.interfaceMockerNamer,
}
return generator.generate()
}
type interfaceMockerGeneratorHelper struct {
interfaceName string
interfaceType gotype.InterfaceType
interfaceMockerNamer InterfaceMockerNamer
funcMockerNamer FuncMockerNamer
funcMockedGenerators []*funcMockerGeneratorHelper
}
func (s *interfaceMockerGeneratorHelper) generate() jen.Code {
if s.interfaceType.Methods == nil {
panic(fmt.Errorf("cannot mock an empty interface"))
}
for _, method := range s.interfaceType.Methods {
// TODO (jauhararifin): maybe can make the funcMockerGeneratorHelper more modular
s.funcMockedGenerators = append(s.funcMockedGenerators, &funcMockerGeneratorHelper{
funcName: s.getFuncAlias(method.Name),
funcType: method.Func,
mockerNamer: s.funcMockerNamer,
withConstructor: false,
})
}
return jen.CustomFunc(jen.Options{}, func(g *jen.Group) {
g.Add(s.generateInterfaceMockerStruct()).Line().Line()
g.Add(s.generateMockedInterfaceStruct()).Line().Line()
g.Add(s.generateMockedInterfaceImpl()).Line().Line()
g.Add(s.generateInterfaceMockerConstructor()).Line().Line()
for i := 0; i < len(s.interfaceType.Methods); i++ {
g.Add(s.funcMockedGenerators[i].generate()).Line().Line()
}
})
}
func (s *interfaceMockerGeneratorHelper) generateInterfaceMockerStruct() jen.Code {
return jen.Type().Id(s.getMockerStructName()).StructFunc(func(g *jen.Group) {
for _, method := range s.interfaceType.Methods {
g.Id(method.Name).Op("*").Id(s.funcMockerNamer.MockerName(s.getFuncAlias(method.Name)))
}
})
}
func (s *interfaceMockerGeneratorHelper) getFuncAlias(funcName string) string {
return s.interfaceMockerNamer.FunctionAliasName(s.interfaceName, funcName)
}
func (s *interfaceMockerGeneratorHelper) getMockerStructName() string {
return s.interfaceMockerNamer.MockerName(s.interfaceName)
}
func (s *interfaceMockerGeneratorHelper) generateMockedInterfaceStruct() jen.Code {
return jen.Type().Id(s.getMockedStructName()).Struct(jen.Id("mocker").Op("*").Id(s.getMockerStructName()))
}
func (s *interfaceMockerGeneratorHelper) getMockedStructName() string {
return s.interfaceMockerNamer.MockedName(s.interfaceName)
}
func (s *interfaceMockerGeneratorHelper) generateMockedInterfaceImpl() jen.Code {
return jen.CustomFunc(jen.Options{}, func(g *jen.Group) {
for i, method := range s.interfaceType.Methods {
methodName := method.Name
g.Func().
Params(jen.Id("m").Op("*").Id(s.getMockedStructName())).
Id(methodName).
Params(s.funcMockedGenerators[i].generateInputParamSignature(true)...).
Params(s.funcMockedGenerators[i].generateOutputParamSignature(true)...).
BlockFunc(func(g *jen.Group) {
if hasOutput := len(method.Func.Outputs) > 0; hasOutput {
g.Return(jen.Id("m").Dot("mocker").Dot(methodName).Dot("Call").CallFunc(
s.funcMockedGenerators[i].generateInputListWithEllipsis,
))
} else {
g.Id("m").Dot("mocker").Dot(methodName).Dot("Call").CallFunc(
s.funcMockedGenerators[i].generateInputListWithEllipsis,
)
}
})
g.Line()
}
g.Line()
})
}
func (s *interfaceMockerGeneratorHelper) generateInterfaceMockerConstructor() jen.Code {
return jen.Func().
Id(s.getConstructorName()).
Params().
Params(
jen.Op("*").Id(s.getMockedStructName()),
jen.Op("*").Id(s.getMockerStructName()),
).
Block(
jen.Id("m").Op(":=").Op("&").Id(s.getMockerStructName()).ValuesFunc(func(g *jen.Group) {
for _, method := range s.interfaceType.Methods {
name := method.Name
g.Id(name).Op(":").Op("&").Id(s.funcMockerNamer.MockerName(s.getFuncAlias(name))).Values()
}
}),
jen.Return(jen.Op("&").Id(s.getMockedStructName()).Values(jen.Id("m")), jen.Id("m")),
)
}
func (s *interfaceMockerGeneratorHelper) getConstructorName() string {
return s.interfaceMockerNamer.ConstructorName(s.interfaceName)
}