Skip to content

Commit

Permalink
deprecated reflect mode has been replaced with package mode (#207)
Browse files Browse the repository at this point in the history
It is impossible to create an mock for a generic interface via reflect
mode, because it is impossible to compile a generic type without
instantiation.
This PR replaces the reflect mod for parsing using go/types.

All exists mocks have been regenerated and the tests have been passed.
But since this radically changes the behavior of reflect mode, I would
be grateful if there are those who want to add additional test cases
that I did not provide.

We can also come up with another name instead of import mode.

benefits:
generation mocks for generic interfaces
generation mocks for aliases to interfaces
correct names for method arguments

resolves #175
resolves #197
resolves #128
---------
Co-authored-by: Jacob Oaks <joaks@uber.com>
  • Loading branch information
tulzke and JacobOaks authored Oct 3, 2024
1 parent 6d5eb71 commit d01ed30
Show file tree
Hide file tree
Showing 30 changed files with 3,749 additions and 364 deletions.
17 changes: 6 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export PATH=$PATH:$(go env GOPATH)/bin

## Running mockgen

`mockgen` has two modes of operation: source and reflect.
`mockgen` has two modes of operation: source and package.

### Source mode

Expand All @@ -54,11 +54,10 @@ Example:
mockgen -source=foo.go [other options]
```

### Reflect mode
### Package mode

Reflect mode generates mock interfaces by building a program
that uses reflection to understand interfaces. It is enabled
by passing two non-flag arguments: an import path, and a
Package mode works by specifying the package and interface names.
It is enabled by passing two non-flag arguments: an import path, and a
comma-separated list of symbols.

You can use "." to refer to the current path's package.
Expand Down Expand Up @@ -98,7 +97,7 @@ It supports the following flags:
`foo=bar/baz.go`, where `bar/baz.go` is the source file and `foo` is the
package name of that file used by the -source file.

- `-build_flags`: (reflect mode only) Flags passed verbatim to `go build`.
- `-build_flags`: (package mode only) Flags passed verbatim to `go list`.

- `-mock_names`: A list of custom names for generated mocks. This is specified
as a comma-separated list of elements of the form
Expand All @@ -119,15 +118,11 @@ It supports the following flags:

- `-debug_parser`: Print out parser results only.

- `-exec_only`: (reflect mode) If set, execute this reflection program.

- `-prog_only`: (reflect mode) Only generate the reflection program; write it to stdout and exit.

- `-write_package_comment`: Writes package documentation comment (godoc) if true. (default true)

- `-write_generate_directive`: Add //go:generate directive to regenerate the mock. (default false)

- `-write_source_comment`: Writes original file (source mode) or interface names (reflect mode) comment if true. (default true)
- `-write_source_comment`: Writes original file (source mode) or interface names (package mode) comment if true. (default true)

- `-typed`: Generate Type-safe 'Return', 'Do', 'DoAndReturn' function. (default false)

Expand Down
9 changes: 8 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,15 @@ module go.uber.org/mock
go 1.22

require (
github.com/stretchr/testify v1.9.0
golang.org/x/mod v0.18.0
golang.org/x/tools v0.22.0
)

require github.com/yuin/goldmark v1.4.13 // indirect
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/yuin/goldmark v1.4.13 // indirect
golang.org/x/sync v0.7.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
Expand All @@ -6,3 +12,7 @@ golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
8 changes: 4 additions & 4 deletions gomock/internal/mock_gomock/mock_matcher.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 41 additions & 0 deletions mockgen/deprecated.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package main

import (
"flag"
"log"
"os"
)

const (
deprecatedFlagProgOnly = "prog_only"
deprecatedFlagExecOnly = "exec_only"
)

var (
_ = flag.Bool("prog_only", false, "DEPRECATED (reflect mode) Only generate the reflection program; write it to stdout and exit.")
_ = flag.String("exec_only", "", "DEPRECATED (reflect mode) If set, execute this reflection program.")
)

// notifyAboutDeprecatedFlags prints a warning message for a deprecated flags if they are set.
func notifyAboutDeprecatedFlags() {
const resetColorPostfix = "\033[0m"
logger := initWarningLogger()

flag.Visit(func(f *flag.Flag) {
switch f.Name {
case deprecatedFlagProgOnly:
logger.Println("The -prog_only flag is deprecated and has no effect.", resetColorPostfix)
case deprecatedFlagExecOnly:
logger.Println("The -exec_only flag is deprecated and has no effect.", resetColorPostfix)
}
})
}

func initWarningLogger() *log.Logger {
const (
yellowColor = "\033[33m"
warningPrefix = yellowColor + "WARNING: "
)

return log.New(os.Stdout, warningPrefix, log.Ldate|log.Ltime)
}
8 changes: 4 additions & 4 deletions mockgen/internal/tests/add_generate_directive/mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions mockgen/internal/tests/build_flags/directive.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package build_flags

// one build flag
//go:generate mockgen -destination=mock1/interfaces_mock.go -build_flags=-tags=tag1 . Interface
// multiple build flags
//go:generate mockgen -destination=mock2/interfaces_mock.go "-build_flags=-race -tags=tag2" . Interface
7 changes: 7 additions & 0 deletions mockgen/internal/tests/build_flags/interfaces_1.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//go:build tag1

package build_flags

type Interface interface {
HelloWorld() string
}
7 changes: 7 additions & 0 deletions mockgen/internal/tests/build_flags/interfaces_2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//go:build tag2

package build_flags

type Interface interface {
Foo()
}
54 changes: 54 additions & 0 deletions mockgen/internal/tests/build_flags/mock1/interfaces_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

52 changes: 52 additions & 0 deletions mockgen/internal/tests/build_flags/mock2/interfaces_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions mockgen/internal/tests/extra_import/mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions mockgen/internal/tests/generics/external.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
)

//go:generate mockgen --source=external.go --destination=source/mock_external_mock.go --package source
//go:generate mockgen --destination=package_mode/mock_external_mock.go -package=package_mode . ExternalConstraint,EmbeddingIface,Generator,Group

type ExternalConstraint[I constraints.Integer, F any] interface {
One(string) string
Expand Down
2 changes: 1 addition & 1 deletion mockgen/internal/tests/generics/generics.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
)

//go:generate mockgen --source=generics.go --destination=source/mock_generics_mock.go --package source
////go:generate mockgen --destination=reflect/mock_test.go --package reflect . Bar,Bar2
//go:generate mockgen --destination=package_mode/mock_test.go --package=package_mode . Bar,Universe,MilkyWay,SolarSystem,Earth,Water

type Bar[T any, R any] interface {
One(string) string
Expand Down
Loading

0 comments on commit d01ed30

Please sign in to comment.