Skip to content

Commit 5d48467

Browse files
committedOct 9, 2023
Add exclude-regex to config
Addresses #718
1 parent 9d79f3a commit 5d48467

File tree

4 files changed

+127
-9
lines changed

4 files changed

+127
-9
lines changed
 

‎docs/configuration.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,10 @@ Parameter Descriptions
6767
| `disable-version-string` | :fontawesome-solid-x: | `#!yaml false` | Disable the version string in the generated mock files. |
6868
| `dry-run` | :fontawesome-solid-x: | `#!yaml false` | Print the actions that would be taken, but don't perform the actions. |
6969
| `exclude` | :fontawesome-solid-x: | `#!yaml []` | Specify subpackages to exclude when using `#!yaml recursive: True` |
70+
| `exclude-regex` | :fontawesome-solid-x: | `#!yaml ""` | When set along with `include-regex`, then interfaces which match `include-regex` but also match `exclude-regex` will not be generated. If `all` is set, or if `include-regex` is not set, then `exclude-regex` has no effect. |
7071
| `filename` | :fontawesome-solid-check: | `#!yaml "mock_{{.InterfaceName}}.go"` | The name of the file the mock will reside in. |
7172
| `include-auto-generated` | :fontawesome-solid-x: | `#!yaml true` | Set to `#!yaml false` if you need mockery to skip auto-generated files during its recursive package discovery. When set to `#!yaml true`, mockery includes auto-generated files when determining if a particular directory is an importable package. |
72-
| `include-regex` | :fontawesome-solid-x: | `#!yaml ""` | When set, only interface names that match the expression will be generated. This setting is ignored if `all: True` is specified in the configuration |
73+
| `include-regex` | :fontawesome-solid-x: | `#!yaml ""` | When set, only interface names that match the expression will be generated. This setting is ignored if `all: True` is specified in the configuration. To further refine the interfaces generated, use `exclude-regex`. |
7374
| `inpackage` | :fontawesome-solid-x: | `#!yaml false` | When generating mocks alongside the original interfaces, you must specify `inpackage: True` to inform mockery that the mock is being placed in the same package as the original interface. |
7475
| `mockname` | :fontawesome-solid-check: | `#!yaml "Mock{{.InterfaceName}}"` | The name of the generated mock. |
7576
| `outpkg` | :fontawesome-solid-check: | `#!yaml "{{.PackageName}}"` | Use `outpkg` to specify the package name of the generated mocks. |

‎docs/features.md

