Skip to content

Commit

Permalink
[gopls-release-branch.0.7] internal/lsp/source: consider test variant…
Browse files Browse the repository at this point in the history
…s when finding pkg from pos

When resolving a position to a package we must consider all packages,
including intermediate test variants. This manifests, for example, when
jumping to definition in a package that is imported as a test variant
(see golang/go#47825).

For now, fix this by threading through an 'includeTestVariants' flag to
PackagesForFile. This isn't pretty, but should be a trivially safe
change: the only effect will be to increase the number of packages
considered in FindPackageFromPos. Since we are discussing future changes
to the API for querying packages from the snapshot, now did not seem
like a good time to undertake significant refactoring.

A regtest based on the original issue is included.

This CL is joint with [email protected].

Fixes golang/go#47825

Co-authored-by: Rebecca Stambler <[email protected]>
Change-Id: I4693ec69b50ed4acd569cff87883769c1edf332b
Reviewed-on: https://go-review.googlesource.com/c/tools/+/347563
Trust: Robert Findley <[email protected]>
Run-TryBot: Robert Findley <[email protected]>
gopls-CI: kokoro <[email protected]>
TryBot-Result: Go Bot <[email protected]>
Reviewed-by: Rebecca Stambler <[email protected]>
(cherry picked from commit e5f719f)
Reviewed-on: https://go-review.googlesource.com/c/tools/+/348372
  • Loading branch information
findleyr and stamblerre committed Sep 8, 2021
1 parent 64eabae commit 7f77468
Show file tree
Hide file tree
Showing 8 changed files with 56 additions and 15 deletions.
43 changes: 43 additions & 0 deletions gopls/internal/regtest/misc/definition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"testing"

. "golang.org/x/tools/internal/lsp/regtest"
"golang.org/x/tools/internal/testenv"

"golang.org/x/tools/internal/lsp/fake"
"golang.org/x/tools/internal/lsp/tests"
Expand Down Expand Up @@ -234,3 +235,45 @@ func main() {}
})
}
}

// Test for golang/go#47825.
func TestImportTestVariant(t *testing.T) {
testenv.NeedsGo1Point(t, 13)

const mod = `
-- go.mod --
module mod.com
go 1.12
-- client/test/role.go --
package test
import _ "mod.com/client"
type RoleSetup struct{}
-- client/client_role_test.go --
package client_test
import (
"testing"
_ "mod.com/client"
ctest "mod.com/client/test"
)
func TestClient(t *testing.T) {
_ = ctest.RoleSetup{}
}
-- client/client_test.go --
package client
import "testing"
func TestClient(t *testing.T) {}
-- client.go --
package client
`
Run(t, mod, func(t *testing.T, env *Env) {
env.OpenFile("client/client_role_test.go")
env.GoToDefinition("client/client_role_test.go", env.RegexpSearch("client/client_role_test.go", "RoleSetup"))
})
}
10 changes: 5 additions & 5 deletions internal/lsp/cache/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -453,10 +453,10 @@ func hashUnsavedOverlays(files map[span.URI]source.VersionedFileHandle) string {
return hashContents([]byte(strings.Join(unsaved, "")))
}

