Open mtoader opened 8 months ago
ping
Hey @mtoader thanks for the PR.
I understand it does create friction to have two different import aliases within the same package for the same import, but can you elaborate on what you mean by "mockgen itself can't handle it"?
Hey @mtoader thanks for the PR.
I understand it does create friction to have two different import aliases within the same package for the same import, but can you elaborate on what you mean by "mockgen itself can't handle it"?
I can definitely try,
Assume this:
p
with two files a.go
and b.go
a.go
like import imp_alias_a "github.com/package/definition"
b.go
with a different name. like import imp_alias_b "github.com/package/definition"
Definition
defined in a.go
(this Definition
might need to refer imp_alias_a
)client_p
that has an interface definition like type Int interface { F(p.Definition) }
Then
client_p
for Int
, mockgen will fail.This triggered for us because we do in-package mock generations for interfaces that reference proto definitions and we decided to have the proto generated packages aliased. One level of generation works but when you import a package that already has a generated mock with a different alias the generation fails.
Let me know if this is clear. If not i can try to make a repro case.
Also .. please advice on how to write those tests better.
Right now they fail with this:
go: downloading golang.org/x/tools v0.2.0
go: downloading golang.org/x/mod v0.11.0
go: downloading github.com/yuin/goldmark v1.4.13
go: downloading golang.org/x/sys v0.1.0
Error: mockgen/internal/tests/import_aliased/source.go:4:2: no required module provides package github.com/package/definition; to add it:
go get github.com/package/definition
Error: Process completed with exit code 1.
i assumed that the internal tree there is only used as a mock source to showcase thing, but i seem to have been wrong.
@mtoader, would you be able to provide a repro example and an error message for the situation?
@mtoader, would you be able to provide a repro example and an error message for the situation?
let me try
@mtoader, would you be able to provide a repro example and an error message for the situation?
let me try
@r-hang see https://github.com/mtoader/sample-gomock. Checkout and do run.sh
(assuming a working go setup) should show an error message similar to:
2024/03/19 13:30:35 Loading input failed: /Users/mihai/sample-gomock/pack/r.go:10:13: failed parsing arguments: /Users/mihai/sample-gomock/pack/r.go:10:17: unknown package "proto_pb"
client.go:8: running "mockgen": exit status 1
there are some comments in the run.sh
explaining the relatively narrow edge case here :)
@mtoader, would you be able to provide a repro example and an error message for the situation?
let me try
@r-hang see https://github.com/mtoader/sample-gomock. Checkout and do
run.sh
(assuming a working go setup) should show an error message similar to:2024/03/19 13:30:35 Loading input failed: /Users/mihai/sample-gomock/pack/r.go:10:13: failed parsing arguments: /Users/mihai/sample-gomock/pack/r.go:10:17: unknown package "proto_pb" client.go:8: running "mockgen": exit status 1
there are some comments in the
run.sh
explaining the relatively narrow edge case here :)
ping ?
Sorry for the delay and thank you for the repro. I'm starting to take a look now, i'll have an update by Monday.
Sorry for the delay and thank you for the repro. I'm starting to take a look now, i'll have an update by Monday.
Perfect, hopefully you can get the right fix in place.
Hey @mtoader,
I think the cause of this issue has to do with mockgen's attempt to merge all the files of a package with ast.MergepackageFiles before parsing it for imports. Only one package name is recognized by gomock at the conclusion of this step. While parsing, if an imported package alias is not in this map produced by this process, mock generation will fail. As your repro case points out, the order of the merge matters.
This also seemed to happen when dealing when mocking embedded interfaces in a different package because mockgen initializes a new parser for that package that does not carry over state from the root file we're looking to mock.
From my understanding, when parsing a package embedded somewhere in a package we want to mock, any difference in package aliases for the a particular package could cause this issue. In your example, a generated mock does trigger this case but mock generated code is not required.
If I patch your proposed fix here https://github.com/uber-go/mock/pull/165/files, but modify your github repro case with the patch below -- i'll still get a similar error on run.
new file mode 100644
index 0000000..8b2c385
--- /dev/null
+++ b/pack/a.go
@@ -0,0 +1,7 @@
+package pack
+
+import (
+ proto_name "github.com/sample/sample-gomock/proto"
+)
+
+func x(p *proto_name.X) { return }
diff --git a/pack/r.go b/pack/r.go
index 5d2c2fd..cca477d 100644
--- a/pack/r.go
+++ b/pack/r.go
@@ -1,11 +1,11 @@
package pack
import (
- proto_pb "github.com/sample/sample-gomock/proto"
+ "github.com/sample/sample-gomock/proto"
)
//go:generate mockgen -source r.go -destination mock_pack.gen.go -package pack
type I interface {
- DoSomething(x *proto_pb.X) (int, error)
+ DoSomething(x *proto.X) (int, error)
}
Where the error is src/github.com/mtoader/sample-gomock/pack/r.go:10:13: failed parsing arguments: /Users/rhang/gocode/src/github.com/mtoader/sample-gomock/pack/r.go:10:17: unknown package "proto"
As you alluded to in this issue, I think mockgen should be able to handle different aliases to the same package since the Go compiler is able to do so, i'm trying to see what changes that would require.
Yea .. my patch just attempts to manage the badness, the real solution is more complicated.
Yea .. my patch just attempts to manage the badness, the real solution is more complicated.
Thinking about what would be a good default behavior here, i think the following rules should hold:
source.go
containing type X interface
imports a package with some alias and that import is needed for the target mock_source.go
the import within mock_source.go
should use the same as the original file. -imports
flag seems kind of broken for some reason but it should always work regardless of how the import package path looks like). ping ?
We are also facing this issue... Any update on the fix as this has not been updates since April?
Hey @mtoader sorry for the delay.
Let's merge https://github.com/uber-go/mock/pull/165/files because it fixes what looks like a mistake where definedImports is never indexed by the importpath it is actually populated with.
As for the long term fix with the rules you specified above, I agree with your points!
I need to rebase / merge things. Gimme some little to do this.
Generating a mock, in source mode, for an interface that references types from an imported package that is aliased will not generate the same alias in the generated output. This creates problems when you want to generate within the same package since other tools, mockgen included, can't deal with packages that import other package with different aliases.
Expected behavior A clear and concise description of what you expected to happen.
The generated mock should use the same aliases as the source package.
To Reproduce Steps to reproduce the behavior
import ( definition_alias "github.com/package/definition" )
//go:generate mockgen -package import_aliased -destination source_mock.go -source=source.go -imports definition_alias=github.com/package/definition
type S interface { M(definition_alias.X) }
notice that now the
import_aliased
package imports thegithub.com/package/definition
with two aliases:definition
anddefinition_alias
. This is not a real problem for the go compiler but mockgen itself can't handle it. The right thing here is for generated file to reference the import with the same alias.Additional Information
Triage Notes for the Maintainers