@@ -197,7 +197,7 @@ func (s *snapshot) load(ctx context.Context, allowNetwork bool, scopes ...interf
197
197
}
198
198
// TODO: once metadata is immutable, we shouldn't have to lock here.
199
199
s .mu .Lock ()
200
- err := s . computeMetadataUpdates (ctx , PackagePath (pkg .PkgPath ), pkg , cfg , query , updates , nil )
200
+ err := computeMetadataUpdates (ctx , s . meta , PackagePath (pkg .PkgPath ), pkg , cfg , query , updates , nil )
201
201
s .mu .Unlock ()
202
202
if err != nil {
203
203
return err
@@ -216,7 +216,7 @@ func (s *snapshot) load(ctx context.Context, allowNetwork bool, scopes ...interf
216
216
delete (s .packages , key )
217
217
}
218
218
}
219
- s .workspacePackages = computeWorkspacePackages ( s .meta )
219
+ s .workspacePackages = computeWorkspacePackagesLocked ( s , s .meta )
220
220
s .dumpWorkspace ("load" )
221
221
s .mu .Unlock ()
222
222
@@ -442,7 +442,7 @@ func getWorkspaceDir(ctx context.Context, h *memoize.Handle, g *memoize.Generati
442
442
// computeMetadataUpdates populates the updates map with metadata updates to
443
443
// apply, based on the given pkg. It recurs through pkg.Imports to ensure that
444
444
// metadata exists for all dependencies.
445
- func ( s * snapshot ) computeMetadataUpdates (ctx context.Context , pkgPath PackagePath , pkg * packages.Package , cfg * packages.Config , query []string , updates map [PackageID ]* KnownMetadata , path []PackageID ) error {
445
+ func computeMetadataUpdates (ctx context.Context , g * metadataGraph , pkgPath PackagePath , pkg * packages.Package , cfg * packages.Config , query []string , updates map [PackageID ]* KnownMetadata , path []PackageID ) error {
446
446
id := PackageID (pkg .ID )
447
447
if new := updates [id ]; new != nil {
448
448
return nil
@@ -494,28 +494,13 @@ func (s *snapshot) computeMetadataUpdates(ctx context.Context, pkgPath PackagePa
494
494
m .Errors = append (m .Errors , err )
495
495
}
496
496
497
- uris := map [span.URI ]struct {}{}
498
497
for _ , filename := range pkg .CompiledGoFiles {
499
498
uri := span .URIFromPath (filename )
500
499
m .CompiledGoFiles = append (m .CompiledGoFiles , uri )
501
- uris [uri ] = struct {}{}
502
500
}
503
501
for _ , filename := range pkg .GoFiles {
504
502
uri := span .URIFromPath (filename )
505
503
m .GoFiles = append (m .GoFiles , uri )
506
- uris [uri ] = struct {}{}
507
- }
508
-
509
- for uri := range uris {
510
- // In order for a package to be considered for the workspace, at least one
511
- // file must be contained in the workspace and not vendored.
512
-
513
- // The package's files are in this view. It may be a workspace package.
514
- // Vendored packages are not likely to be interesting to the user.
515
- if ! strings .Contains (string (uri ), "/vendor/" ) && s .view .contains (uri ) {
516
- m .HasWorkspaceFiles = true
517
- break
518
- }
519
504
}
520
505
521
506
for importPath , importPkg := range pkg .Imports {
@@ -532,8 +517,8 @@ func (s *snapshot) computeMetadataUpdates(ctx context.Context, pkgPath PackagePa
532
517
m .MissingDeps [importPkgPath ] = struct {}{}
533
518
continue
534
519
}
535
- if s . noValidMetadataForIDLocked ( importID ) {
536
- if err := s . computeMetadataUpdates (ctx , importPkgPath , importPkg , cfg , query , updates , append (path , id )); err != nil {
520
+ if noValidMetadataForID ( g , importID ) {
521
+ if err := computeMetadataUpdates (ctx , g , importPkgPath , importPkg , cfg , query , updates , append (path , id )); err != nil {
537
522
event .Error (ctx , "error in dependency" , err )
538
523
}
539
524
}
@@ -542,12 +527,101 @@ func (s *snapshot) computeMetadataUpdates(ctx context.Context, pkgPath PackagePa
542
527
return nil
543
528
}
544
529
545
- // computeWorkspacePackages computes workspace packages for the given metadata
546
- // graph.
547
- func computeWorkspacePackages (meta * metadataGraph ) map [PackageID ]PackagePath {
530
+ // containsPackageLocked reports whether p is a workspace package for the
531
+ // snapshot s.
532
+ //
533
+ // s.mu must be held while calling this function.
534
+ func containsPackageLocked (s * snapshot , m * Metadata ) bool {
535
+ // In legacy workspace mode, or if a package does not have an associated
536
+ // module, a package is considered inside the workspace if any of its files
537
+ // are under the workspace root (and not excluded).
538
+ //
539
+ // Otherwise if the package has a module it must be an active module (as
540
+ // defined by the module root or go.work file) and at least one file must not
541
+ // be filtered out by directoryFilters.
542
+ if m .Module != nil && s .workspace .moduleSource != legacyWorkspace {
543
+ modURI := span .URIFromPath (m .Module .GoMod )
544
+ _ , ok := s .workspace .activeModFiles [modURI ]
545
+ if ! ok {
546
+ return false
547
+ }
548
+
549
+ uris := map [span.URI ]struct {}{}
550
+ for _ , uri := range m .CompiledGoFiles {
551
+ uris [uri ] = struct {}{}
552
+ }
553
+ for _ , uri := range m .GoFiles {
554
+ uris [uri ] = struct {}{}
555
+ }
556
+
557
+ for uri := range uris {
558
+ // Don't use view.contains here. go.work files may include modules
559
+ // outside of the workspace folder.
560
+ if ! strings .Contains (string (uri ), "/vendor/" ) && ! s .view .filters (uri ) {
561
+ return true
562
+ }
563
+ }
564
+ return false
565
+ }
566
+
567
+ return containsFileInWorkspaceLocked (s , m )
568
+ }
569
+
570
+ // containsOpenFileLocked reports whether any file referenced by m is open in
571
+ // the snapshot s.
572
+ //
573
+ // s.mu must be held while calling this function.
574
+ func containsOpenFileLocked (s * snapshot , m * KnownMetadata ) bool {
575
+ uris := map [span.URI ]struct {}{}
576
+ for _ , uri := range m .CompiledGoFiles {
577
+ uris [uri ] = struct {}{}
578
+ }
579
+ for _ , uri := range m .GoFiles {
580
+ uris [uri ] = struct {}{}
581
+ }
582
+
583
+ for uri := range uris {
584
+ if s .isOpenLocked (uri ) {
585
+ return true
586
+ }
587
+ }
588
+ return false
589
+ }
590
+
591
+ // containsFileInWorkspace reports whether m contains any file inside the
592
+ // workspace of the snapshot s.
593
+ //
594
+ // s.mu must be held while calling this function.
595
+ func containsFileInWorkspaceLocked (s * snapshot , m * Metadata ) bool {
596
+ uris := map [span.URI ]struct {}{}
597
+ for _ , uri := range m .CompiledGoFiles {
598
+ uris [uri ] = struct {}{}
599
+ }
600
+ for _ , uri := range m .GoFiles {
601
+ uris [uri ] = struct {}{}
602
+ }
603
+
604
+ for uri := range uris {
605
+ // In order for a package to be considered for the workspace, at least one
606
+ // file must be contained in the workspace and not vendored.
607
+
608
+ // The package's files are in this view. It may be a workspace package.
609
+ // Vendored packages are not likely to be interesting to the user.
610
+ if ! strings .Contains (string (uri ), "/vendor/" ) && s .view .contains (uri ) {
611
+ return true
612
+ }
613
+ }
614
+ return false
615
+ }
616
+
617
+ // computeWorkspacePackagesLocked computes workspace packages in the snapshot s
618
+ // for the given metadata graph.
619
+ //
620
+ // s.mu must be held while calling this function.
621
+ func computeWorkspacePackagesLocked (s * snapshot , meta * metadataGraph ) map [PackageID ]PackagePath {
548
622
workspacePackages := make (map [PackageID ]PackagePath )
549
623
for _ , m := range meta .metadata {
550
- if ! m . HasWorkspaceFiles {
624
+ if ! containsPackageLocked ( s , m . Metadata ) {
551
625
continue
552
626
}
553
627
if m .PkgFilesChanged {
@@ -567,6 +641,12 @@ func computeWorkspacePackages(meta *metadataGraph) map[PackageID]PackagePath {
567
641
if allFilesHaveRealPackages (meta , m ) {
568
642
continue
569
643
}
644
+
645
+ // We only care about command-line-arguments packages if they are still
646
+ // open.
647
+ if ! containsOpenFileLocked (s , m ) {
648
+ continue
649
+ }
570
650
}
571
651
572
652
switch {
0 commit comments