From 8d2a9f6d59a99289066f3bda61b6142e023fa1e3 Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 1 Feb 2025 19:37:26 +0300 Subject: [PATCH 1/2] feat(v3): Warning for nonexistent mocks --- .gitignore | 1 + .mockery.yml | 19 +++++++------- internal/cmd/mockery.go | 57 ++++++++++++++++++++++++++++++++++++----- 3 files changed, 62 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index ce357ea3..5544cdcd 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ coverage.txt site/ .task/ tools/tools +*.lua diff --git a/.mockery.yml b/.mockery.yml index b83b58a0..1136ccae 100644 --- a/.mockery.yml +++ b/.mockery.yml @@ -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: @@ -61,4 +60,6 @@ packages: all: True dir: internal/fixtures/ pkgname: test - + github.com/vektra/mockery/v3/internal: + interfaces: + InterfaceDoesntExist: diff --git a/internal/cmd/mockery.go b/internal/cmd/mockery.go index eac911c7..7c35e48c 100644 --- a/internal/cmd/mockery.go +++ b/internal/cmd/mockery.go @@ -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" ) @@ -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 { @@ -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 { @@ -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) @@ -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 packageName := range missingMap { + for iface := range missingMap[packageName] { + log.Warn(). + Str(logging.LogKeyInterface, iface). + Str(logging.LogKeyPackagePath, packageName). + Msg("no such interface") + } + } + return nil } From 234407bb3d393d64b291c3a418b7b401155447b1 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 4 Feb 2025 19:15:05 +0300 Subject: [PATCH 2/2] refactor: wording of error message & package vars --- internal/cmd/mockery.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/cmd/mockery.go b/internal/cmd/mockery.go index 7c35e48c..4fed1378 100644 --- a/internal/cmd/mockery.go +++ b/internal/cmd/mockery.go @@ -358,12 +358,12 @@ func (r *RootApp) Run() error { // The loop above could exit early, so sometimes warnings won't be shown // until other errors are fixed - for packageName := range missingMap { - for iface := range missingMap[packageName] { + for packagePath := range missingMap { + for ifaceName := range missingMap[packagePath] { log.Warn(). - Str(logging.LogKeyInterface, iface). - Str(logging.LogKeyPackagePath, packageName). - Msg("no such interface") + Str(logging.LogKeyInterface, ifaceName). + Str(logging.LogKeyPackagePath, packagePath). + Msg("interface not found in source") } }