@@ -127,142 +127,58 @@ func (s *snapshot) buildOverlay() map[string][]byte {
127
127
}
128
128
129
129
func (s * snapshot ) PackageHandles (ctx context.Context , fh source.FileHandle ) ([]source.PackageHandle , error ) {
130
- // If the file is a go.mod file, go.Packages.Load will always return 0 packages.
131
- if fh .Identity ().Kind == source .Mod {
132
- return nil , errors .Errorf ("attempting to get PackageHandles of .mod file %s" , fh .Identity ().URI )
130
+ if fh .Identity ().Kind != source .Go {
131
+ panic (fmt .Sprintf ("called PackageHandles on a non-Go FileHandle" ))
133
132
}
134
133
135
134
ctx = telemetry .File .With (ctx , fh .Identity ().URI )
136
- meta := s .getMetadataForURI (fh .Identity ().URI )
137
135
138
- phs , err := s .packageHandles (ctx , fh .Identity ().URI , meta )
139
- if err != nil {
140
- return nil , err
141
- }
142
- var results []source.PackageHandle
143
- for _ , ph := range phs {
144
- results = append (results , ph )
145
- }
146
- return results , nil
147
- }
148
-
149
- func (s * snapshot ) packageHandle (ctx context.Context , id packageID ) (* packageHandle , error ) {
150
- m := s .getMetadata (id )
151
-
152
- // Don't reload metadata in this function.
153
- // Callers of this function must reload metadata themselves.
154
- if m == nil {
155
- return nil , errors .Errorf ("%s has no metadata" , id )
156
- }
157
- phs , load , check := s .shouldCheck ([]* metadata {m })
158
- if load {
159
- return nil , errors .Errorf ("%s needs loading" , id )
160
- }
161
- if check {
162
- return s .buildPackageHandle (ctx , m .id , source .ParseFull )
163
- }
164
- var result * packageHandle
165
- for _ , ph := range phs {
166
- if ph .m .id == id {
167
- if result != nil {
168
- return nil , errors .Errorf ("multiple package handles for the same ID: %s" , id )
169
- }
170
- result = ph
171
- }
172
- }
173
- if result == nil {
174
- return nil , errors .Errorf ("no PackageHandle for %s" , id )
175
- }
176
- return result , nil
177
- }
178
-
179
- func (s * snapshot ) packageHandles (ctx context.Context , uri span.URI , meta []* metadata ) ([]* packageHandle , error ) {
180
- // First, determine if we need to reload or recheck the package.
181
- phs , load , check := s .shouldCheck (meta )
182
- if load {
183
- if err := s .load (ctx , fileURI (uri )); err != nil {
136
+ // Check if we should reload metadata for the file. We don't invalidate IDs
137
+ // (though we should), so the IDs will be a better source of truth than the
138
+ // metadata. If there are no IDs for the file, then we should also reload.
139
+ ids := s .getIDsForURI (fh .Identity ().URI )
140
+ reload := len (ids ) == 0
141
+ for _ , id := range ids {
142
+ // Reload package metadata if any of the metadata has missing
143
+ // dependencies, in case something has changed since the last time we
144
+ // reloaded it.
145
+ if m := s .getMetadata (id ); m == nil || len (m .missingDeps ) > 0 {
146
+ reload = true
147
+ break
148
+ }
149
+ }
150
+ if reload {
151
+ if err := s .load (ctx , fileURI (fh .Identity ().URI )); err != nil {
184
152
return nil , err
185
153
}
186
- // TODO(rstambler): Now that we are creating new package handles in
187
- // every load, this isn't really necessary.
188
- newMeta := s .getMetadataForURI (uri )
189
- newMissing := missingImports (newMeta )
190
- if len (newMissing ) != 0 {
191
- // Type checking a package with the same missing imports over and over
192
- // is futile. Don't re-check unless something has changed.
193
- check = check && ! sameSet (missingImports (meta ), newMissing )
194
- }
195
- meta = newMeta
196
- }
197
- var results []* packageHandle
198
- if check {
199
- for _ , m := range meta {
200
- ph , err := s .buildPackageHandle (ctx , m .id , source .ParseFull )
201
- if err != nil {
202
- return nil , err
203
- }
204
- results = append (results , ph )
205
- }
206
- } else {
207
- results = phs
208
154
}
209
- if len (results ) == 0 {
210
- return nil , errors .Errorf ("packageHandles: no package handles for %v" , uri )
211
- }
212
- return results , nil
213
- }
214
-
215
- func missingImports (metadata []* metadata ) map [packagePath ]struct {} {
216
- result := map [packagePath ]struct {}{}
217
- for _ , m := range metadata {
218
- for path := range m .missingDeps {
219
- result [path ] = struct {}{}
220
- }
221
- }
222
- return result
223
- }
224
-
225
- func sameSet (x , y map [packagePath ]struct {}) bool {
226
- if len (x ) != len (y ) {
227
- return false
228
- }
229
- for k := range x {
230
- if _ , ok := y [k ]; ! ok {
231
- return false
155
+ // Get the list of IDs from the snapshot again, in case it has changed.
156
+ var phs []source.PackageHandle
157
+ for _ , id := range s .getIDsForURI (fh .Identity ().URI ) {
158
+ ph , err := s .packageHandle (ctx , id , source .ParseFull )
159
+ if err != nil {
160
+ return nil , err
232
161
}
162
+ phs = append (phs , ph )
233
163
}
234
- return true
164
+ return phs , nil
235
165
}
236
166
237
- // shouldCheck determines if the packages provided by the metadata
238
- // need to be re-loaded or re-type-checked.
239
- func (s * snapshot ) shouldCheck (m []* metadata ) (phs []* packageHandle , load , check bool ) {
240
- // No metadata. Re-load and re-check.
241
- if len (m ) == 0 {
242
- return nil , true , true
243
- }
244
- // We expect to see a checked package for each package ID,
245
- // and it should be parsed in full mode.
246
- // If a single PackageHandle is missing, re-check all of them.
247
- // TODO: Optimize this by only checking the necessary packages.
248
- for _ , m := range m {
249
- ph := s .getPackage (m .id , source .ParseFull )
250
- if ph == nil {
251
- return nil , false , true
252
- }
253
- phs = append (phs , ph )
167
+ // packageHandle returns a PackageHandle for the given ID. It assumes that
168
+ // the metadata for the given ID has already been loaded, but if the
169
+ // PackageHandle has not been constructed, it will rebuild it.
170
+ func (s * snapshot ) packageHandle (ctx context.Context , id packageID , mode source.ParseMode ) (* packageHandle , error ) {
171
+ ph := s .getPackage (id , mode )
172
+ if ph != nil {
173
+ return ph , nil
254
174
}
255
- // If the metadata for the package had missing dependencies,
256
- // we _may_ need to re-check. If the missing dependencies haven't changed
257
- // since previous load, we will not check again.
258
- if len (phs ) < len (m ) {
259
- for _ , m := range m {
260
- if len (m .missingDeps ) != 0 {
261
- return nil , true , true
262
- }
263
- }
175
+ // Don't reload metadata in this function.
176
+ // Callers of this function must reload metadata themselves.
177
+ m := s .getMetadata (id )
178
+ if m == nil {
179
+ return nil , errors .Errorf ("%s has no metadata" , id )
264
180
}
265
- return phs , false , false
181
+ return s . buildPackageHandle ( ctx , m . id , mode )
266
182
}
267
183
268
184
func (s * snapshot ) GetReverseDependencies (ctx context.Context , id string ) ([]source.PackageHandle , error ) {
@@ -277,7 +193,7 @@ func (s *snapshot) GetReverseDependencies(ctx context.Context, id string) ([]sou
277
193
278
194
var results []source.PackageHandle
279
195
for id := range ids {
280
- ph , err := s .packageHandle (ctx , id )
196
+ ph , err := s .packageHandle (ctx , id , source . ParseFull )
281
197
if err != nil {
282
198
return nil , err
283
199
}
@@ -362,7 +278,7 @@ func (s *snapshot) WorkspacePackages(ctx context.Context) ([]source.PackageHandl
362
278
}
363
279
var results []source.PackageHandle
364
280
for _ , pkgID := range s .workspacePackageIDs () {
365
- ph , err := s .packageHandle (ctx , pkgID )
281
+ ph , err := s .packageHandle (ctx , pkgID , source . ParseFull )
366
282
if err != nil {
367
283
return nil , err
368
284
}
@@ -386,7 +302,7 @@ func (s *snapshot) KnownPackages(ctx context.Context) ([]source.PackageHandle, e
386
302
387
303
var results []source.PackageHandle
388
304
for pkgID := range wsPackages {
389
- ph , err := s .packageHandle (ctx , pkgID )
305
+ ph , err := s .packageHandle (ctx , pkgID , source . ParseFull )
390
306
if err != nil {
391
307
return nil , err
392
308
}
@@ -486,11 +402,11 @@ func (s *snapshot) addActionHandle(ah *actionHandle) {
486
402
s .actions [key ] = ah
487
403
}
488
404
489
- func (s * snapshot ) getMetadataForURI (uri span.URI ) []* metadata {
405
+ func (s * snapshot ) getIDsForURI (uri span.URI ) []packageID {
490
406
s .mu .Lock ()
491
407
defer s .mu .Unlock ()
492
408
493
- return s .getMetadataForURILocked ( uri )
409
+ return s .ids [ uri ]
494
410
}
495
411
496
412
func (s * snapshot ) getMetadataForURILocked (uri span.URI ) (metadata []* metadata ) {
@@ -711,7 +627,7 @@ func (s *snapshot) clone(ctx context.Context, withoutURIs map[span.URI]source.Fi
711
627
712
628
// Check if the file's package name or imports have changed,
713
629
// and if so, invalidate this file's packages' metadata.
714
- invalidateMetadata := s .shouldLoad (ctx , originalFH , currentFH )
630
+ invalidateMetadata := s .shouldInvalidateMetadata (ctx , originalFH , currentFH )
715
631
716
632
// If a go.mod file's contents have changed, invalidate the metadata
717
633
// for all of the packages in the workspace.
@@ -802,9 +718,9 @@ func (s *snapshot) clone(ctx context.Context, withoutURIs map[span.URI]source.Fi
802
718
return result
803
719
}
804
720
805
- // shouldLoad reparses a file's package and import declarations to
721
+ // shouldInvalidateMetadata reparses a file's package and import declarations to
806
722
// determine if the file requires a metadata reload.
807
- func (s * snapshot ) shouldLoad (ctx context.Context , originalFH , currentFH source.FileHandle ) bool {
723
+ func (s * snapshot ) shouldInvalidateMetadata (ctx context.Context , originalFH , currentFH source.FileHandle ) bool {
808
724
if originalFH == nil {
809
725
return currentFH .Identity ().Kind == source .Go
810
726
}
@@ -823,7 +739,6 @@ func (s *snapshot) shouldLoad(ctx context.Context, originalFH, currentFH source.
823
739
if originalErr != nil || currentErr != nil {
824
740
return (originalErr == nil ) != (currentErr == nil )
825
741
}
826
-
827
742
// Check if the package's metadata has changed. The cases handled are:
828
743
// 1. A package's name has changed
829
744
// 2. A file's imports have changed
0 commit comments