@@ -45,7 +45,6 @@ func (s *snapshot) load(ctx context.Context, uri span.URI) ([]*metadata, error)
45
45
if err == context .Canceled {
46
46
return nil , errors .Errorf ("no metadata for %s: %v" , uri .Filename (), err )
47
47
}
48
-
49
48
log .Print (ctx , "go/packages.Load" , tag .Of ("packages" , len (pkgs )))
50
49
if len (pkgs ) == 0 {
51
50
if err == nil {
@@ -149,7 +148,7 @@ func (s *snapshot) updateMetadata(ctx context.Context, uri span.URI, pkgs []*pac
149
148
log .Print (ctx , "go/packages.Load" , tag .Of ("package" , pkg .PkgPath ), tag .Of ("files" , pkg .CompiledGoFiles ))
150
149
151
150
// Set the metadata for this package.
152
- if err := s .updateImports (ctx , packagePath (pkg .PkgPath ), pkg , cfg ); err != nil {
151
+ if err := s .updateImports (ctx , packagePath (pkg .PkgPath ), pkg , cfg , map [ packageID ] struct {}{} ); err != nil {
153
152
return nil , nil , err
154
153
}
155
154
m := s .getMetadata (packageID (pkg .ID ))
@@ -167,33 +166,36 @@ func (s *snapshot) updateMetadata(ctx context.Context, uri span.URI, pkgs []*pac
167
166
return results , prevMissingImports , nil
168
167
}
169
168
170
- func (s * snapshot ) updateImports (ctx context.Context , pkgPath packagePath , pkg * packages.Package , cfg * packages.Config ) error {
169
+ func (s * snapshot ) updateImports (ctx context.Context , pkgPath packagePath , pkg * packages.Package , cfg * packages.Config , seen map [packageID ]struct {}) error {
170
+ id := packageID (pkg .ID )
171
+ if _ , ok := seen [id ]; ok {
172
+ return errors .Errorf ("import cycle detected: %q" , id )
173
+ }
171
174
// Recreate the metadata rather than reusing it to avoid locking.
172
175
m := & metadata {
173
- id : packageID ( pkg . ID ) ,
176
+ id : id ,
174
177
pkgPath : pkgPath ,
175
178
name : pkg .Name ,
176
179
typesSizes : pkg .TypesSizes ,
177
180
errors : pkg .Errors ,
178
181
config : cfg ,
179
182
}
183
+ seen [id ] = struct {}{}
180
184
for _ , filename := range pkg .CompiledGoFiles {
181
185
uri := span .FileURI (filename )
182
186
m .files = append (m .files , uri )
183
187
184
188
s .addID (uri , m .id )
185
189
}
186
190
187
- // Add the metadata to the cache.
188
- s .setMetadata (m )
189
-
191
+ copied := make (map [packageID ]struct {})
192
+ for k , v := range seen {
193
+ copied [k ] = v
194
+ }
190
195
for importPath , importPkg := range pkg .Imports {
191
196
importPkgPath := packagePath (importPath )
192
197
importID := packageID (importPkg .ID )
193
198
194
- if importPkgPath == pkgPath {
195
- return errors .Errorf ("cycle detected in %s" , importPath )
196
- }
197
199
m .deps = append (m .deps , importID )
198
200
199
201
// Don't remember any imports with significant errors.
@@ -206,10 +208,14 @@ func (s *snapshot) updateImports(ctx context.Context, pkgPath packagePath, pkg *
206
208
}
207
209
dep := s .getMetadata (importID )
208
210
if dep == nil {
209
- if err := s .updateImports (ctx , importPkgPath , importPkg , cfg ); err != nil {
211
+ if err := s .updateImports (ctx , importPkgPath , importPkg , cfg , copied ); err != nil {
210
212
log .Error (ctx , "error in dependency" , err )
211
213
}
212
214
}
213
215
}
216
+
217
+ // Add the metadata to the cache.
218
+ s .setMetadata (m )
219
+
214
220
return nil
215
221
}
0 commit comments