@@ -6,6 +6,7 @@ package cache
6
6
7
7
import (
8
8
"bytes"
9
+ "cmp"
9
10
"context"
10
11
"errors"
11
12
"fmt"
@@ -18,7 +19,6 @@ import (
18
19
"path/filepath"
19
20
"regexp"
20
21
"slices"
21
- "sort"
22
22
"strconv"
23
23
"strings"
24
24
"sync"
@@ -652,11 +652,10 @@ func (s *Snapshot) Tests(ctx context.Context, ids ...PackageID) ([]*testfuncs.In
652
652
// (the one with the fewest files) that encloses the specified file.
653
653
// The result may be a test variant, but never an intermediate test variant.
654
654
func (snapshot * Snapshot ) NarrowestMetadataForFile (ctx context.Context , uri protocol.DocumentURI ) (* metadata.Package , error ) {
655
- mps , err := snapshot .MetadataForFile (ctx , uri )
655
+ mps , err := snapshot .MetadataForFile (ctx , uri , true )
656
656
if err != nil {
657
657
return nil , err
658
658
}
659
- metadata .RemoveIntermediateTestVariants (& mps )
660
659
if len (mps ) == 0 {
661
660
return nil , fmt .Errorf ("no package metadata for file %s" , uri )
662
661
}
@@ -668,13 +667,10 @@ func (snapshot *Snapshot) NarrowestMetadataForFile(ctx context.Context, uri prot
668
667
// number of CompiledGoFiles (i.e. "narrowest" to "widest" package),
669
668
// and secondarily by IsIntermediateTestVariant (false < true).
670
669
// The result may include tests and intermediate test variants of
671
- // importable packages.
670
+ // importable packages. If removeIntermediateTestVariants is provided,
671
+ // intermediate test variants will be excluded.
672
672
// It returns an error if the context was cancelled.
673
- //
674
- // TODO(adonovan): in nearly all cases the caller must use
675
- // [metadata.RemoveIntermediateTestVariants]. Make this a parameter to
676
- // force the caller to consider it (and reduce code).
677
- func (s * Snapshot ) MetadataForFile (ctx context.Context , uri protocol.DocumentURI ) ([]* metadata.Package , error ) {
673
+ func (s * Snapshot ) MetadataForFile (ctx context.Context , uri protocol.DocumentURI , removeIntermediateTestVariants bool ) ([]* metadata.Package , error ) {
678
674
if s .view .typ == AdHocView {
679
675
// As described in golang/go#57209, in ad-hoc workspaces (where we load ./
680
676
// rather than ./...), preempting the directory load with file loads can
@@ -712,7 +708,6 @@ func (s *Snapshot) MetadataForFile(ctx context.Context, uri protocol.DocumentURI
712
708
scope := fileLoadScope (uri )
713
709
err := s .load (ctx , NoNetwork , scope )
714
710
715
- //
716
711
// Return the context error here as the current operation is no longer
717
712
// valid.
718
713
if err != nil {
@@ -752,23 +747,42 @@ func (s *Snapshot) MetadataForFile(ctx context.Context, uri protocol.DocumentURI
752
747
s .unloadableFiles .Add (uri )
753
748
}
754
749
750
+ if removeIntermediateTestVariants {
751
+ metadata .RemoveIntermediateTestVariants (& metas )
752
+ }
753
+
755
754
// Sort packages "narrowest" to "widest" (in practice:
756
755
// non-tests before tests), and regular packages before
757
756
// their intermediate test variants (which have the same
758
757
// files but different imports).
759
- sort .Slice (metas , func (i , j int ) bool {
760
- x , y := metas [i ], metas [j ]
761
- xfiles , yfiles := len (x .CompiledGoFiles ), len (y .CompiledGoFiles )
762
- if xfiles != yfiles {
763
- return xfiles < yfiles
758
+ slices .SortFunc (metas , func (x , y * metadata.Package ) int {
759
+ if sign := cmp .Compare (len (x .CompiledGoFiles ), len (y .CompiledGoFiles )); sign != 0 {
760
+ return sign
761
+ }
762
+ // Skip ITV-specific ordering if they were removed.
763
+ if removeIntermediateTestVariants {
764
+ return 0
764
765
}
765
- return boolLess (x .IsIntermediateTestVariant (), y .IsIntermediateTestVariant ())
766
+ return boolCompare (x .IsIntermediateTestVariant (), y .IsIntermediateTestVariant ())
766
767
})
767
768
768
769
return metas , nil
769
770
}
770
771
771
- func boolLess (x , y bool ) bool { return ! x && y } // false < true
772
+ // btoi returns int(b) as proposed in #64825.
773
+ func btoi (b bool ) int {
774
+ if b {
775
+ return 1
776
+ } else {
777
+ return 0
778
+ }
779
+ }
780
+
781
+ // boolCompare is a comparison function for booleans, returning -1 if x < y, 0
782
+ // if x == y, and 1 if x > y, where false < true.
783
+ func boolCompare (x , y bool ) int {
784
+ return btoi (x ) - btoi (y )
785
+ }
772
786
773
787
// ReverseDependencies returns a new mapping whose entries are
774
788
// the ID and Metadata of each package in the workspace that
@@ -1252,7 +1266,7 @@ searchOverlays:
1252
1266
if s .IsBuiltin (uri ) || s .FileKind (o ) != file .Go {
1253
1267
continue
1254
1268
}
1255
- mps , err := s .MetadataForFile (ctx , uri )
1269
+ mps , err := s .MetadataForFile (ctx , uri , true )
1256
1270
if err != nil {
1257
1271
return nil , err
1258
1272
}
@@ -1261,7 +1275,6 @@ searchOverlays:
1261
1275
continue searchOverlays
1262
1276
}
1263
1277
}
1264
- metadata .RemoveIntermediateTestVariants (& mps )
1265
1278
1266
1279
// With zero-config gopls (golang/go#57979), orphaned file diagnostics
1267
1280
// include diagnostics for orphaned files -- not just diagnostics relating
@@ -1341,6 +1354,7 @@ searchOverlays:
1341
1354
if s .view .folder .Env .GoVersion >= 18 {
1342
1355
if s .view .gowork != "" {
1343
1356
fix = fmt .Sprintf ("To fix this problem, you can add this module to your go.work file (%s)" , s .view .gowork )
1357
+
1344
1358
cmd := command .NewRunGoWorkCommandCommand ("Run `go work use`" , command.RunGoWorkArgs {
1345
1359
ViewID : s .view .ID (),
1346
1360
Args : []string {"use" , modDir },
0 commit comments