func (s *snapshot) PackagesForFile(ctx context.Context, uri span.URI, mode source.TypecheckMode) ([]source.Package, error) {
func (s *snapshot) PackagesForFile(ctx context.Context, uri span.URI, mode source.TypecheckMode, includeTestVariants bool) ([]source.Package, error) {
ctx = event.Label(ctx, tag.URI.Of(uri))

phs, err := s.packageHandlesForFile(ctx, uri, mode)
phs, err := s.packageHandlesForFile(ctx, uri, mode, includeTestVariants)
if err != nil {
return nil, err
}
Expand All @@ -474,7 +474,7 @@ func (s *snapshot) PackagesForFile(ctx context.Context, uri span.URI, mode sourc
func (s *snapshot) PackageForFile(ctx context.Context, uri span.URI, mode source.TypecheckMode, pkgPolicy source.PackageFilter) (source.Package, error) {
ctx = event.Label(ctx, tag.URI.Of(uri))

phs, err := s.packageHandlesForFile(ctx, uri, mode)
phs, err := s.packageHandlesForFile(ctx, uri, mode, false)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -503,7 +503,7 @@ func (s *snapshot) PackageForFile(ctx context.Context, uri span.URI, mode source
return ph.check(ctx, s)
}

func (s *snapshot) packageHandlesForFile(ctx context.Context, uri span.URI, mode source.TypecheckMode) ([]*packageHandle, error) {
func (s *snapshot) packageHandlesForFile(ctx context.Context, uri span.URI, mode source.TypecheckMode, includeTestVariants bool) ([]*packageHandle, error) {
// Check if we should reload metadata for the file. We don't invalidate IDs
// (though we should), so the IDs will be a better source of truth than the
// metadata. If there are no IDs for the file, then we should also reload.
Expand All @@ -523,7 +523,7 @@ func (s *snapshot) packageHandlesForFile(ctx context.Context, uri span.URI, mode
for _, id := range knownIDs {
// Filter out any intermediate test variants. We typically aren't
// interested in these packages for file= style queries.
if m := s.getMetadata(id); m != nil && m.IsIntermediateTestVariant {
if m := s.getMetadata(id); m != nil && m.IsIntermediateTestVariant && !includeTestVariants {
continue
}
var parseModes []source.ParseMode
Expand Down
2 changes: 1 addition & 1 deletion internal/lsp/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ func (c *commandHandler) RunTests(ctx context.Context, args command.RunTestsArgs

func (c *commandHandler) runTests(ctx context.Context, snapshot source.Snapshot, work *progress.WorkDone, uri protocol.DocumentURI, tests, benchmarks []string) error {
// TODO: fix the error reporting when this runs async.
pkgs, err := snapshot.PackagesForFile(ctx, uri.SpanURI(), source.TypecheckWorkspace)
pkgs, err := snapshot.PackagesForFile(ctx, uri.SpanURI(), source.TypecheckWorkspace, false)
if err != nil {
return err
}
Expand Down
4 changes: 2 additions & 2 deletions internal/lsp/diagnostics.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ func (s *Server) diagnoseChangedFiles(ctx context.Context, snapshot source.Snaps
if snapshot.IsBuiltin(ctx, uri) {
continue
}
pkgs, err := snapshot.PackagesForFile(ctx, uri, source.TypecheckFull)
pkgs, err := snapshot.PackagesForFile(ctx, uri, source.TypecheckFull, false)
if err != nil {
// TODO (findleyr): we should probably do something with the error here,
// but as of now this can fail repeatedly if load fails, so can be too
Expand Down Expand Up @@ -423,7 +423,7 @@ func (s *Server) checkForOrphanedFile(ctx context.Context, snapshot source.Snaps
if snapshot.IsBuiltin(ctx, fh.URI()) {
return nil
}
pkgs, err := snapshot.PackagesForFile(ctx, fh.URI(), source.TypecheckWorkspace)
pkgs, err := snapshot.PackagesForFile(ctx, fh.URI(), source.TypecheckWorkspace, false)
if len(pkgs) > 0 || err == nil {
return nil
}
Expand Down
2 changes: 1 addition & 1 deletion internal/lsp/source/identifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func Identifier(ctx context.Context, snapshot Snapshot, fh FileHandle, pos proto
ctx, done := event.Start(ctx, "source.Identifier")
defer done()

pkgs, err := snapshot.PackagesForFile(ctx, fh.URI(), TypecheckAll)
pkgs, err := snapshot.PackagesForFile(ctx, fh.URI(), TypecheckAll, false)
if err != nil {
return nil, err
}
Expand Down
4 changes: 2 additions & 2 deletions internal/lsp/source/implementation.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ var (
// every package that the file belongs to, in every typechecking mode
// applicable.
func qualifiedObjsAtProtocolPos(ctx context.Context, s Snapshot, uri span.URI, pp protocol.Position) ([]qualifiedObject, error) {
pkgs, err := s.PackagesForFile(ctx, uri, TypecheckAll)
pkgs, err := s.PackagesForFile(ctx, uri, TypecheckAll, false)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -262,7 +262,7 @@ func qualifiedObjsAtLocation(ctx context.Context, s Snapshot, key objSearchKey,
// try to be comprehensive in case we ever support variations on build
// constraints.

pkgs, err := s.PackagesForFile(ctx, key.uri, TypecheckAll)
pkgs, err := s.PackagesForFile(ctx, key.uri, TypecheckAll, false)
if err != nil {
return nil, err
}
Expand Down
4 changes: 1 addition & 3 deletions internal/lsp/source/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -282,9 +282,7 @@ func FindPackageFromPos(ctx context.Context, snapshot Snapshot, pos token.Pos) (
return nil, errors.Errorf("no file for pos %v", pos)
}
uri := span.URIFromPath(tok.Name())
// Search all packages: some callers may be working with packages not
// type-checked in workspace mode.
pkgs, err := snapshot.PackagesForFile(ctx, uri, TypecheckAll)
pkgs, err := snapshot.PackagesForFile(ctx, uri, TypecheckAll, true)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion internal/lsp/source/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ type Snapshot interface {

// PackagesForFile returns the packages that this file belongs to, checked
// in mode.
PackagesForFile(ctx context.Context, uri span.URI, mode TypecheckMode) ([]Package, error)
PackagesForFile(ctx context.Context, uri span.URI, mode TypecheckMode, includeTestVariants bool) ([]Package, error)

// PackageForFile returns a single package that this file belongs to,
// checked in mode and filtered by the package policy.
Expand Down

0 comments on commit 7f77468

Please sign in to comment.