@@ -142,7 +142,21 @@ func packageReferences(ctx context.Context, snapshot Snapshot, uri span.URI) ([]
142
142
if err != nil {
143
143
return nil , err
144
144
}
145
+
146
+ // Restrict search to workspace packages.
147
+ workspace , err := snapshot .WorkspaceMetadata (ctx )
148
+ if err != nil {
149
+ return nil , err
150
+ }
151
+ workspaceMap := make (map [PackageID ]* Metadata , len (workspace ))
152
+ for _ , m := range workspace {
153
+ workspaceMap [m .ID ] = m
154
+ }
155
+
145
156
for _ , rdep := range rdeps {
157
+ if _ , ok := workspaceMap [rdep .ID ]; ! ok {
158
+ continue
159
+ }
146
160
for _ , uri := range rdep .CompiledGoFiles {
147
161
fh , err := snapshot .ReadFile (ctx , uri )
148
162
if err != nil {
@@ -257,9 +271,9 @@ func ordinaryReferences(ctx context.Context, snapshot Snapshot, uri span.URI, pp
257
271
// Is object exported?
258
272
// If so, compute scope and targets of the global search.
259
273
var (
260
- globalScope = make (map [PackageID ]* Metadata )
274
+ globalScope = make (map [PackageID ]* Metadata ) // (excludes ITVs)
261
275
globalTargets map [PackagePath ]map [objectpath.Path ]unit
262
- expansions = make (map [* Metadata ]unit ) // packages that caused search expansion
276
+ expansions = make (map [PackageID ]unit ) // packages that caused search expansion
263
277
)
264
278
// TODO(adonovan): what about generic functions? Need to consider both
265
279
// uninstantiated and instantiated. The latter have no objectpath. Use Origin?
@@ -269,6 +283,47 @@ func ordinaryReferences(ctx context.Context, snapshot Snapshot, uri span.URI, pp
269
283
pkgPath : {path : {}}, // primary target
270
284
}
271
285
286
+ // Compute set of (non-ITV) workspace packages.
287
+ // We restrict references to this subset.
288
+ workspace , err := snapshot .WorkspaceMetadata (ctx )
289
+ if err != nil {
290
+ return nil , err
291
+ }
292
+ workspaceMap := make (map [PackageID ]* Metadata , len (workspace ))
293
+ workspaceIDs := make ([]PackageID , 0 , len (workspace ))
294
+ for _ , m := range workspace {
295
+ workspaceMap [m .ID ] = m
296
+ workspaceIDs = append (workspaceIDs , m .ID )
297
+ }
298
+
299
+ // addRdeps expands the global scope to include the
300
+ // reverse dependencies of the specified package.
301
+ addRdeps := func (id PackageID , transitive bool ) error {
302
+ rdeps , err := snapshot .ReverseDependencies (ctx , id , transitive )
303
+ if err != nil {
304
+ return err
305
+ }
306
+ for rdepID , rdep := range rdeps {
307
+ // Skip non-workspace packages.
308
+ //
309
+ // This means we also skip any expansion of the
310
+ // search that might be caused by a non-workspace
311
+ // package, possibly causing us to miss references
312
+ // to the expanded target set from workspace packages.
313
+ //
314
+ // TODO(adonovan): don't skip those expansions.
315
+ // The challenge is how to so without type-checking
316
+ // a lot of non-workspace packages not covered by
317
+ // the initial workspace load.
318
+ if _ , ok := workspaceMap [rdepID ]; ! ok {
319
+ continue
320
+ }
321
+
322
+ globalScope [rdepID ] = rdep
323
+ }
324
+ return nil
325
+ }
326
+
272
327
// How far need we search?
273
328
// For package-level objects, we need only search the direct importers.
274
329
// For fields and methods, we must search transitively.
@@ -278,13 +333,9 @@ func ordinaryReferences(ctx context.Context, snapshot Snapshot, uri span.URI, pp
278
333
// (Each set is disjoint so there's no benefit to
279
334
// to combining the metadata graph traversals.)
280
335
for _ , m := range variants {
281
- rdeps , err := snapshot .ReverseDependencies (ctx , m .ID , transitive )
282
- if err != nil {
336
+ if err := addRdeps (m .ID , transitive ); err != nil {
283
337
return nil , err
284
338
}
285
- for id , rdep := range rdeps {
286
- globalScope [id ] = rdep
287
- }
288
339
}
289
340
290
341
// Is object a method?
@@ -297,7 +348,7 @@ func ordinaryReferences(ctx context.Context, snapshot Snapshot, uri span.URI, pp
297
348
// 'expansions' records the packages that declared
298
349
// such types.
299
350
if recv := effectiveReceiver (obj ); recv != nil {
300
- if err := expandMethodSearch (ctx , snapshot , obj .(* types.Func ), recv , globalScope , globalTargets , expansions ); err != nil {
351
+ if err := expandMethodSearch (ctx , snapshot , workspaceIDs , obj .(* types.Func ), recv , addRdeps , globalTargets , expansions ); err != nil {
301
352
return nil , err
302
353
}
303
354
}
@@ -388,18 +439,18 @@ func ordinaryReferences(ctx context.Context, snapshot Snapshot, uri span.URI, pp
388
439
// Also compute local references within packages that declare
389
440
// corresponding methods (see above), which expand the global search.
390
441
// The target objects are identified by (PkgPath, objectpath).
391
- for m := range expansions {
392
- m := m
442
+ for id := range expansions {
443
+ id := id
393
444
group .Go (func () error {
394
445
// TODO(adonovan): opt: batch these TypeChecks.
395
- pkgs , err := snapshot .TypeCheck (ctx , m . ID )
446
+ pkgs , err := snapshot .TypeCheck (ctx , id )
396
447
if err != nil {
397
448
return err
398
449
}
399
450
pkg := pkgs [0 ]
400
451
401
452
targets := make (map [types.Object ]bool )
402
- for objpath := range globalTargets [m .PkgPath ] {
453
+ for objpath := range globalTargets [pkg . Metadata () .PkgPath ] {
403
454
obj , err := objectpath .Object (pkg .GetTypes (), objpath )
404
455
if err != nil {
405
456
return err // can't happen?
@@ -413,16 +464,7 @@ func ordinaryReferences(ctx context.Context, snapshot Snapshot, uri span.URI, pp
413
464
// Compute global references for selected reverse dependencies.
414
465
group .Go (func () error {
415
466
var globalIDs []PackageID
416
- for id , m := range globalScope {
417
- // Skip intermediate test variants.
418
- //
419
- // Strictly, an ITV's cross-reference index
420
- // may have different objectpaths from the
421
- // ordinary variant, but we ignore that. See
422
- // explanation at IsIntermediateTestVariant.
423
- if m .IsIntermediateTestVariant () {
424
- continue
425
- }
467
+ for id := range globalScope {
426
468
globalIDs = append (globalIDs , id )
427
469
}
428
470
indexes , err := snapshot .References (ctx , globalIDs ... )
@@ -444,37 +486,28 @@ func ordinaryReferences(ctx context.Context, snapshot Snapshot, uri span.URI, pp
444
486
}
445
487
446
488
// expandMethodSearch expands the scope and targets of a global search
447
- // for an exported method to include all methods that correspond to
448
- // it through interface satisfaction.
489
+ // for an exported method to include all methods in the workspace
490
+ // that correspond to it through interface satisfaction.
449
491
//
450
492
// Each package that declares a corresponding type is added to
451
493
// expansions so that we can also find local references to the type
452
494
// within the package, which of course requires type checking.
453
495
//
496
+ // The scope is expanded by a sequence of calls (not concurrent) to addRdeps.
497
+ //
454
498
// recv is the method's effective receiver type, for method-set computations.
455
- func expandMethodSearch (ctx context.Context , snapshot Snapshot , method * types.Func , recv types.Type , scope map [ PackageID ] * Metadata , targets map [PackagePath ]map [objectpath.Path ]unit , expansions map [* Metadata ]unit ) error {
499
+ func expandMethodSearch (ctx context.Context , snapshot Snapshot , workspaceIDs [] PackageID , method * types.Func , recv types.Type , addRdeps func ( id PackageID , transitive bool ) error , targets map [PackagePath ]map [objectpath.Path ]unit , expansions map [PackageID ]unit ) error {
456
500
// Compute the method-set fingerprint used as a key to the global search.
457
501
key , hasMethods := methodsets .KeyOf (recv )
458
502
if ! hasMethods {
459
503
return bug .Errorf ("KeyOf(%s)={} yet %s is a method" , recv , method )
460
504
}
461
- metas , err := snapshot .AllMetadata (ctx )
462
- if err != nil {
463
- return err
464
- }
465
- // Discard ITVs to avoid redundant type-checking.
466
- // (See explanation at IsIntermediateTestVariant.)
467
- RemoveIntermediateTestVariants (& metas )
468
- allIDs := make ([]PackageID , 0 , len (metas ))
469
- for _ , m := range metas {
470
- allIDs = append (allIDs , m .ID )
471
- }
472
505
// Search the methodset index of each package in the workspace.
473
- indexes , err := snapshot .MethodSets (ctx , allIDs ... )
506
+ indexes , err := snapshot .MethodSets (ctx , workspaceIDs ... )
474
507
if err != nil {
475
508
return err
476
509
}
477
- var mu sync.Mutex // guards scope , targets, expansions
510
+ var mu sync.Mutex // guards addRdeps , targets, expansions
478
511
var group errgroup.Group
479
512
for i , index := range indexes {
480
513
i := i
@@ -486,21 +519,21 @@ func expandMethodSearch(ctx context.Context, snapshot Snapshot, method *types.Fu
486
519
return nil
487
520
}
488
521
489
- // Expand global search scope to include rdeps of this pkg.
490
- rdeps , err := snapshot .ReverseDependencies (ctx , allIDs [i ], true )
491
- if err != nil {
492
- return err
493
- }
522
+ // We have discovered one or more corresponding types.
523
+ id := workspaceIDs [i ]
494
524
495
525
mu .Lock ()
496
526
defer mu .Unlock ()
497
527
498
- expansions [metas [i ]] = unit {}
499
-
500
- for _ , rdep := range rdeps {
501
- scope [rdep .ID ] = rdep
528
+ // Expand global search scope to include rdeps of this pkg.
529
+ if err := addRdeps (id , true ); err != nil {
530
+ return err
502
531
}
503
532
533
+ // Mark this package so that we search within it for
534
+ // local references to the additional types/methods.
535
+ expansions [id ] = unit {}
536
+
504
537
// Add each corresponding method the to set of global search targets.
505
538
for _ , res := range results {
506
539
methodPkg := PackagePath (res .PkgPath )
0 commit comments