+14-1
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,21 @@ packages:
193193
include-regex: ".*Client"
194194
```
195195

196+
To further refine matched interfaces, you can also use `exclude-regex`. If an interface matches both `include-regex` and `exclude-regex` then it will not be generated. For example, to generate all interfaces except those ending in `Func`:
197+
198+
```yaml
199+
packages:
200+
github.com/user/project:
201+
config:
202+
recursive: true
203+
include-regex: ".*"
204+
exclude-regex: ".*Func"
205+
```
206+
207+
You can only use `exclude-regex` with `include-regex`. If set by itself, `exclude-regex` has no effect.
208+
196209
??? note "all: true"
197-
Using `all: true` will override `include-regex` and issue a warning.
210+
Using `all: true` will override `include-regex` (and `exclude-regex`) and issue a warning.
198211

199212
Mock Constructors
200213
-----------------

‎pkg/config/config.go

+23-4
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ type Config struct {
4141
DisableConfigSearch bool `mapstructure:"disable-config-search"`
4242
DisableVersionString bool `mapstructure:"disable-version-string"`
4343
DryRun bool `mapstructure:"dry-run"`
44+
ExcludeRegex string `mapstructure:"exclude-regex"`
4445
Exported bool `mapstructure:"exported"`
4546
FileName string `mapstructure:"filename"`
4647
IncludeAutoGenerated bool `mapstructure:"include-auto-generated"`
@@ -271,19 +272,37 @@ func (c *Config) ShouldGenerateInterface(ctx context.Context, packageName, inter
271272
}
272273
_, interfaceExists := interfacesSection[interfaceName]
273274

274-
var matchedByRegex bool
275+
matchedByRegex := false
275276
if pkgConfig.IncludeRegex != "" {
276277
if pkgConfig.All {
277278
log := zerolog.Ctx(ctx)
278-
log.Warn().Msg("interface config has both `all` and `include-regex` set. `include-regex` will be ignored")
279+
log.Warn().Msg("interface config has both `all` and `include-regex` set: `include-regex` will be ignored")
279280
} else {
280281
matchedByRegex, err = regexp.MatchString(pkgConfig.IncludeRegex, interfaceName)
281282
if err != nil {
282-
return false, err
283+
return false, fmt.Errorf("evaluating `include-regex`: %w", err)
283284
}
284285
}
285286
}
286-
return pkgConfig.All || interfaceExists || matchedByRegex, nil
287+
excludedByRegex := false
288+
if pkgConfig.ExcludeRegex != "" {
289+
if pkgConfig.All {
290+
log := zerolog.Ctx(ctx)
291+
log.Warn().Msg("interface config has both `all` and `exclude-regex` set: `exclude-regex` will be ignored")
292+
} else if pkgConfig.IncludeRegex == "" {
293+
log := zerolog.Ctx(ctx)
294+
log.Warn().Msg("interface config has `exclude-regex` set but not `include-regex`: `exclude-regex` will be ignored")
295+
} else {
296+
excludedByRegex, err = regexp.MatchString(pkgConfig.ExcludeRegex, interfaceName)
297+
if err != nil {
298+
return false, fmt.Errorf("evaluating `exclude-regex`: %w", err)
299+
}
300+
if excludedByRegex {
301+
matchedByRegex = false
302+
}
303+
}
304+
}
305+
return pkgConfig.All || interfaceExists || (matchedByRegex && !excludedByRegex), nil
287306
}
288307

289308
func (c *Config) getInterfacesSection(ctx context.Context, packageName string) (map[string]any, error) {

‎pkg/config/config_test.go

+88-3
Original file line numberDiff line numberDiff line change
@@ -609,7 +609,7 @@ func TestConfig_ShouldGenerateInterface(t *testing.T) {
609609
want: true,
610610
},
611611
{
612-
name: "should generate using included-regex",
612+
name: "should generate using include-regex",
613613
c: &Config{
614614
Packages: map[string]interface{}{
615615
"some_package": map[string]interface{}{
@@ -622,7 +622,7 @@ func TestConfig_ShouldGenerateInterface(t *testing.T) {
622622
want: true,
623623
},
624624
{
625-
name: "should generate when using all and included-regex doesn't match",
625+
name: "should generate when using all and include-regex doesn't match",
626626
c: &Config{
627627
Packages: map[string]interface{}{
628628
"some_package": map[string]interface{}{
@@ -636,7 +636,7 @@ func TestConfig_ShouldGenerateInterface(t *testing.T) {
636636
want: true,
637637
},
638638
{
639-
name: "should not generate when included-regex doesn't match",
639+
name: "should not generate when include-regex doesn't match",
640640
c: &Config{
641641
Packages: map[string]interface{}{
642642
"some_package": map[string]interface{}{
@@ -648,6 +648,91 @@ func TestConfig_ShouldGenerateInterface(t *testing.T) {
648648
},
649649
want: false,
650650
},
651+
{
652+
name: "should not generate when include-regex and exclude-regex both match",
653+
c: &Config{
654+
Packages: map[string]interface{}{
655+
"some_package": map[string]interface{}{
656+
"config": map[string]interface{}{
657+
"include-regex": ".*Interface",
658+
"exclude-regex": "Some.*",
659+
},
660+
},
661+
},
662+
},
663+
want: false,
664+
},
665+
{
666+
name: "should generate when include-regex matches but not exclude-regex",
667+
c: &Config{
668+
Packages: map[string]interface{}{
669+
"some_package": map[string]interface{}{
670+
"config": map[string]interface{}{
671+
"include-regex": ".*Interface",
672+
"exclude-regex": "Foo.*",
673+
},
674+
},
675+
},
676+
},
677+
want: true,
678+
},
679+
{
680+
name: "should not generate when neither include-regex nor exclude-regex match",
681+
c: &Config{
682+
Packages: map[string]interface{}{
683+
"some_package": map[string]interface{}{
684+
"config": map[string]interface{}{
685+
"include-regex": ".*XInterface",
686+
"exclude-regex": "Foo.*",
687+
},
688+
},
689+
},
690+
},
691+
want: false,
692+
},
693+
{
694+
name: "should not generate when exclude-regex doesn't match but include-regex isn't set",
695+
c: &Config{
696+
Packages: map[string]interface{}{
697+
"some_package": map[string]interface{}{
698+
"config": map[string]interface{}{
699+
"exclude-regex": "Foo.*",
700+
},
701+
},
702+
},
703+
},
704+
want: false,
705+
},
706+
{
707+
name: "should generate when using all and exclude-regex matches",
708+
c: &Config{
709+
Packages: map[string]interface{}{
710+
"some_package": map[string]interface{}{
711+
"config": map[string]interface{}{
712+
"all": true,
713+
"exclude-regex": ".*Interface",
714+
},
715+
},
716+
},
717+
},
718+
want: true,
719+
},
720+
{
721+
name: "should generate when interface is selected and exclude-regex matches",
722+
c: &Config{
723+
Packages: map[string]interface{}{
724+
"some_package": map[string]interface{}{
725+
"interfaces": map[string]interface{}{
726+
"SomeInterface": struct{}{},
727+
},
728+
"config": map[string]interface{}{
729+
"exclude-regex": ".*Interface",
730+
},
731+
},
732+
},
733+
},
734+
want: true,
735+
},
651736
}
652737
for _, tt := range tests {
653738
t.Run(tt.name, func(t *testing.T) {

0 commit comments

Comments
 (0)
Please sign in to comment.