Skip to content

Commit

Permalink
feat(v3): Warning for nonexistent mocks (#911)
Browse files Browse the repository at this point in the history
* feat(v3): Warning for nonexistent mocks

* refactor: wording of error message & package vars
  • Loading branch information
ravsii authored Feb 4, 2025
1 parent 422f170 commit 0c8aecf
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 15 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ coverage.txt
site/
.task/
tools/tools
*.lua
19 changes: 10 additions & 9 deletions .mockery.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,13 @@ packages:
interfaces:
RType:
configs:
- {}
- mockname: RTypeReplaced1
replace-type:
github.com/vektra/mockery/v3/internal/fixtures/example_project/replace_type/rti/rt1:
RType1:
pkg-path: github.com/vektra/mockery/v3/internal/fixtures/example_project/replace_type/rti/rt2
type-name: RType2

- {}
- mockname: RTypeReplaced1
replace-type:
github.com/vektra/mockery/v3/internal/fixtures/example_project/replace_type/rti/rt1:
RType1:
pkg-path: github.com/vektra/mockery/v3/internal/fixtures/example_project/replace_type/rti/rt2
type-name: RType2
github.com/vektra/mockery/v3/internal/fixtures:
interfaces:
RequesterVariadic:
Expand Down Expand Up @@ -61,4 +60,6 @@ packages:
all: True
dir: internal/fixtures/
pkgname: test

github.com/vektra/mockery/v3/internal:
interfaces:
InterfaceDoesntExist:
57 changes: 51 additions & 6 deletions internal/cmd/mockery.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ import (
"os"
"strings"

"github.com/chigopher/pathlib"
"github.com/rs/zerolog"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/vektra/mockery/v3/config"
pkg "github.com/vektra/mockery/v3/internal"
"github.com/vektra/mockery/v3/internal/logging"
"github.com/vektra/mockery/v3/internal/stackerr"

"github.com/chigopher/pathlib"
"github.com/rs/zerolog"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"golang.org/x/tools/go/packages"
)

Expand Down Expand Up @@ -195,6 +196,31 @@ func (r *RootApp) Run() error {
}
parser := pkg.NewParser(buildTags)

// Let's build a missing map here to keep track of seen interfaces.
// (pkg -> list of interface names)
// After seeing an interface it'll be deleted from the map, keeping only
// missing interfaces or packages in there.
//
// NOTE: We do that here without relying on parser, because parses iterates
// over existing go files and interfaces, while user could've had a typo in
// interface or pacakge name, making it impossible for parser to find these
// files/interfaces in the first place.
log.Debug().Msg("Making seen map...")
missingMap := make(map[string]map[string]struct{}, len(configuredPackages))
for _, p := range configuredPackages {
config, err := r.Config.GetPackageConfig(ctx, p)
if err != nil {
return err
}
if _, ok := missingMap[p]; !ok {
missingMap[p] = make(map[string]struct{}, len(config.Interfaces))
}

for ifaceName := range config.Interfaces {
missingMap[p][ifaceName] = struct{}{}
}
}

log.Info().Msg("Parsing configured packages...")
interfaces, err := parser.ParsePackages(ctx, configuredPackages)
if err != nil {
Expand All @@ -206,8 +232,8 @@ func (r *RootApp) Run() error {
// outputFilePath|fullyQualifiedInterfaceName|[]*pkg.Interface
// The reason why we need an interior map of fully qualified interface name
// to a slice of *pkg.Interface (which represents all information necessary
// to create the output mock) is because mockery allows multiple mocks to be
// created for each input interface.
// to create the output mock) is because mockery allows multiple mocks to
// be created for each input interface.
mockFileToInterfaces := map[string]*InterfaceCollection{}

for _, iface := range interfaces {
Expand All @@ -217,6 +243,14 @@ func (r *RootApp) Run() error {
Str(logging.LogKeyPackagePath, iface.Pkg.Types.Path()).
Logger()

if _, exist := missingMap[iface.Pkg.PkgPath]; exist {
delete(missingMap[iface.Pkg.PkgPath], iface.Name)

if len(missingMap[iface.Pkg.PkgPath]) == 0 {
delete(missingMap, iface.Pkg.PkgPath)
}
}

ifaceCtx := ifaceLog.WithContext(ctx)

pkgConfig, err := r.Config.GetPackageConfig(ctx, iface.Pkg.PkgPath)
Expand Down Expand Up @@ -322,5 +356,16 @@ func (r *RootApp) Run() error {
}
}

// The loop above could exit early, so sometimes warnings won't be shown
// until other errors are fixed
for packagePath := range missingMap {
for ifaceName := range missingMap[packagePath] {
log.Warn().
Str(logging.LogKeyInterface, ifaceName).
Str(logging.LogKeyPackagePath, packagePath).
Msg("interface not found in source")
}
}

return nil
}

0 comments on commit 0c8aecf

Please sign in to comment.