Commit c205527
authored
Package Mode: Use aliases when used in source (#220)
v0.5.0 included #207, which replaced reflect mode with package mode. One
issue with package mode that came up (ref: #216) was that generated
mocks for interfaces that referred to alias types were referring to the
aliases' underlying names instead.
e.g.,
some package:
```go
package somgpkg
import "somepkg/internal/apicodec"
...
type Codec = apicodec.Codec
```
mockgen input:
```go
type Foo interface{
Bar() somepkg.Codec
}
```
mock:
```go
func (m *MockFoo) Bar() apicodec.Codec { // This is a problem, since apicodec is an internal package.
// ...
}
```
While technically this problem is solved in Go 1.23 with explicit alias
types representation, (indeed, if you run mockgen on the example in the
linked issue with `GODEBUG=gotypesalias=1`, you get the expected
behavior) since we support the last two versions, we can't bump `go.mod`
to 1.23 yet. This leaves us with the old behavior, where `go/types` does
not track alias types. You can tell if an object is an alias, but not a
type itself, and there is no way to retrieve the object of interest at
the point where we are recursively parsing method types.
This PR works around this issue (temporarily) by using syntax
information to find all references to aliases in the source package.
When we find one, we record it in a mapping of underlying type -> alias
name. Later, while we parse the type tree, we replace any underlying
types in the mapping with their alias names.
The unexpected side effect of this is that _all_ references to the
underlying type in the generated mocks will be replaced with the alias,
even if the source used the underlying name. This is fine because:
* If the alias is in the mapping, it was used at least once, which means
its accessible.
* From a type-checking perspective, aliases and their underlying types
are equivalent.
The nice exception to the side effect is when we explicitly request mock
generation for an alias type, since at that point we are dealing with
the object, not the type.
With this PR, the mocks get generated correctly now:
```go
func (m *MockFoo) Bar() Codec {
// ...
}
```
Once we can bump `go.mod` to 1.23, we should definitely remove this,
since the new type alias type nodes solve this problem automatically.1 parent b8222fa commit c205527
File tree
7 files changed
+802
-9
lines changed- mockgen
- internal/tests
- alias
- mock
- subpkg
- package_mode/mock
7 files changed
+802
-9
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
0 commit comments