mirror of https://github.com/golang/go.git
go/internal/gcimporter: add a test case for issue 51219
Based on CL 387814, construct a reproducer for issue 51219 using x/tools/go/internal/gcimporter. Confirmed that this fails without the fix in CL 392475. Additionally, this CL includes some minor cleanup: - no need to take two passes in testExportSrc, as IExportVersionGenerics and IExportVersionGo1_18 are the same - remove skips that are no longer needed. Fixes golang/go#51219 Change-Id: Ia76fe9038aab7a2b9efc8429dc211b03adbb5560 Reviewed-on: https://go-review.googlesource.com/c/tools/+/392734 Trust: Robert Findley <rfindley@google.com> Run-TryBot: Robert Findley <rfindley@google.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com> gopls-CI: kokoro <noreply+kokoro@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
parent
24806f2a30
commit
40370f8a2a
|
|
@ -9,6 +9,7 @@ package gcimporter_test
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/importer"
|
||||
"go/parser"
|
||||
|
|
@ -71,39 +72,27 @@ func testExportSrc(t *testing.T, src []byte) {
|
|||
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
|
||||
}
|
||||
|
||||
// Test at both stages of the 1.18 export data format change.
|
||||
tests := []struct {
|
||||
name string
|
||||
version int
|
||||
}{
|
||||
{"legacy generics", gcimporter.IExportVersionGenerics},
|
||||
{"go1.18", gcimporter.IExportVersionGo1_18},
|
||||
fset := token.NewFileSet()
|
||||
f, err := parser.ParseFile(fset, "g.go", src, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
conf := types.Config{
|
||||
Importer: importer.Default(),
|
||||
}
|
||||
pkg, err := conf.Check("", fset, []*ast.File{f}, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
fset := token.NewFileSet()
|
||||
f, err := parser.ParseFile(fset, "g.go", src, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
conf := types.Config{
|
||||
Importer: importer.Default(),
|
||||
}
|
||||
pkg, err := conf.Check("", fset, []*ast.File{f}, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// export
|
||||
data, err := iexport(fset, test.version, pkg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testPkgData(t, fset, test.version, pkg, data)
|
||||
})
|
||||
// export
|
||||
version := gcimporter.IExportVersion
|
||||
data, err := iexport(fset, version, pkg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testPkgData(t, fset, version, pkg, data)
|
||||
}
|
||||
|
||||
func TestImportTypeparamTests(t *testing.T) {
|
||||
|
|
@ -118,10 +107,6 @@ func TestImportTypeparamTests(t *testing.T) {
|
|||
t.Skip("unified export data format is currently unsupported")
|
||||
}
|
||||
|
||||
skip := map[string]string{
|
||||
"issue48424.go": "go/types support missing", // TODO: need to implement this if #48424 is accepted
|
||||
}
|
||||
|
||||
for _, entry := range list {
|
||||
if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".go") {
|
||||
// For now, only consider standalone go files.
|
||||
|
|
@ -129,10 +114,6 @@ func TestImportTypeparamTests(t *testing.T) {
|
|||
}
|
||||
|
||||
t.Run(entry.Name(), func(t *testing.T) {
|
||||
if reason, ok := skip[entry.Name()]; ok {
|
||||
t.Skip(reason)
|
||||
}
|
||||
|
||||
filename := filepath.Join(rootDir, entry.Name())
|
||||
src, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
|
|
@ -150,3 +131,124 @@ func TestImportTypeparamTests(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRecursiveExport_Issue51219(t *testing.T) {
|
||||
const srca = `
|
||||
package a
|
||||
|
||||
type Interaction[DataT InteractionDataConstraint] struct {
|
||||
}
|
||||
|
||||
type InteractionDataConstraint interface {
|
||||
[]byte |
|
||||
UserCommandInteractionData
|
||||
}
|
||||
|
||||
type UserCommandInteractionData struct {
|
||||
resolvedInteractionWithOptions
|
||||
}
|
||||
|
||||
type resolvedInteractionWithOptions struct {
|
||||
Resolved Resolved
|
||||
}
|
||||
|
||||
type Resolved struct {
|
||||
Users ResolvedData[User]
|
||||
}
|
||||
|
||||
type ResolvedData[T ResolvedDataConstraint] map[uint64]T
|
||||
|
||||
type ResolvedDataConstraint interface {
|
||||
User | Message
|
||||
}
|
||||
|
||||
type User struct{}
|
||||
|
||||
type Message struct {
|
||||
Interaction *Interaction[[]byte]
|
||||
}
|
||||
`
|
||||
|
||||
const srcb = `
|
||||
package b
|
||||
|
||||
import (
|
||||
"a"
|
||||
)
|
||||
|
||||
// InteractionRequest is an incoming request Interaction
|
||||
type InteractionRequest[T a.InteractionDataConstraint] struct {
|
||||
a.Interaction[T]
|
||||
}
|
||||
`
|
||||
|
||||
const srcp = `
|
||||
package p
|
||||
|
||||
import (
|
||||
"b"
|
||||
)
|
||||
|
||||
// ResponseWriterMock mocks corde's ResponseWriter interface
|
||||
type ResponseWriterMock struct {
|
||||
x b.InteractionRequest[[]byte]
|
||||
}
|
||||
`
|
||||
|
||||
importer := &testImporter{
|
||||
src: map[string][]byte{
|
||||
"a": []byte(srca),
|
||||
"b": []byte(srcb),
|
||||
"p": []byte(srcp),
|
||||
},
|
||||
pkgs: make(map[string]*types.Package),
|
||||
}
|
||||
_, err := importer.Import("p")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// testImporter is a helper to test chains of imports using export data.
|
||||
type testImporter struct {
|
||||
src map[string][]byte // original source
|
||||
pkgs map[string]*types.Package // memoized imported packages
|
||||
}
|
||||
|
||||
func (t *testImporter) Import(path string) (*types.Package, error) {
|
||||
if pkg, ok := t.pkgs[path]; ok {
|
||||
return pkg, nil
|
||||
}
|
||||
src, ok := t.src[path]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unknown path %v", path)
|
||||
}
|
||||
|
||||
// Type-check, but don't return this package directly.
|
||||
fset := token.NewFileSet()
|
||||
f, err := parser.ParseFile(fset, path+".go", src, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conf := types.Config{
|
||||
Importer: t,
|
||||
}
|
||||
pkg, err := conf.Check(path, fset, []*ast.File{f}, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Export and import to get the package imported from export data.
|
||||
exportdata, err := iexport(fset, gcimporter.IExportVersion, pkg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
imports := make(map[string]*types.Package)
|
||||
fset2 := token.NewFileSet()
|
||||
_, pkg2, err := gcimporter.IImportData(fset2, imports, exportdata, pkg.Path())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t.pkgs[path] = pkg2
|
||||
return pkg2, nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue