Skip to content

Commit c05436a

Browse files
skewb1kgopherbot
authored andcommitted
gopls/internal/cache: add removeIntermediateTestVariants parameter
This CL adds a removeIntermediateTestVariants parameter to snapshot.MetadataForFile method. As noted in the TODO: "in nearly all cases the caller must use [metadata.RemoveIntermediateTestVariants]. Make this a parameter to force the caller to consider it (and reduce code)." Also allows earlier removal before sorting. Replaces sort.Slice with the more efficient slices.SortFunc. Change-Id: Ie2fd1b2862b3d511b837436b3805fc86739cef21 Reviewed-on: https://go-review.googlesource.com/c/tools/+/692415 Auto-Submit: Robert Findley <[email protected]> Reviewed-by: Alan Donovan <[email protected]> Reviewed-by: Robert Findley <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent f2692ba commit c05436a

File tree

8 files changed

+46
-34
lines changed

8 files changed

+46
-34
lines changed

gopls/internal/cache/metadata/metadata.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ func (mp *Package) String() string { return string(mp.ID) }
151151
// intermediate test variant of p, of which there could be many.
152152
// Good code doesn't rely on such trickery.
153153
//
154-
// Most callers of MetadataForFile call RemoveIntermediateTestVariants
154+
// Most callers of MetadataForFile set removeIntermediateTestVariants parameter
155155
// to discard them before requesting type checking, or the products of
156156
// type-checking such as the cross-reference index or method set index.
157157
//

gopls/internal/cache/snapshot.go

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package cache
66

77
import (
88
"bytes"
9+
"cmp"
910
"context"
1011
"errors"
1112
"fmt"
@@ -18,7 +19,6 @@ import (
1819
"path/filepath"
1920
"regexp"
2021
"slices"
21-
"sort"
2222
"strconv"
2323
"strings"
2424
"sync"
@@ -652,11 +652,10 @@ func (s *Snapshot) Tests(ctx context.Context, ids ...PackageID) ([]*testfuncs.In
652652
// (the one with the fewest files) that encloses the specified file.
653653
// The result may be a test variant, but never an intermediate test variant.
654654
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)
656656
if err != nil {
657657
return nil, err
658658
}
659-
metadata.RemoveIntermediateTestVariants(&mps)
660659
if len(mps) == 0 {
661660
return nil, fmt.Errorf("no package metadata for file %s", uri)
662661
}
@@ -668,13 +667,10 @@ func (snapshot *Snapshot) NarrowestMetadataForFile(ctx context.Context, uri prot
668667
// number of CompiledGoFiles (i.e. "narrowest" to "widest" package),
669668
// and secondarily by IsIntermediateTestVariant (false < true).
670669
// 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.
672672
// 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) {
678674
if s.view.typ == AdHocView {
679675
// As described in golang/go#57209, in ad-hoc workspaces (where we load ./
680676
// rather than ./...), preempting the directory load with file loads can
@@ -712,7 +708,6 @@ func (s *Snapshot) MetadataForFile(ctx context.Context, uri protocol.DocumentURI
712708
scope := fileLoadScope(uri)
713709
err := s.load(ctx, NoNetwork, scope)
714710

715-
//
716711
// Return the context error here as the current operation is no longer
717712
// valid.
718713
if err != nil {
@@ -752,23 +747,42 @@ func (s *Snapshot) MetadataForFile(ctx context.Context, uri protocol.DocumentURI
752747
s.unloadableFiles.Add(uri)
753748
}
754749

750+
if removeIntermediateTestVariants {
751+
metadata.RemoveIntermediateTestVariants(&metas)
752+
}
753+
755754
// Sort packages "narrowest" to "widest" (in practice:
756755
// non-tests before tests), and regular packages before
757756
// their intermediate test variants (which have the same
758757
// 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
764765
}
765-
return boolLess(x.IsIntermediateTestVariant(), y.IsIntermediateTestVariant())
766+
return boolCompare(x.IsIntermediateTestVariant(), y.IsIntermediateTestVariant())
766767
})
767768

768769
return metas, nil
769770
}
770771

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+
}
772786

773787
// ReverseDependencies returns a new mapping whose entries are
774788
// the ID and Metadata of each package in the workspace that
@@ -1252,7 +1266,7 @@ searchOverlays:
12521266
if s.IsBuiltin(uri) || s.FileKind(o) != file.Go {
12531267
continue
12541268
}
1255-
mps, err := s.MetadataForFile(ctx, uri)
1269+
mps, err := s.MetadataForFile(ctx, uri, true)
12561270
if err != nil {
12571271
return nil, err
12581272
}
@@ -1261,7 +1275,6 @@ searchOverlays:
12611275
continue searchOverlays
12621276
}
12631277
}
1264-
metadata.RemoveIntermediateTestVariants(&mps)
12651278

