GoPLS Viewer

Home|gopls/internal/gcimporter/iexport_go118_test.go
1// Copyright 2021 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5//go:build go1.18
6// +build go1.18
7
8package gcimporter_test
9
10import (
11    "bytes"
12    "fmt"
13    "go/ast"
14    "go/importer"
15    "go/parser"
16    "go/token"
17    "go/types"
18    "os"
19    "path/filepath"
20    "runtime"
21    "strings"
22    "testing"
23
24    "golang.org/x/tools/internal/gcimporter"
25    "golang.org/x/tools/internal/testenv"
26)
27
28// TODO(rfindley): migrate this to testdata, as has been done in the standard library.
29func TestGenericExport(t *testing.T) {
30    const src = `
31package generic
32
33type Any any
34
35type T[A, B any] struct { Left A; Right B }
36
37func (T[P, Q]) m() {}
38
39var X T[int, string] = T[int, string]{1, "hi"}
40
41func ToInt[P interface{ ~int }](p P) int { return int(p) }
42
43var IntID = ToInt[int]
44
45type G[C comparable] int
46
47func ImplicitFunc[T ~int]() {}
48
49type ImplicitType[T ~int] int
50
51// Exercise constant import/export
52const C1 = 42
53const C2 int = 42
54const C3 float64 = 42
55
56type Constraint[T any] interface {
57       m(T)
58}
59
60// TODO(rfindley): revert to multiple blanks once the restriction on multiple
61// blanks is removed from the type checker.
62// type Blanks[_ any, _ Constraint[int]] int
63// func (Blanks[_, _]) m() {}
64type Blanks[_ any] int
65func (Blanks[_]) m() {}
66`
67    testExportSrc(t, []byte(src))
68}
69
70func testExportSrc(t *testing.Tsrc []byte) {
71    // This package only handles gc export data.
72    if runtime.Compiler != "gc" {
73        t.Skipf("gc-built packages not available (compiler = %s)"runtime.Compiler)
74    }
75
76    fset := token.NewFileSet()
77    ferr := parser.ParseFile(fset"g.go"src0)
78    if err != nil {
79        t.Fatal(err)
80    }
81    conf := types.Config{
82        Importerimporter.Default(),
83    }
84    pkgerr := conf.Check(""fset, []*ast.File{f}, nil)
85    if err != nil {
86        t.Fatal(err)
87    }
88
89    // export
90    version := gcimporter.IExportVersion
91    dataerr := iexport(fsetversionpkg)
92    if err != nil {
93        t.Fatal(err)
94    }
95
96    testPkgData(tfsetversionpkgdata)
97}
98
99func TestImportTypeparamTests(t *testing.T) {
100    testenv.NeedsGoBuild(t// to find stdlib export data in the build cache
101
102    // Check go files in test/typeparam.
103    rootDir := filepath.Join(runtime.GOROOT(), "test""typeparam")
104    listerr := os.ReadDir(rootDir)
105    if err != nil {
106        t.Fatal(err)
107    }
108
109    if isUnifiedBuilder() {
110        t.Skip("unified export data format is currently unsupported")
111    }
112
113    for _entry := range list {
114        if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".go") {
115            // For now, only consider standalone go files.
116            continue
117        }
118
119        t.Run(entry.Name(), func(t *testing.T) {
120            filename := filepath.Join(rootDirentry.Name())
121            srcerr := os.ReadFile(filename)
122            if err != nil {
123                t.Fatal(err)
124            }
125
126            if !bytes.HasPrefix(src, []byte("// run")) && !bytes.HasPrefix(src, []byte("// compile")) {
127                // We're bypassing the logic of run.go here, so be conservative about
128                // the files we consider in an attempt to make this test more robust to
129                // changes in test/typeparams.
130                t.Skipf("not detected as a run test")
131            }
132
133            testExportSrc(tsrc)
134        })
135    }
136}
137
138func TestRecursiveExport_Issue51219(t *testing.T) {
139    const srca = `
140package a
141
142type Interaction[DataT InteractionDataConstraint] struct {
143}
144
145type InteractionDataConstraint interface {
146    []byte |
147        UserCommandInteractionData
148}
149
150type UserCommandInteractionData struct {
151    resolvedInteractionWithOptions
152}
153
154type resolvedInteractionWithOptions struct {
155    Resolved Resolved
156}
157
158type Resolved struct {
159    Users ResolvedData[User]
160}
161
162type ResolvedData[T ResolvedDataConstraint] map[uint64]T
163
164type ResolvedDataConstraint interface {
165    User | Message
166}
167
168type User struct{}
169
170type Message struct {
171    Interaction *Interaction[[]byte]
172}
173`
174
175    const srcb = `
176package b
177
178import (
179    "a"
180)
181
182// InteractionRequest is an incoming request Interaction
183type InteractionRequest[T a.InteractionDataConstraint] struct {
184    a.Interaction[T]
185}
186`
187
188    const srcp = `
189package p
190
191import (
192    "b"
193)
194
195// ResponseWriterMock mocks corde's ResponseWriter interface
196type ResponseWriterMock struct {
197    x b.InteractionRequest[[]byte]
198}
199`
200
201    importer := &testImporter{
202        src: map[string][]byte{
203            "a": []byte(srca),
204            "b": []byte(srcb),
205            "p": []byte(srcp),
206        },
207        pkgsmake(map[string]*types.Package),
208    }
209    _err := importer.Import("p")
210    if err != nil {
211        t.Fatal(err)
212    }
213}
214
215// testImporter is a helper to test chains of imports using export data.
216type testImporter struct {
217    src  map[string][]byte         // original source
218    pkgs map[string]*types.Package // memoized imported packages
219}
220
221func (t *testImporterImport(path string) (*types.Packageerror) {
222    if pkgok := t.pkgs[path]; ok {
223        return pkgnil
224    }
225    srcok := t.src[path]
226    if !ok {
227        return nilfmt.Errorf("unknown path %v"path)
228    }
229
230    // Type-check, but don't return this package directly.
231    fset := token.NewFileSet()
232    ferr := parser.ParseFile(fsetpath+".go"src0)
233    if err != nil {
234        return nilerr
235    }
236    conf := types.Config{
237        Importert,
238    }
239    pkgerr := conf.Check(pathfset, []*ast.File{f}, nil)
240    if err != nil {
241        return nilerr
242    }
243
244    // Export and import to get the package imported from export data.
245    exportdataerr := iexport(fsetgcimporter.IExportVersionpkg)
246    if err != nil {
247        return nilerr
248    }
249    imports := make(map[string]*types.Package)
250    fset2 := token.NewFileSet()
251    _pkg2err := gcimporter.IImportData(fset2importsexportdatapkg.Path())
252    if err != nil {
253        return nilerr
254    }
255    t.pkgs[path] = pkg2
256    return pkg2nil
257}
258
MembersX
TestImportTypeparamTests.BlockStmt.RangeStmt_2360.BlockStmt.BlockStmt.filename
testImporter.Import.t
testImporter.Import.path
testImporter.Import.imports
TestGenericExport.t
testExportSrc.t
testExportSrc.conf
testExportSrc.pkg
testImporter.Import.fset2
testImporter.Import.pkg2
testImporter.Import
testImporter.Import.f
testImporter.Import.exportdata
testImporter.Import._
TestGenericExport
testExportSrc.version
TestRecursiveExport_Issue51219.importer
TestRecursiveExport_Issue51219.err
TestRecursiveExport_Issue51219.srca
testImporter.Import.err
TestGenericExport.src
testExportSrc
testExportSrc.src
testExportSrc.f
TestRecursiveExport_Issue51219
testImporter.Import.fset
testImporter.Import.pkg
testExportSrc.err
TestImportTypeparamTests.BlockStmt.err
TestImportTypeparamTests.BlockStmt.RangeStmt_2360.BlockStmt.BlockStmt.src
testImporter.Import.conf
testImporter
testImporter.src
testImporter.pkgs
TestImportTypeparamTests.BlockStmt.rootDir
TestImportTypeparamTests.BlockStmt.list
TestRecursiveExport_Issue51219.t
TestRecursiveExport_Issue51219._
testExportSrc.fset
testExportSrc.data
TestRecursiveExport_Issue51219.srcb
TestImportTypeparamTests.BlockStmt.RangeStmt_2360.entry
TestImportTypeparamTests.BlockStmt.RangeStmt_2360.BlockStmt.BlockStmt.err
TestRecursiveExport_Issue51219.srcp
Members
X