-
Notifications
You must be signed in to change notification settings - Fork 7
/
mockery.go
153 lines (130 loc) · 4.52 KB
/
mockery.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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package generate
import (
"context"
"fmt"
"os"
"regexp"
"runtime/pprof"
"strings"
"emperror.dev/errors"
"github.com/spf13/cobra"
"github.com/vektra/mockery/v2/pkg"
)
type mockeryOptions struct {
fName string
fPrint bool
fOutput string
fOutpkg string
fDir string
fRecursive bool
fAll bool
fIP bool
fTO bool
fCase string
fNote string
fProfile string
fkeepTree bool
buildTags string
}
// NewMockeryCommand returns a cobra command for generating a mock using mockery.
func NewMockeryCommand() *cobra.Command {
var options mockeryOptions
cmd := &cobra.Command{
Use: "mockery",
Short: "Generate a mock from an interface using Mockery",
Long: `This command is a drop-in replacement for Mockery.
It uses the original code base under https://github.com/vektra/mockery
The command accepts the same arguments as the original executable.
`,
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
cmd.SilenceErrors = true
cmd.SilenceUsage = true
return runMockery(options)
},
}
flags := cmd.Flags()
flags.StringVar(&options.fName, "name", "", "name or matching regular expression of interface to generate mock for")
flags.BoolVar(&options.fPrint, "print", false, "print the generated mock to stdout")
flags.StringVar(&options.fOutput, "output", "./mocks", "directory to write mocks to")
flags.StringVar(&options.fOutpkg, "outpkg", "mocks", "name of generated package")
flags.StringVar(&options.fDir, "dir", ".", "directory to search for interfaces")
flags.BoolVar(&options.fRecursive, "recursive", false, "recurse search into sub-directories")
flags.BoolVar(&options.fAll, "all", false, "generates mocks for all found interfaces in all sub-directories")
flags.BoolVar(&options.fIP, "inpkg", false, "generate a mock that goes inside the original package")
flags.BoolVar(&options.fTO, "testonly", false, "generate a mock in a _test.go file")
flags.StringVar(&options.fCase, "case", "camel", "name the mocked file using casing convention [camel, snake, underscore]") // nolint: lll
flags.StringVar(&options.fNote, "note", "", "comment to insert into prologue of each generated file")
flags.StringVar(&options.fProfile, "cpuprofile", "", "write cpu profile to file")
flags.BoolVar(&options.fkeepTree, "keeptree", false, "keep the tree structure of the original interface files into a different repository. Must be used with XX") // nolint: lll
flags.StringVar(&options.buildTags, "tags", "", "space-separated list of additional build tags to use")
return cmd
}
const regexMetadataChars = "\\.+*?()|[]{}^$"
func runMockery(options mockeryOptions) error {
var recursive bool
var filter *regexp.Regexp
var err error
var limitOne bool
// nolint: gocritic
if options.fName != "" && options.fAll {
return errors.New("specify -name or -all, but not both")
} else if options.fName != "" {
recursive = options.fRecursive
if strings.ContainsAny(options.fName, regexMetadataChars) {
if filter, err = regexp.Compile(options.fName); err != nil {
return errors.New("invalid regular expression provided to -name")
}
} else {
filter = regexp.MustCompile(fmt.Sprintf("^%s$", options.fName))
limitOne = true
}
} else if options.fAll {
recursive = true
filter = regexp.MustCompile(".*")
} else {
return errors.New("use -name to specify the name of the interface or -all for all interfaces found")
}
if options.fkeepTree {
options.fIP = false
}
if options.fProfile != "" {
f, err := os.Create(options.fProfile)
if err != nil {
return err
}
_ = pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile()
}
var osp pkg.OutputStreamProvider
if options.fPrint {
osp = &pkg.StdoutStreamProvider{}
} else {
osp = &pkg.FileOutputStreamProvider{
BaseDir: options.fOutput,
InPackage: options.fIP,
TestOnly: options.fTO,
Case: options.fCase,
KeepTree: options.fkeepTree,
KeepTreeOriginalDirectory: options.fDir,
}
}
visitor := &pkg.GeneratorVisitor{
InPackage: options.fIP,
Note: options.fNote,
Osp: osp,
PackageName: options.fOutpkg,
}
walker := pkg.Walker{
BaseDir: options.fDir,
Recursive: recursive,
Filter: filter,
LimitOne: limitOne,
BuildTags: strings.Split(options.buildTags, " "),
}
generated := walker.Walk(context.Background(), visitor)
if options.fName != "" && !generated {
return errors.Errorf("unable to find %s in any go files under this path\n", options.fName)
}
return nil
}