Skip to content

Commit

Permalink
Add exclude-regex to config
Browse files Browse the repository at this point in the history
Addresses #718
  • Loading branch information
kbolino committed Oct 9, 2023
1 parent 9d79f3a commit 5d48467
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 9 deletions.
3 changes: 2 additions & 1 deletion docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,10 @@ Parameter Descriptions
| `disable-version-string` | :fontawesome-solid-x: | `#!yaml false` | Disable the version string in the generated mock files. |
| `dry-run` | :fontawesome-solid-x: | `#!yaml false` | Print the actions that would be taken, but don't perform the actions. |
| `exclude` | :fontawesome-solid-x: | `#!yaml []` | Specify subpackages to exclude when using `#!yaml recursive: True` |
| `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. |
| `filename` | :fontawesome-solid-check: | `#!yaml "mock_{{.InterfaceName}}.go"` | The name of the file the mock will reside in. |
| `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. |
| `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 |
| `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`. |
| `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. |
| `mockname` | :fontawesome-solid-check: | `#!yaml "Mock{{.InterfaceName}}"` | The name of the generated mock. |
| `outpkg` | :fontawesome-solid-check: | `#!yaml "{{.PackageName}}"` | Use `outpkg` to specify the package name of the generated mocks. |
Expand Down
15 changes: 14 additions & 1 deletion docs/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,21 @@ packages:
include-regex: ".*Client"
```

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`:

```yaml
packages:
github.com/user/project:
config:
recursive: true
include-regex: ".*"
exclude-regex: ".*Func"
```

You can only use `exclude-regex` with `include-regex`. If set by itself, `exclude-regex` has no effect.

??? note "all: true"
Using `all: true` will override `include-regex` and issue a warning.
Using `all: true` will override `include-regex` (and `exclude-regex`) and issue a warning.

Mock Constructors
-----------------
Expand Down
27 changes: 23 additions & 4 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ type Config struct {
DisableConfigSearch bool `mapstructure:"disable-config-search"`
DisableVersionString bool `mapstructure:"disable-version-string"`
DryRun bool `mapstructure:"dry-run"`
ExcludeRegex string `mapstructure:"exclude-regex"`
Exported bool `mapstructure:"exported"`
FileName string `mapstructure:"filename"`
IncludeAutoGenerated bool `mapstructure:"include-auto-generated"`
Expand Down Expand Up @@ -271,19 +272,37 @@ func (c *Config) ShouldGenerateInterface(ctx context.Context, packageName, inter
}
_, interfaceExists := interfacesSection[interfaceName]

var matchedByRegex bool
matchedByRegex := false
if pkgConfig.IncludeRegex != "" {
if pkgConfig.All {
log := zerolog.Ctx(ctx)
log.Warn().Msg("interface config has both `all` and `include-regex` set. `include-regex` will be ignored")
log.Warn().Msg("interface config has both `all` and `include-regex` set: `include-regex` will be ignored")
} else {
matchedByRegex, err = regexp.MatchString(pkgConfig.IncludeRegex, interfaceName)
if err != nil {
return false, err
return false, fmt.Errorf("evaluating `include-regex`: %w", err)
}
}
}
return pkgConfig.All || interfaceExists || matchedByRegex, nil
excludedByRegex := false
if pkgConfig.ExcludeRegex != "" {
if pkgConfig.All {
log := zerolog.Ctx(ctx)
log.Warn().Msg("interface config has both `all` and `exclude-regex` set: `exclude-regex` will be ignored")
} else if pkgConfig.IncludeRegex == "" {
log := zerolog.Ctx(ctx)
log.Warn().Msg("interface config has `exclude-regex` set but not `include-regex`: `exclude-regex` will be ignored")
} else {
excludedByRegex, err = regexp.MatchString(pkgConfig.ExcludeRegex, interfaceName)
if err != nil {
return false, fmt.Errorf("evaluating `exclude-regex`: %w", err)
}
if excludedByRegex {
matchedByRegex = false
}
}
}
return pkgConfig.All || interfaceExists || (matchedByRegex && !excludedByRegex), nil
}

func (c *Config) getInterfacesSection(ctx context.Context, packageName string) (map[string]any, error) {
Expand Down
91 changes: 88 additions & 3 deletions pkg/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -609,7 +609,7 @@ func TestConfig_ShouldGenerateInterface(t *testing.T) {
want: true,
},
{
name: "should generate using included-regex",
name: "should generate using include-regex",
c: &Config{
Packages: map[string]interface{}{
"some_package": map[string]interface{}{
Expand All @@ -622,7 +622,7 @@ func TestConfig_ShouldGenerateInterface(t *testing.T) {
want: true,
},
{
name: "should generate when using all and included-regex doesn't match",
name: "should generate when using all and include-regex doesn't match",
c: &Config{
Packages: map[string]interface{}{
"some_package": map[string]interface{}{
Expand All @@ -636,7 +636,7 @@ func TestConfig_ShouldGenerateInterface(t *testing.T) {
want: true,
},
{
name: "should not generate when included-regex doesn't match",
name: "should not generate when include-regex doesn't match",
c: &Config{
Packages: map[string]interface{}{
"some_package": map[string]interface{}{
Expand All @@ -648,6 +648,91 @@ func TestConfig_ShouldGenerateInterface(t *testing.T) {
},
want: false,
},
{
name: "should not generate when include-regex and exclude-regex both match",
c: &Config{
Packages: map[string]interface{}{
"some_package": map[string]interface{}{
"config": map[string]interface{}{
"include-regex": ".*Interface",
"exclude-regex": "Some.*",
},
},
},
},
want: false,
},
{
name: "should generate when include-regex matches but not exclude-regex",
c: &Config{
Packages: map[string]interface{}{
"some_package": map[string]interface{}{
"config": map[string]interface{}{
"include-regex": ".*Interface",
"exclude-regex": "Foo.*",
},
},
},
},
want: true,
},
{
name: "should not generate when neither include-regex nor exclude-regex match",
c: &Config{
Packages: map[string]interface{}{
"some_package": map[string]interface{}{
"config": map[string]interface{}{
"include-regex": ".*XInterface",
"exclude-regex": "Foo.*",
},
},
},
},
want: false,
},
{
name: "should not generate when exclude-regex doesn't match but include-regex isn't set",
c: &Config{
Packages: map[string]interface{}{
"some_package": map[string]interface{}{
"config": map[string]interface{}{
"exclude-regex": "Foo.*",
},
},
},
},
want: false,
},
{
name: "should generate when using all and exclude-regex matches",
c: &Config{
Packages: map[string]interface{}{
"some_package": map[string]interface{}{
"config": map[string]interface{}{
"all": true,
"exclude-regex": ".*Interface",
},
},
},
},
want: true,
},
{
name: "should generate when interface is selected and exclude-regex matches",
c: &Config{
Packages: map[string]interface{}{
"some_package": map[string]interface{}{
"interfaces": map[string]interface{}{
"SomeInterface": struct{}{},
},
"config": map[string]interface{}{
"exclude-regex": ".*Interface",
},
},
},
},
want: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down

0 comments on commit 5d48467

Please sign in to comment.