Skip to content

Commit b720c05

Browse files
committed
add -out-dir argument
1 parent 6b37b7c commit b720c05

File tree

3 files changed

+127
-13
lines changed

3 files changed

+127
-13
lines changed

main.go

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ var Version string = "dev"
1818

1919
type userFlags struct {
2020
outFile string
21+
outDir string
2122
pkgName string
2223
formatter string
2324
stubImpl bool
@@ -30,6 +31,7 @@ type userFlags struct {
3031
func main() {
3132
var flags userFlags
3233
flag.StringVar(&flags.outFile, "out", "", "output file (default stdout)")
34+
flag.StringVar(&flags.outDir, "out-dir", "", "output dir (exclusive with -out)")
3335
flag.StringVar(&flags.pkgName, "pkg", "", "package name (default will infer)")
3436
flag.StringVar(&flags.formatter, "fmt", "", "go pretty-printer: gofmt, goimports or noop (default gofmt)")
3537
flag.BoolVar(&flags.stubImpl, "stub", false,
@@ -76,12 +78,6 @@ func run(flags userFlags) error {
7678
}
7779
}
7880

79-
var buf bytes.Buffer
80-
var out io.Writer = os.Stdout
81-
if flags.outFile != "" {
82-
out = &buf
83-
}
84-
8581
srcDir, args := flags.args[0], flags.args[1:]
8682
m, err := moq.New(moq.Config{
8783
SrcDir: srcDir,
@@ -95,19 +91,52 @@ func run(flags userFlags) error {
9591
return err
9692
}
9793

98-
if err = m.Mock(out, args...); err != nil {
94+
switch {
95+
case flags.outDir != "" && flags.outFile != "":
96+
return errors.New("use only one from -out and -out-dir arguments")
97+
case flags.outDir != "":
98+
return mockToDir(m, flags.outDir, args...)
99+
case flags.outFile != "":
100+
return mockToFile(m, flags.outFile, args...)
101+
default:
102+
// mock to stdout
103+
return m.Mock(os.Stdout, args...)
104+
}
105+
}
106+
107+
func mockToDir(m *moq.Mocker, outDir string, args ...string) error {
108+
if err := os.MkdirAll(outDir, 0o750); err != nil {
99109
return err
100110
}
101111

102-
if flags.outFile == "" {
103-
return nil
112+
var buf bytes.Buffer
113+
for _, arg := range args {
114+
if err := m.Mock(&buf, arg); err != nil {
115+
return err
116+
}
117+
118+
filename := filepath.Join(outDir, m.FileMockName(arg))
119+
if err := ioutil.WriteFile(filename, buf.Bytes(), 0o600); err != nil {
120+
return err
121+
}
122+
123+
buf.Reset()
104124
}
105125

106-
// create the file
107-
err = os.MkdirAll(filepath.Dir(flags.outFile), 0o750)
108-
if err != nil {
126+
return nil
127+
}
128+
129+
func mockToFile(m *moq.Mocker, outFile string, args ...string) error {
130+
var buf bytes.Buffer
131+
var out io.Writer = &buf
132+
133+
if err := m.Mock(out, args...); err != nil {
134+
return err
135+
}
136+
137+
if err := os.MkdirAll(filepath.Dir(outFile), 0o750); err != nil {
109138
return err
110139
}
111140

112-
return ioutil.WriteFile(flags.outFile, buf.Bytes(), 0o600)
141+
return ioutil.WriteFile(outFile, buf.Bytes(), 0o600)
113142
}

pkg/moq/moq.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"go/types"
88
"io"
99
"strings"
10+
"unicode"
1011

1112
"github.com/matryer/moq/internal/registry"
1213
"github.com/matryer/moq/internal/template"
@@ -114,6 +115,19 @@ func (m *Mocker) Mock(w io.Writer, namePairs ...string) error {
114115
return nil
115116
}
116117

118+
// FileMockName generates file name for mock from interface
119+
func (m *Mocker) FileMockName(namePair string) string {
120+
ifaceName, mockName := parseInterfaceName(namePair)
121+
122+
var mockFile string
123+
if strings.HasPrefix(mockName, ifaceName) {
124+
mockFile = toSnakeCase(ifaceName)
125+
} else {
126+
mockFile = toSnakeCase(mockName)
127+
}
128+
return mockFile + ".go"
129+
}
130+
117131
func (m *Mocker) typeParams(tparams *types.TypeParamList) []template.TypeParamData {
118132
var tpd []template.TypeParamData
119133
if tparams == nil {
@@ -210,3 +224,49 @@ func parseInterfaceName(namePair string) (ifaceName, mockName string) {
210224
ifaceName = parts[0]
211225
return ifaceName, ifaceName + "Mock"
212226
}
227+
228+
func toSnakeCase(name string) string {
229+
var buf bytes.Buffer
230+
231+
fUpper := -1
232+
for i, r := range name {
233+
if unicode.IsUpper(r) {
234+
if fUpper < 0 {
235+
fUpper = i
236+
}
237+
continue
238+
}
239+
240+
if fUpper < 0 {
241+
// just next low rune
242+
buf.WriteRune(r)
243+
continue
244+
}
245+
246+
if fUpper == 0 && name[0] == 'I' {
247+
// special case for interface preffix
248+
buf.WriteString("i")
249+
fUpper++
250+
}
251+
if fUpper > 0 {
252+
buf.WriteRune('_')
253+
}
254+
if i-fUpper >= 2 {
255+
buf.WriteString(strings.ToLower(name[fUpper : i-1]))
256+
buf.WriteRune('_')
257+
}
258+
259+
buf.WriteString(strings.ToLower(name[i-1 : i]))
260+
buf.WriteRune(r)
261+
fUpper = -1
262+
}
263+
264+
if fUpper > 0 {
265+
buf.WriteRune('_')
266+
}
267+
268+
if fUpper >= 0 {
269+
buf.WriteString(strings.ToLower(name[fUpper:]))
270+
}
271+
return buf.String()
272+
}

pkg/moq/moq_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,31 @@ func TestMockError(t *testing.T) {
699699
}
700700
}
701701

702+
func TestToSnakeCase(t *testing.T) {
703+
cases := []struct {
704+
arg, want string
705+
}{
706+
{"allcased", "allcased"},
707+
{"ALLUPPER", "allupper"},
708+
{"ICache", "i_cache"},
709+
{"IJournalService", "i_journal_service"},
710+
{"ITJournalService", "i_t_journal_service"},
711+
{"IAddressAPI", "i_address_api"},
712+
{"IABClient", "i_ab_client"},
713+
{"APIClient", "api_client"},
714+
{"IAPIClient", "i_api_client"},
715+
}
716+
717+
for _, tc := range cases {
718+
t.Run(tc.arg, func(t *testing.T) {
719+
actual := toSnakeCase(tc.arg)
720+
if actual != tc.want {
721+
t.Errorf("expect: %v, actual: %v", tc.want, actual)
722+
}
723+
})
724+
}
725+
}
726+
702727
// normalize normalizes \r\n (windows) and \r (mac)
703728
// into \n (unix)
704729
func normalize(d []byte) []byte {

0 commit comments

Comments
 (0)