12661279
// With zero-config gopls (golang/go#57979), orphaned file diagnostics
12671280
// include diagnostics for orphaned files -- not just diagnostics relating
@@ -1341,6 +1354,7 @@ searchOverlays:
13411354
if s.view.folder.Env.GoVersion >= 18 {
13421355
if s.view.gowork != "" {
13431356
fix = fmt.Sprintf("To fix this problem, you can add this module to your go.work file (%s)", s.view.gowork)
1357+
13441358
cmd := command.NewRunGoWorkCommandCommand("Run `go work use`", command.RunGoWorkArgs{
13451359
ViewID: s.view.ID(),
13461360
Args: []string{"use", modDir},

gopls/internal/cache/source.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ type found struct {
176176

177177
func (s *goplsSource) resolveWorkspaceReferences(filename string, missing imports.References) ([]*imports.Result, error) {
178178
uri := protocol.URIFromPath(filename)
179-
mypkgs, err := s.snapshot.MetadataForFile(s.ctx, uri)
179+
mypkgs, err := s.snapshot.MetadataForFile(s.ctx, uri, false)
180180
if err != nil {
181181
return nil, err
182182
}

gopls/internal/golang/completion/package.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,13 +215,14 @@ func packageSuggestions(ctx context.Context, snapshot *cache.Snapshot, fileURI p
215215
return candidate{obj: obj, name: name, detail: name, score: score}
216216
}
217217

218-
matcher := fuzzy.NewMatcher(prefix)
219218
var currentPackageName string
220-
if variants, err := snapshot.MetadataForFile(ctx, fileURI); err == nil &&
221-
len(variants) != 0 {
222-
currentPackageName = string(variants[0].Name)
219+
// TODO: consider propagating error.
220+
if md, err := snapshot.NarrowestMetadataForFile(ctx, fileURI); err == nil {
221+
currentPackageName = string(md.Name)
223222
}
224223

224+
matcher := fuzzy.NewMatcher(prefix)
225+
225226
// Always try to suggest a main package
226227
defer func() {
227228
mainScore := lowScore

gopls/internal/golang/implementation.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,11 +143,10 @@ func implementationsMsets(ctx context.Context, snapshot *cache.Snapshot, pkg *ca
143143
// enumerate all types within the package that satisfy the
144144
// query type, even those defined local to a function.
145145
declURI = protocol.URIFromPath(declPosn.Filename)
146-
declMPs, err := snapshot.MetadataForFile(ctx, declURI)
146+
declMPs, err := snapshot.MetadataForFile(ctx, declURI, true)
147147
if err != nil {
148148
return err
149149
}
150-
metadata.RemoveIntermediateTestVariants(&declMPs)
151150
if len(declMPs) == 0 {
152151
return fmt.Errorf("no packages for file %s", declURI)
153152
}

gopls/internal/golang/references.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ func references(ctx context.Context, snapshot *cache.Snapshot, f file.Handle, pp
110110
// import declarations of all packages that directly import the target
111111
// package.
112112
func packageReferences(ctx context.Context, snapshot *cache.Snapshot, uri protocol.DocumentURI) ([]reference, error) {
113-
metas, err := snapshot.MetadataForFile(ctx, uri)
113+
metas, err := snapshot.MetadataForFile(ctx, uri, false)
114114
if err != nil {
115115
return nil, err
116116
}
@@ -260,7 +260,7 @@ func ordinaryReferences(ctx context.Context, snapshot *cache.Snapshot, uri proto
260260
// This may include the query pkg, and possibly other variants.
261261
declPosn := safetoken.StartPosition(pkg.FileSet(), obj.Pos())
262262
declURI := protocol.URIFromPath(declPosn.Filename)
263-
variants, err := snapshot.MetadataForFile(ctx, declURI)
263+
variants, err := snapshot.MetadataForFile(ctx, declURI, false)
264264
if err != nil {
265265
return nil, err
266266
}

gopls/internal/golang/rename.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -494,11 +494,10 @@ func renameOrdinary(ctx context.Context, snapshot *cache.Snapshot, uri protocol.
494494
// only package we need. (In case you're wondering why
495495
// 'references' doesn't also want the widest variant: it
496496
// computes the union across all variants.)
497-
mps, err := snapshot.MetadataForFile(ctx, uri)
497+
mps, err := snapshot.MetadataForFile(ctx, uri, true)
498498
if err != nil {
499499
return nil, err
500500
}
501-
metadata.RemoveIntermediateTestVariants(&mps)
502501
if len(mps) == 0 {
503502
return nil, fmt.Errorf("no package metadata for file %s", uri)
504503
}
@@ -745,7 +744,7 @@ func renameReceivers(pkg *cache.Package, recv *types.Var, newName string, editMa
745744
// selectors used only in an ITV, but life is short. Also sin must be
746745
// punished.)
747746
func typeCheckReverseDependencies(ctx context.Context, snapshot *cache.Snapshot, declURI protocol.DocumentURI, transitive bool) ([]*cache.Package, error) {
748-
variants, err := snapshot.MetadataForFile(ctx, declURI)
747+
variants, err := snapshot.MetadataForFile(ctx, declURI, false)
749748
if err != nil {
750749
return nil, err
751750
}

gopls/internal/golang/snapshot.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,10 @@ func WidestPackageForFile(ctx context.Context, snapshot *cache.Snapshot, uri pro
5252
}
5353

5454
func selectPackageForFile(ctx context.Context, snapshot *cache.Snapshot, uri protocol.DocumentURI, selector func([]*metadata.Package) *metadata.Package) (*cache.Package, *parsego.File, error) {
55-
mps, err := snapshot.MetadataForFile(ctx, uri)
55+
mps, err := snapshot.MetadataForFile(ctx, uri, true)
5656
if err != nil {
5757
return nil, nil, err
5858
}
59-
metadata.RemoveIntermediateTestVariants(&mps)
6059
if len(mps) == 0 {
6160
return nil, nil, fmt.Errorf("no package metadata for file %s", uri)
6261
}

0 commit comments

Comments
 (0)