From d699167df1e96e9327f731d3810090378d1ea092 Mon Sep 17 00:00:00 2001 From: Eric Fritz Date: Thu, 9 Jun 2022 10:08:47 -0500 Subject: [PATCH 1/4] Squash commits. --- cmd/go-mockgen/args.go | 160 ++++++++++++++++-------- cmd/go-mockgen/main.go | 21 +++- internal/mockgen/generation/generate.go | 80 +++++++----- internal/mockgen/types/extract.go | 34 +++-- internal/mockgen/types/interface.go | 3 + 5 files changed, 198 insertions(+), 100 deletions(-) diff --git a/cmd/go-mockgen/args.go b/cmd/go-mockgen/args.go index 987947f..9eeb9d7 100644 --- a/cmd/go-mockgen/args.go +++ b/cmd/go-mockgen/args.go @@ -56,27 +56,31 @@ func parseOptions() ([]*generation.Options, error) { func parseFlags() (*generation.Options, error) { opts := &generation.Options{ - ImportPaths: []string{}, - Interfaces: []string{}, + PackageOptions: []generation.PackageOptions{ + { + ImportPaths: []string{}, + Interfaces: []string{}, + }, + }, } app := kingpin.New(consts.Name, consts.Description).Version(consts.Version) app.UsageWriter(os.Stdout) - app.Arg("path", "The import paths used to search for eligible interfaces").Required().StringsVar(&opts.ImportPaths) - app.Flag("package", "The name of the generated package. It will be inferred from the output options by default.").Short('p').StringVar(&opts.PkgName) - app.Flag("interfaces", "A list of target interfaces to generate defined in the given the import paths.").Short('i').StringsVar(&opts.Interfaces) - app.Flag("exclude", "A list of interfaces to exclude from generation. Mocks for all other exported interfaces defined in the given import paths are generated.").Short('e').StringsVar(&opts.Exclude) - app.Flag("dirname", "The target output directory. Each mock will be written to a unique file.").Short('d').StringVar(&opts.OutputDir) - app.Flag("filename", "The target output file. All mocks are written to this file.").Short('o').StringVar(&opts.OutputFilename) - app.Flag("import-path", "The import path of the generated package. It will be inferred from the target directory by default.").StringVar(&opts.PkgName) - app.Flag("prefix", "A prefix used in the name of each mock struct. Should be TitleCase by convention.").StringVar(&opts.Prefix) - app.Flag("constructor-prefix", "A prefix used in the name of each mock constructor function (after the initial `New`/`NewStrict` prefixes). Should be TitleCase by convention.").StringVar(&opts.ConstructorPrefix) - app.Flag("force", "Do not abort if a write to disk would overwrite an existing file.").Short('f').BoolVar(&opts.Force) - app.Flag("disable-formatting", "Do not run goimports over the rendered files.").BoolVar(&opts.DisableFormatting) - app.Flag("goimports", "Path to the goimports binary.").Default("goimports").StringVar(&opts.GoImportsBinary) - app.Flag("for-test", "Append _test suffix to generated package names and file names.").Default("false").BoolVar(&opts.ForTest) - app.Flag("file-prefix", "Content that is written at the top of each generated file.").StringVar(&opts.FilePrefix) + app.Arg("path", "The import paths used to search for eligible interfaces").Required().StringsVar(&opts.PackageOptions[0].ImportPaths) + app.Flag("package", "The name of the generated package. It will be inferred from the output options by default.").Short('p').StringVar(&opts.ContentOptions.PkgName) + app.Flag("interfaces", "A list of target interfaces to generate defined in the given the import paths.").Short('i').StringsVar(&opts.PackageOptions[0].Interfaces) + app.Flag("exclude", "A list of interfaces to exclude from generation. Mocks for all other exported interfaces defined in the given import paths are generated.").Short('e').StringsVar(&opts.PackageOptions[0].Exclude) + app.Flag("dirname", "The target output directory. Each mock will be written to a unique file.").Short('d').StringVar(&opts.OutputOptions.OutputDir) + app.Flag("filename", "The target output file. All mocks are written to this file.").Short('o').StringVar(&opts.OutputOptions.OutputFilename) + app.Flag("import-path", "The import path of the generated package. It will be inferred from the target directory by default.").StringVar(&opts.ContentOptions.OutputImportPath) + app.Flag("prefix", "A prefix used in the name of each mock struct. Should be TitleCase by convention.").StringVar(&opts.ContentOptions.Prefix) + app.Flag("constructor-prefix", "A prefix used in the name of each mock constructor function (after the initial `New`/`NewStrict` prefixes). Should be TitleCase by convention.").StringVar(&opts.ContentOptions.ConstructorPrefix) + app.Flag("force", "Do not abort if a write to disk would overwrite an existing file.").Short('f').BoolVar(&opts.OutputOptions.Force) + app.Flag("disable-formatting", "Do not run goimports over the rendered files.").BoolVar(&opts.OutputOptions.DisableFormatting) + app.Flag("goimports", "Path to the goimports binary.").Default("goimports").StringVar(&opts.OutputOptions.GoImportsBinary) + app.Flag("for-test", "Append _test suffix to generated package names and file names.").Default("false").BoolVar(&opts.OutputOptions.ForTest) + app.Flag("file-prefix", "Content that is written at the top of each generated file.").StringVar(&opts.ContentOptions.FilePrefix) if _, err := app.Parse(os.Args[1:]); err != nil { return nil, err @@ -103,8 +107,15 @@ func parseManifest() ([]*generation.Options, error) { FilePrefix string `yaml:"file-prefix"` Mocks []struct { - Path string `yaml:"path"` - Paths []string `yaml:"paths"` + Path string `yaml:"path"` + Paths []string `yaml:"paths"` + Sources []struct { + Path string `yaml:"path"` + Paths []string `yaml:"paths"` + Interfaces []string `yaml:"interfaces"` + Exclude []string `yaml:"exclude"` + Prefix string `yaml:"prefix"` + } `yaml:"sources"` Package string `yaml:"package"` Interfaces []string `yaml:"interfaces"` Exclude []string `yaml:"exclude"` @@ -154,30 +165,63 @@ func parseManifest() ([]*generation.Options, error) { opts.ForTest = true } - // Validation + // Canonicalization paths := opts.Paths if opts.Path != "" { paths = append(paths, opts.Path) } + + // Defaults if opts.Goimports == "" { opts.Goimports = "goimports" } + var packageOptions []generation.PackageOptions + if len(opts.Sources) > 0 { + if len(opts.Paths) > 0 { + return nil, fmt.Errorf("sources and path/paths are mutually exclusive") + } + + for _, source := range opts.Sources { + // Canonicalization + paths := source.Paths + if source.Path != "" { + paths = append(paths, source.Path) + } + + packageOptions = append(packageOptions, generation.PackageOptions{ + ImportPaths: paths, + Interfaces: source.Interfaces, + Exclude: source.Exclude, + Prefix: source.Prefix, + }) + } + } else { + packageOptions = append(packageOptions, generation.PackageOptions{ + ImportPaths: paths, + Interfaces: opts.Interfaces, + Exclude: opts.Exclude, + Prefix: opts.Prefix, + }) + } + allOptions = append(allOptions, &generation.Options{ - ImportPaths: paths, - PkgName: opts.Package, - Interfaces: opts.Interfaces, - Exclude: opts.Exclude, - OutputDir: opts.Dirname, - OutputFilename: opts.Filename, - OutputImportPath: opts.ImportPath, - Prefix: opts.Prefix, - ConstructorPrefix: opts.ConstructorPrefix, - Force: opts.Force, - DisableFormatting: opts.DisableFormatting, - GoImportsBinary: opts.Goimports, - ForTest: opts.ForTest, - FilePrefix: opts.FilePrefix, + PackageOptions: packageOptions, + OutputOptions: generation.OutputOptions{ + OutputDir: opts.Dirname, + OutputFilename: opts.Filename, + Force: opts.Force, + DisableFormatting: opts.DisableFormatting, + GoImportsBinary: opts.Goimports, + ForTest: opts.ForTest, + }, + ContentOptions: generation.ContentOptions{ + PkgName: opts.Package, + OutputImportPath: opts.ImportPath, + Prefix: opts.Prefix, + ConstructorPrefix: opts.ConstructorPrefix, + FilePrefix: opts.FilePrefix, + }, }) } @@ -190,28 +234,28 @@ func validateOutputPaths(opts *generation.Options) (bool, error) { return true, fmt.Errorf("failed to get current directory") } - if opts.OutputFilename == "" && opts.OutputDir == "" { - opts.OutputDir = wd + if opts.OutputOptions.OutputFilename == "" && opts.OutputOptions.OutputDir == "" { + opts.OutputOptions.OutputDir = wd } - if opts.OutputFilename != "" && opts.OutputDir != "" { + if opts.OutputOptions.OutputFilename != "" && opts.OutputOptions.OutputDir != "" { return false, fmt.Errorf("dirname and filename are mutually exclusive") } - if opts.OutputFilename != "" { - opts.OutputDir = path.Dir(opts.OutputFilename) - opts.OutputFilename = path.Base(opts.OutputFilename) + if opts.OutputOptions.OutputFilename != "" { + opts.OutputOptions.OutputDir = path.Dir(opts.OutputOptions.OutputFilename) + opts.OutputOptions.OutputFilename = path.Base(opts.OutputOptions.OutputFilename) } - if err := paths.EnsureDirExists(opts.OutputDir); err != nil { + if err := paths.EnsureDirExists(opts.OutputOptions.OutputDir); err != nil { return true, fmt.Errorf( "failed to make output directory %s: %s", - opts.OutputDir, + opts.OutputOptions.OutputDir, err.Error(), ) } - if opts.OutputDir, err = cleanPath(opts.OutputDir); err != nil { + if opts.OutputOptions.OutputDir, err = cleanPath(opts.OutputOptions.OutputDir); err != nil { return true, err } @@ -221,33 +265,39 @@ func validateOutputPaths(opts *generation.Options) (bool, error) { var goIdentifierPattern = regexp.MustCompile("^[A-Za-z]([A-Za-z0-9_]*[A-Za-z])?$") func validateOptions(opts *generation.Options) (bool, error) { - if len(opts.Interfaces) != 0 && len(opts.Exclude) != 0 { - return false, fmt.Errorf("interface lists and exclude lists are mutually exclusive") + for _, packageOpts := range opts.PackageOptions { + if len(packageOpts.Interfaces) != 0 && len(packageOpts.Exclude) != 0 { + return false, fmt.Errorf("interface lists and exclude lists are mutually exclusive") + } + + if packageOpts.Prefix != "" && !goIdentifierPattern.Match([]byte(packageOpts.Prefix)) { + return false, fmt.Errorf("prefix `%s` is illegal", packageOpts.Prefix) + } } - if opts.OutputImportPath == "" { - path, ok := paths.InferImportPath(opts.OutputDir) + if opts.ContentOptions.OutputImportPath == "" { + path, ok := paths.InferImportPath(opts.OutputOptions.OutputDir) if !ok { return false, fmt.Errorf("could not infer output import path") } - opts.OutputImportPath = path + opts.ContentOptions.OutputImportPath = path } - if opts.PkgName == "" { - opts.PkgName = opts.OutputImportPath[strings.LastIndex(opts.OutputImportPath, string(os.PathSeparator))+1:] + if opts.ContentOptions.PkgName == "" { + opts.ContentOptions.PkgName = opts.ContentOptions.OutputImportPath[strings.LastIndex(opts.ContentOptions.OutputImportPath, string(os.PathSeparator))+1:] } - if !goIdentifierPattern.Match([]byte(opts.PkgName)) { - return false, fmt.Errorf("package name `%s` is illegal", opts.PkgName) + if !goIdentifierPattern.Match([]byte(opts.ContentOptions.PkgName)) { + return false, fmt.Errorf("package name `%s` is illegal", opts.ContentOptions.PkgName) } - if opts.Prefix != "" && !goIdentifierPattern.Match([]byte(opts.Prefix)) { - return false, fmt.Errorf("prefix `%s` is illegal", opts.Prefix) + if opts.ContentOptions.Prefix != "" && !goIdentifierPattern.Match([]byte(opts.ContentOptions.Prefix)) { + return false, fmt.Errorf("prefix `%s` is illegal", opts.ContentOptions.Prefix) } - if opts.ConstructorPrefix != "" && !goIdentifierPattern.Match([]byte(opts.ConstructorPrefix)) { - return false, fmt.Errorf("constructor-`prefix `%s` is illegal", opts.ConstructorPrefix) + if opts.ContentOptions.ConstructorPrefix != "" && !goIdentifierPattern.Match([]byte(opts.ContentOptions.ConstructorPrefix)) { + return false, fmt.Errorf("constructor-`prefix `%s` is illegal", opts.ContentOptions.ConstructorPrefix) } return false, nil diff --git a/cmd/go-mockgen/main.go b/cmd/go-mockgen/main.go index de24793..05181dd 100644 --- a/cmd/go-mockgen/main.go +++ b/cmd/go-mockgen/main.go @@ -45,16 +45,25 @@ func mainErr() error { var importPaths []string for _, opts := range allOptions { - importPaths = append(importPaths, opts.ImportPaths...) + for _, packageOpts := range opts.PackageOptions { + importPaths = append(importPaths, packageOpts.ImportPaths...) + } } + log.Printf("loading data for %d packages\n", len(importPaths)) + pkgs, err := packages.Load(&packages.Config{Mode: packages.NeedName | packages.NeedImports | packages.NeedSyntax | packages.NeedTypes}, importPaths...) if err != nil { return fmt.Errorf("could not load packages %s (%s)", strings.Join(importPaths, ","), err.Error()) } for _, opts := range allOptions { - ifaces, err := types.Extract(pkgs, opts.ImportPaths, opts.Interfaces, opts.Exclude) + typePackageOpts := make([]types.PackageOptions, 0, len(opts.PackageOptions)) + for _, packageOpts := range opts.PackageOptions { + typePackageOpts = append(typePackageOpts, types.PackageOptions(packageOpts)) + } + + ifaces, err := types.Extract(pkgs, typePackageOpts) if err != nil { return err } @@ -64,9 +73,11 @@ func mainErr() error { nameMap[strings.ToLower(t.Name)] = struct{}{} } - for _, name := range opts.Interfaces { - if _, ok := nameMap[strings.ToLower(name)]; !ok { - return fmt.Errorf("type '%s' not found in supplied import paths", name) + for _, packageOpts := range opts.PackageOptions { + for _, name := range packageOpts.Interfaces { + if _, ok := nameMap[strings.ToLower(name)]; !ok { + return fmt.Errorf("type '%s' not found in supplied import paths", name) + } } } diff --git a/internal/mockgen/generation/generate.go b/internal/mockgen/generation/generate.go index d48e0c8..b34f504 100644 --- a/internal/mockgen/generation/generate.go +++ b/internal/mockgen/generation/generate.go @@ -17,24 +17,37 @@ import ( ) type Options struct { - ImportPaths []string - PkgName string - Interfaces []string - Exclude []string + PackageOptions []PackageOptions + OutputOptions OutputOptions + ContentOptions ContentOptions +} + +type PackageOptions struct { + ImportPaths []string + Interfaces []string + Exclude []string + Prefix string +} + +type OutputOptions struct { OutputFilename string OutputDir string - OutputImportPath string - Prefix string - ConstructorPrefix string Force bool DisableFormatting bool GoImportsBinary string ForTest bool +} + +type ContentOptions struct { + PkgName string + OutputImportPath string + Prefix string + ConstructorPrefix string FilePrefix string } func Generate(ifaces []*types.Interface, opts *Options) error { - if opts.OutputFilename != "" { + if opts.OutputOptions.OutputFilename != "" { return generateFile(ifaces, opts) } @@ -42,19 +55,19 @@ func Generate(ifaces []*types.Interface, opts *Options) error { } func generateFile(ifaces []*types.Interface, opts *Options) error { - basename := opts.OutputFilename - if opts.ForTest { + basename := opts.OutputOptions.OutputFilename + if opts.OutputOptions.ForTest { ext := filepath.Ext(basename) basename = strings.TrimSuffix(basename, ext) + "_test" + ext } - filename := filepath.Join(opts.OutputDir, basename) + filename := filepath.Join(opts.OutputOptions.OutputDir, basename) exists, err := paths.Exists(filename) if err != nil { return err } - if exists && !opts.Force { + if exists && !opts.OutputOptions.Force { return fmt.Errorf("filename %s already exists, overwrite with --force", paths.GetRelativePath(filename)) } @@ -62,25 +75,29 @@ func generateFile(ifaces []*types.Interface, opts *Options) error { } func generateDirectory(ifaces []*types.Interface, opts *Options) error { - var prefix string - if opts.Prefix != "" { - prefix = opts.Prefix + "_" - } - suffix := "_mock" - if opts.ForTest { + if opts.OutputOptions.ForTest { suffix += "_test" } - makeFilename := func(interfaceName string) string { - filename := fmt.Sprintf("%s%s%s.go", prefix, interfaceName, suffix) - return path.Join(opts.OutputDir, strings.Replace(strings.ToLower(filename), "-", "_", -1)) + makeFilename := func(iface *types.Interface) string { + prefix := opts.ContentOptions.Prefix + if iface.Prefix != "" { + prefix = iface.Prefix + } + if prefix != "" { + prefix += "_" + } + + filename := fmt.Sprintf("%s%s%s.go", prefix, iface.Name, suffix) + return path.Join(opts.OutputOptions.OutputDir, strings.Replace(strings.ToLower(filename), "-", "_", -1)) } - if !opts.Force { + if !opts.OutputOptions.Force { allPaths := make([]string, 0, len(ifaces)) for _, iface := range ifaces { - allPaths = append(allPaths, makeFilename(iface.Name)) + + allPaths = append(allPaths, makeFilename(iface)) } conflict, err := paths.AnyExists(allPaths) @@ -93,7 +110,7 @@ func generateDirectory(ifaces []*types.Interface, opts *Options) error { } for _, iface := range ifaces { - if err := generateAndRender([]*types.Interface{iface}, makeFilename(iface.Name), opts); err != nil { + if err := generateAndRender([]*types.Interface{iface}, makeFilename(iface), opts); err != nil { return err } } @@ -102,12 +119,12 @@ func generateDirectory(ifaces []*types.Interface, opts *Options) error { } func generateAndRender(ifaces []*types.Interface, filename string, opts *Options) error { - pkgName := opts.PkgName - if opts.ForTest { + pkgName := opts.ContentOptions.PkgName + if opts.OutputOptions.ForTest { pkgName += "_test" } - content, err := generateContent(ifaces, pkgName, opts.Prefix, opts.ConstructorPrefix, opts.FilePrefix, opts.OutputImportPath) + content, err := generateContent(ifaces, pkgName, opts.ContentOptions.Prefix, opts.ContentOptions.ConstructorPrefix, opts.ContentOptions.FilePrefix, opts.ContentOptions.OutputImportPath) if err != nil { return err } @@ -117,8 +134,8 @@ func generateAndRender(ifaces []*types.Interface, filename string, opts *Options return err } - if !opts.DisableFormatting { - if err := exec.Command(opts.GoImportsBinary, "-w", filename).Run(); err != nil { + if !opts.OutputOptions.DisableFormatting { + if err := exec.Command(opts.OutputOptions.GoImportsBinary, "-w", filename).Run(); err != nil { return errorWithSolutions{ err: fmt.Errorf("failed to format file: %s", err), solutions: []string{ @@ -156,6 +173,11 @@ func generateContent(ifaces []*types.Interface, pkgName, prefix, constructorPref } func generateInterface(file *jen.File, iface *types.Interface, prefix, constructorPrefix, outputImportPath string) { + if iface.Prefix != "" { + // Override parent prefix if one is set on the iface + prefix = iface.Prefix + } + withConstructorPrefix := func(f func(*wrappedInterface, string, string) jen.Code) func(*wrappedInterface, string) jen.Code { return func(iface *wrappedInterface, outputImportPath string) jen.Code { return f(iface, constructorPrefix, outputImportPath) diff --git a/internal/mockgen/types/extract.go b/internal/mockgen/types/extract.go index 182acba..ecf7ed3 100644 --- a/internal/mockgen/types/extract.go +++ b/internal/mockgen/types/extract.go @@ -13,28 +13,40 @@ import ( "golang.org/x/tools/go/packages" ) -func Extract(pkgs []*packages.Package, importPaths, targetNames, excludeNames []string) ([]*Interface, error) { +type PackageOptions struct { + ImportPaths []string + Interfaces []string + Exclude []string + Prefix string +} + +func Extract(pkgs []*packages.Package, packageOptions []PackageOptions) (ifaces []*Interface, _ error) { workingDirectory, err := os.Getwd() if err != nil { return nil, fmt.Errorf("failed to get working directory (%s)", err.Error()) } + var importPaths []string + for _, packageOpts := range packageOptions { + importPaths = append(importPaths, packageOpts.ImportPaths...) + } + packageTypes, err := gatherAllPackageTypes(pkgs, workingDirectory, importPaths) if err != nil { return nil, err } - typeNames := gatherAllPackageTypeNames(packageTypes) - - ifaces := make([]*Interface, 0, len(typeNames)) - for _, name := range typeNames { - iface, err := extractInterface(packageTypes, name, targetNames, excludeNames) - if err != nil { - return nil, err - } + for _, packageOpts := range packageOptions { + for _, name := range gatherAllPackageTypeNames(packageTypes) { + iface, err := extractInterface(packageTypes, name, packageOpts.Interfaces, packageOpts.Exclude) + if err != nil { + return nil, err + } - if iface != nil { - ifaces = append(ifaces, iface) + if iface != nil { + iface.Prefix = packageOpts.Prefix + ifaces = append(ifaces, iface) + } } } diff --git a/internal/mockgen/types/interface.go b/internal/mockgen/types/interface.go index afbf3be..2800b48 100644 --- a/internal/mockgen/types/interface.go +++ b/internal/mockgen/types/interface.go @@ -11,6 +11,9 @@ type Interface struct { ImportPath string TypeParams []TypeParam Methods []*Method + + // Prefix is set on extraction based on the current PackageOptions + Prefix string } type TypeParam struct { From 06153dbd814be3d8985f4da5b83ca07bf84cce2b Mon Sep 17 00:00:00 2001 From: Eric Fritz Date: Thu, 9 Jun 2022 10:11:55 -0500 Subject: [PATCH 2/4] WIP. --- cmd/go-mockgen/args.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/go-mockgen/args.go b/cmd/go-mockgen/args.go index 9eeb9d7..982080b 100644 --- a/cmd/go-mockgen/args.go +++ b/cmd/go-mockgen/args.go @@ -73,7 +73,7 @@ func parseFlags() (*generation.Options, error) { app.Flag("exclude", "A list of interfaces to exclude from generation. Mocks for all other exported interfaces defined in the given import paths are generated.").Short('e').StringsVar(&opts.PackageOptions[0].Exclude) app.Flag("dirname", "The target output directory. Each mock will be written to a unique file.").Short('d').StringVar(&opts.OutputOptions.OutputDir) app.Flag("filename", "The target output file. All mocks are written to this file.").Short('o').StringVar(&opts.OutputOptions.OutputFilename) - app.Flag("import-path", "The import path of the generated package. It will be inferred from the target directory by default.").StringVar(&opts.ContentOptions.OutputImportPath) + app.Flag("import-path", "The import path of the generated package. It will be inferred from the target directory by default.").StringVar(&opts.ContentOptions.PkgName) app.Flag("prefix", "A prefix used in the name of each mock struct. Should be TitleCase by convention.").StringVar(&opts.ContentOptions.Prefix) app.Flag("constructor-prefix", "A prefix used in the name of each mock constructor function (after the initial `New`/`NewStrict` prefixes). Should be TitleCase by convention.").StringVar(&opts.ContentOptions.ConstructorPrefix) app.Flag("force", "Do not abort if a write to disk would overwrite an existing file.").Short('f').BoolVar(&opts.OutputOptions.Force) From fdef55feb43f7f0439893597815151b0972cec33 Mon Sep 17 00:00:00 2001 From: Eric Fritz Date: Thu, 9 Jun 2022 10:15:40 -0500 Subject: [PATCH 3/4] Update changelog and docs. --- CHANGELOG.md | 4 +++- README.md | 16 +++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 73b12e1..671fabe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,9 @@ ## [Unreleased] -Nothing changed yet. +### Added + +- Added support for `sources` in config file. [#33](https://github.com/derision-test/go-mockgen/pull/33) ## [v1.3.1] - 2022-06-06 diff --git a/README.md b/README.md index 7214363..af74972 100644 --- a/README.md +++ b/README.md @@ -47,13 +47,23 @@ A configuration file is also supported. If no command line arguments are supplie ```yaml force: true mocks: - - path: github.com/cache/user/pkg + - filename: foo/bar/mock_cache_test.go + path: github.com/usr/pkg/cache interfaces: - Cache - filename: foo/bar/mock_cache_test.go + - filename: foo/baz/mocks_test.go + # Supports multiple package sources in a single file + sources: + - path: github.com/usr/pkg/timer + interfaces: + - Timer + - path: github.com/usr/pkg/stopwatch + interfaces: + - LapTimer + - Stopwatch ``` -The top level of the configuration file may also set the keys `exclude`, `prefix`, `constructor-prefix`, `goimports`, `file-prefix`, `force`, `disable-formatting`, and `for-tests`. Top-level excludes will also be applied to each mock generator entry. The values for interface and constructor prefixes, goimports, and file content prefixes will apply to each mock generator entry if a value is not set. The remaining boolean values will be true for each mock generator entry if set at the top level (regardless of the setting of each entry). +The top level of the configuration file may also set the keys `exclude`, `prefix`, `constructor-prefix`, `goimports`, `file-prefix`, `force`, `disable-formatting`, and `for-tests`. Top-level excludes will also be applied to each mock generator entry. The values for interface and constructor prefixes, goimports, generated packag names, and file content prefixes will apply to each mock generator entry source(s) if a value is not set. The remaining boolean values will be true for each mock generator entry if set at the top level (regardless of the setting of each entry). ## Testing with Mocks From f64c7154a02f876f93936233a9dda44927bff0f8 Mon Sep 17 00:00:00 2001 From: Eric Fritz Date: Thu, 9 Jun 2022 10:16:37 -0500 Subject: [PATCH 4/4] Update spacing in readme. --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index af74972..88522fd 100644 --- a/README.md +++ b/README.md @@ -54,13 +54,13 @@ mocks: - filename: foo/baz/mocks_test.go # Supports multiple package sources in a single file sources: - - path: github.com/usr/pkg/timer - interfaces: - - Timer - - path: github.com/usr/pkg/stopwatch - interfaces: - - LapTimer - - Stopwatch + - path: github.com/usr/pkg/timer + interfaces: + - Timer + - path: github.com/usr/pkg/stopwatch + interfaces: + - LapTimer + - Stopwatch ``` The top level of the configuration file may also set the keys `exclude`, `prefix`, `constructor-prefix`, `goimports`, `file-prefix`, `force`, `disable-formatting`, and `for-tests`. Top-level excludes will also be applied to each mock generator entry. The values for interface and constructor prefixes, goimports, generated packag names, and file content prefixes will apply to each mock generator entry source(s) if a value is not set. The remaining boolean values will be true for each mock generator entry if set at the top level (regardless of the setting of each entry).