From 5dfcd56803571753f723bf5ba388e2f3188dcc05 Mon Sep 17 00:00:00 2001 From: Reilly Watson Date: Sat, 24 Aug 2024 01:22:43 -0400 Subject: [PATCH] Use Go 1.23, support imported type aliases (#225) Go 1.23 changed how go/types handles type aliases, which breaks code generation if you use a package that has an alias type (example: https://pkg.go.dev/github.com/golang/protobuf@v1.5.3/ptypes/timestamp#Timestamp ). These were getting generated as just the unqualified name, without the package. If you used a previous version of Go, it meant that if that aliased type was in an internal package we'd try to import the internal package instead, resulting in a compilation error. Add a switch to handle that case, and bump the go.mod version to support using types.Alias. --- go.mod | 2 +- internal/registry/method_scope.go | 12 +++ pkg/moq/moq_test.go | 6 ++ pkg/moq/testpackages/typealias/typealias.go | 9 +++ .../typealias/typealias_moq.golden.go | 81 +++++++++++++++++++ .../typealiasinternal/typealiasinternal.go | 10 +++ .../testpackages/typealiastwo/typealiastwo.go | 7 ++ 7 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 pkg/moq/testpackages/typealias/typealias.go create mode 100644 pkg/moq/testpackages/typealias/typealias_moq.golden.go create mode 100644 pkg/moq/testpackages/typealiastwo/internal/typealiasinternal/typealiasinternal.go create mode 100644 pkg/moq/testpackages/typealiastwo/typealiastwo.go diff --git a/go.mod b/go.mod index e04213b..79d0b70 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/matryer/moq -go 1.22.5 +go 1.23 require ( github.com/pmezard/go-difflib v1.0.0 diff --git a/internal/registry/method_scope.go b/internal/registry/method_scope.go index 65b5616..8cfd095 100644 --- a/internal/registry/method_scope.go +++ b/internal/registry/method_scope.go @@ -90,6 +90,18 @@ func (m MethodScope) populateImports(t types.Type, imports map[string]*Package) } } + case *types.Alias: + if pkg := t.Obj().Pkg(); pkg != nil { + imports[stripVendorPath(pkg.Path())] = m.registry.AddImport(pkg) + } + // The imports of a Type with a TypeList must be added to the imports list + // For example: Foo[otherpackage.Bar] , must have otherpackage imported + if targs := t.TypeArgs(); targs != nil { + for i := 0; i < targs.Len(); i++ { + m.populateImports(targs.At(i), imports) + } + } + case *types.Array: m.populateImports(t.Elem(), imports) diff --git a/pkg/moq/moq_test.go b/pkg/moq/moq_test.go index 5d6230d..1e31cfb 100644 --- a/pkg/moq/moq_test.go +++ b/pkg/moq/moq_test.go @@ -412,6 +412,12 @@ func TestMockGolden(t *testing.T) { interfaces: []string{"Magician"}, goldenFile: filepath.Join("testpackages/rangenum", "rangenum_moq.golden.go"), }, + { + name: "TypeAlias", + cfg: Config{SrcDir: "testpackages/typealias"}, + interfaces: []string{"Example"}, + goldenFile: filepath.Join("testpackages/typealias", "typealias_moq.golden.go"), + }, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { diff --git a/pkg/moq/testpackages/typealias/typealias.go b/pkg/moq/testpackages/typealias/typealias.go new file mode 100644 index 0000000..619fc99 --- /dev/null +++ b/pkg/moq/testpackages/typealias/typealias.go @@ -0,0 +1,9 @@ +package typealias + +import ( + "github.com/matryer/moq/pkg/moq/testpackages/typealiastwo" +) + +type Example interface { + Do(a typealiastwo.AliasType, b typealiastwo.GenericAliasType) error +} diff --git a/pkg/moq/testpackages/typealias/typealias_moq.golden.go b/pkg/moq/testpackages/typealias/typealias_moq.golden.go new file mode 100644 index 0000000..225a35c --- /dev/null +++ b/pkg/moq/testpackages/typealias/typealias_moq.golden.go @@ -0,0 +1,81 @@ +// Code generated by moq; DO NOT EDIT. +// github.com/matryer/moq + +package typealias + +import ( + "github.com/matryer/moq/pkg/moq/testpackages/typealiastwo" + "sync" +) + +// Ensure, that ExampleMock does implement Example. +// If this is not the case, regenerate this file with moq. +var _ Example = &ExampleMock{} + +// ExampleMock is a mock implementation of Example. +// +// func TestSomethingThatUsesExample(t *testing.T) { +// +// // make and configure a mocked Example +// mockedExample := &ExampleMock{ +// DoFunc: func(a typealiastwo.AliasType, b typealiastwo.GenericAliasType) error { +// panic("mock out the Do method") +// }, +// } +// +// // use mockedExample in code that requires Example +// // and then make assertions. +// +// } +type ExampleMock struct { + // DoFunc mocks the Do method. + DoFunc func(a typealiastwo.AliasType, b typealiastwo.GenericAliasType) error + + // calls tracks calls to the methods. + calls struct { + // Do holds details about calls to the Do method. + Do []struct { + // A is the a argument value. + A typealiastwo.AliasType + // B is the b argument value. + B typealiastwo.GenericAliasType + } + } + lockDo sync.RWMutex +} + +// Do calls DoFunc. +func (mock *ExampleMock) Do(a typealiastwo.AliasType, b typealiastwo.GenericAliasType) error { + if mock.DoFunc == nil { + panic("ExampleMock.DoFunc: method is nil but Example.Do was just called") + } + callInfo := struct { + A typealiastwo.AliasType + B typealiastwo.GenericAliasType + }{ + A: a, + B: b, + } + mock.lockDo.Lock() + mock.calls.Do = append(mock.calls.Do, callInfo) + mock.lockDo.Unlock() + return mock.DoFunc(a, b) +} + +// DoCalls gets all the calls that were made to Do. +// Check the length with: +// +// len(mockedExample.DoCalls()) +func (mock *ExampleMock) DoCalls() []struct { + A typealiastwo.AliasType + B typealiastwo.GenericAliasType +} { + var calls []struct { + A typealiastwo.AliasType + B typealiastwo.GenericAliasType + } + mock.lockDo.RLock() + calls = mock.calls.Do + mock.lockDo.RUnlock() + return calls +} diff --git a/pkg/moq/testpackages/typealiastwo/internal/typealiasinternal/typealiasinternal.go b/pkg/moq/testpackages/typealiastwo/internal/typealiasinternal/typealiasinternal.go new file mode 100644 index 0000000..c0b80de --- /dev/null +++ b/pkg/moq/testpackages/typealiastwo/internal/typealiasinternal/typealiasinternal.go @@ -0,0 +1,10 @@ +package typealiasinternal + +// we shouldn't be able to import these types directly, you need to use the alias in the parent package +type MyInternalType struct { + Foo int +} + +type MyGenericType[T any] struct { + A T +} diff --git a/pkg/moq/testpackages/typealiastwo/typealiastwo.go b/pkg/moq/testpackages/typealiastwo/typealiastwo.go new file mode 100644 index 0000000..de24951 --- /dev/null +++ b/pkg/moq/testpackages/typealiastwo/typealiastwo.go @@ -0,0 +1,7 @@ +package typealiastwo + +import "github.com/matryer/moq/pkg/moq/testpackages/typealiastwo/internal/typealiasinternal" + +type AliasType = typealiasinternal.MyInternalType + +type GenericAliasType = typealiasinternal.MyGenericType[int]