@@ -9,6 +9,7 @@ package gcimporter_test
9
9
10
10
import (
11
11
"bytes"
12
+ "fmt"
12
13
"go/ast"
13
14
"go/importer"
14
15
"go/parser"
@@ -71,39 +72,27 @@ func testExportSrc(t *testing.T, src []byte) {
71
72
t .Skipf ("gc-built packages not available (compiler = %s)" , runtime .Compiler )
72
73
}
73
74
74
- // Test at both stages of the 1.18 export data format change.
75
- tests := []struct {
76
- name string
77
- version int
78
- }{
79
- {"legacy generics" , gcimporter .IExportVersionGenerics },
80
- {"go1.18" , gcimporter .IExportVersionGo1_18 },
75
+ fset := token .NewFileSet ()
76
+ f , err := parser .ParseFile (fset , "g.go" , src , 0 )
77
+ if err != nil {
78
+ t .Fatal (err )
79
+ }
80
+ conf := types.Config {
81
+ Importer : importer .Default (),
82
+ }
83
+ pkg , err := conf .Check ("" , fset , []* ast.File {f }, nil )
84
+ if err != nil {
85
+ t .Fatal (err )
81
86
}
82
87
83
- for _ , test := range tests {
84
- t .Run (test .name , func (t * testing.T ) {
85
- fset := token .NewFileSet ()
86
- f , err := parser .ParseFile (fset , "g.go" , src , 0 )
87
- if err != nil {
88
- t .Fatal (err )
89
- }
90
- conf := types.Config {
91
- Importer : importer .Default (),
92
- }
93
- pkg , err := conf .Check ("" , fset , []* ast.File {f }, nil )
94
- if err != nil {
95
- t .Fatal (err )
96
- }
97
-
98
- // export
99
- data , err := iexport (fset , test .version , pkg )
100
- if err != nil {
101
- t .Fatal (err )
102
- }
103
-
104
- testPkgData (t , fset , test .version , pkg , data )
105
- })
88
+ // export
89
+ version := gcimporter .IExportVersion
90
+ data , err := iexport (fset , version , pkg )
91
+ if err != nil {
92
+ t .Fatal (err )
106
93
}
94
+
95
+ testPkgData (t , fset , version , pkg , data )
107
96
}
108
97
109
98
func TestImportTypeparamTests (t * testing.T ) {
@@ -118,21 +107,13 @@ func TestImportTypeparamTests(t *testing.T) {
118
107
t .Skip ("unified export data format is currently unsupported" )
119
108
}
120
109
121
- skip := map [string ]string {
122
- "issue48424.go" : "go/types support missing" , // TODO: need to implement this if #48424 is accepted
123
- }
124
-
125
110
for _ , entry := range list {
126
111
if entry .IsDir () || ! strings .HasSuffix (entry .Name (), ".go" ) {
127
112
// For now, only consider standalone go files.
128
113
continue
129
114
}
130
115
131
116
t .Run (entry .Name (), func (t * testing.T ) {
132
- if reason , ok := skip [entry .Name ()]; ok {
133
- t .Skip (reason )
134
- }
135
-
136
117
filename := filepath .Join (rootDir , entry .Name ())
137
118
src , err := os .ReadFile (filename )
138
119
if err != nil {
@@ -150,3 +131,124 @@ func TestImportTypeparamTests(t *testing.T) {
150
131
})
151
132
}
152
133
}
134
+
135
+ func TestRecursiveExport_Issue51219 (t * testing.T ) {
136
+ const srca = `
137
+ package a
138
+
139
+ type Interaction[DataT InteractionDataConstraint] struct {
140
+ }
141
+
142
+ type InteractionDataConstraint interface {
143
+ []byte |
144
+ UserCommandInteractionData
145
+ }
146
+
147
+ type UserCommandInteractionData struct {
148
+ resolvedInteractionWithOptions
149
+ }
150
+
151
+ type resolvedInteractionWithOptions struct {
152
+ Resolved Resolved
153
+ }
154
+
155
+ type Resolved struct {
156
+ Users ResolvedData[User]
157
+ }
158
+
159
+ type ResolvedData[T ResolvedDataConstraint] map[uint64]T
160
+
161
+ type ResolvedDataConstraint interface {
162
+ User | Message
163
+ }
164
+
165
+ type User struct{}
166
+
167
+ type Message struct {
168
+ Interaction *Interaction[[]byte]
169
+ }
170
+ `
171
+
172
+ const srcb = `
173
+ package b
174
+
175
+ import (
176
+ "a"
177
+ )
178
+
179
+ // InteractionRequest is an incoming request Interaction
180
+ type InteractionRequest[T a.InteractionDataConstraint] struct {
181
+ a.Interaction[T]
182
+ }
183
+ `
184
+
185
+ const srcp = `
186
+ package p
187
+
188
+ import (
189
+ "b"
190
+ )
191
+
192
+ // ResponseWriterMock mocks corde's ResponseWriter interface
193
+ type ResponseWriterMock struct {
194
+ x b.InteractionRequest[[]byte]
195
+ }
196
+ `
197
+
198
+ importer := & testImporter {
199
+ src : map [string ][]byte {
200
+ "a" : []byte (srca ),
201
+ "b" : []byte (srcb ),
202
+ "p" : []byte (srcp ),
203
+ },
204
+ pkgs : make (map [string ]* types.Package ),
205
+ }
206
+ _ , err := importer .Import ("p" )
207
+ if err != nil {
208
+ t .Fatal (err )
209
+ }
210
+ }
211
+
212
+ // testImporter is a helper to test chains of imports using export data.
213
+ type testImporter struct {
214
+ src map [string ][]byte // original source
215
+ pkgs map [string ]* types.Package // memoized imported packages
216
+ }
217
+
218
+ func (t * testImporter ) Import (path string ) (* types.Package , error ) {
219
+ if pkg , ok := t .pkgs [path ]; ok {
220
+ return pkg , nil
221
+ }
222
+ src , ok := t .src [path ]
223
+ if ! ok {
224
+ return nil , fmt .Errorf ("unknown path %v" , path )
225
+ }
226
+
227
+ // Type-check, but don't return this package directly.
228
+ fset := token .NewFileSet ()
229
+ f , err := parser .ParseFile (fset , path + ".go" , src , 0 )
230
+ if err != nil {
231
+ return nil , err
232
+ }
233
+ conf := types.Config {
234
+ Importer : t ,
235
+ }
236
+ pkg , err := conf .Check (path , fset , []* ast.File {f }, nil )
237
+ if err != nil {
238
+ return nil , err
239
+ }
240
+
241
+ // Export and import to get the package imported from export data.
242
+ exportdata , err := iexport (fset , gcimporter .IExportVersion , pkg )
243
+ if err != nil {
244
+ return nil , err
245
+ }
246
+ imports := make (map [string ]* types.Package )
247
+ fset2 := token .NewFileSet ()
248
+ _ , pkg2 , err := gcimporter .IImportData (fset2 , imports , exportdata , pkg .Path ())
249
+ if err != nil {
250
+ return nil , err
251
+ }
252
+ t .pkgs [path ] = pkg2
253
+ return pkg2 , nil
254
+ }
0 commit comments