зеркало из https://github.com/golang/tools.git
gopls/internal: implement Packages command
Implements the `gopls.packages` command. Updates golang/go#59445 Change-Id: Ia72a971b7aac9baa964c8cf5eee8b332b3125fa4 Reviewed-on: https://go-review.googlesource.com/c/tools/+/600355 Reviewed-by: Cherry Mui <cherryyz@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
Родитель
e5e8aa8472
Коммит
f5c7449850
|
@ -143,8 +143,85 @@ func (h *commandHandler) Modules(ctx context.Context, args command.ModulesArgs)
|
|||
return result, nil
|
||||
}
|
||||
|
||||
func (h *commandHandler) Packages(context.Context, command.PackagesArgs) (command.PackagesResult, error) {
|
||||
panic("unimplemented")
|
||||
func (h *commandHandler) Packages(ctx context.Context, args command.PackagesArgs) (command.PackagesResult, error) {
|
||||
wantTests := args.Mode&command.NeedTests != 0
|
||||
result := command.PackagesResult{
|
||||
Module: make(map[string]command.Module),
|
||||
}
|
||||
|
||||
keepPackage := func(pkg *metadata.Package) bool {
|
||||
for _, file := range pkg.GoFiles {
|
||||
for _, arg := range args.Files {
|
||||
if file == arg || file.Dir() == arg {
|
||||
return true
|
||||
}
|
||||
if args.Recursive && arg.Encloses(file) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
buildPackage := func(snapshot *cache.Snapshot, meta *metadata.Package) (command.Package, command.Module) {
|
||||
if wantTests {
|
||||
// These will be used in the next CL to query tests
|
||||
_, _ = ctx, snapshot
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
pkg := command.Package{
|
||||
Path: string(meta.PkgPath),
|
||||
}
|
||||
if meta.Module == nil {
|
||||
return pkg, command.Module{}
|
||||
}
|
||||
|
||||
mod := command.Module{
|
||||
Path: meta.Module.Path,
|
||||
Version: meta.Module.Version,
|
||||
GoMod: protocol.URIFromPath(meta.Module.GoMod),
|
||||
}
|
||||
pkg.ModulePath = mod.Path
|
||||
return pkg, mod
|
||||
}
|
||||
|
||||
err := h.run(ctx, commandConfig{
|
||||
progress: "Packages",
|
||||
}, func(ctx context.Context, _ commandDeps) error {
|
||||
for _, view := range h.s.session.Views() {
|
||||
snapshot, release, err := view.Snapshot()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer release()
|
||||
|
||||
metas, err := snapshot.WorkspaceMetadata(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, meta := range metas {
|
||||
if meta.IsIntermediateTestVariant() {
|
||||
continue
|
||||
}
|
||||
if !keepPackage(meta) {
|
||||
continue
|
||||
}
|
||||
|
||||
pkg, mod := buildPackage(snapshot, meta)
|
||||
result.Packages = append(result.Packages, pkg)
|
||||
|
||||
// Overwriting is ok
|
||||
if mod.Path != "" {
|
||||
result.Module[mod.Path] = mod
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (h *commandHandler) MaybePromptForTelemetry(ctx context.Context) error {
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
// Copyright 2024 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package workspace
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"golang.org/x/tools/gopls/internal/protocol"
|
||||
"golang.org/x/tools/gopls/internal/protocol/command"
|
||||
. "golang.org/x/tools/gopls/internal/test/integration"
|
||||
)
|
||||
|
||||
func TestPackages(t *testing.T) {
|
||||
const goModView = `
|
||||
-- go.mod --
|
||||
module foo
|
||||
|
||||
-- foo.go --
|
||||
package foo
|
||||
func Foo()
|
||||
|
||||
-- bar/bar.go --
|
||||
package bar
|
||||
func Bar()
|
||||
|
||||
-- baz/go.mod --
|
||||
module baz
|
||||
|
||||
-- baz/baz.go --
|
||||
package baz
|
||||
func Baz()
|
||||
`
|
||||
|
||||
t.Run("file", func(t *testing.T) {
|
||||
Run(t, goModView, func(t *testing.T, env *Env) {
|
||||
checkPackages(t, env, []protocol.DocumentURI{env.Editor.DocumentURI("foo.go")}, false, []command.Package{
|
||||
{
|
||||
Path: "foo",
|
||||
ModulePath: "foo",
|
||||
},
|
||||
}, map[string]command.Module{
|
||||
"foo": {
|
||||
Path: "foo",
|
||||
GoMod: env.Editor.DocumentURI("go.mod"),
|
||||
},
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("package", func(t *testing.T) {
|
||||
Run(t, goModView, func(t *testing.T, env *Env) {
|
||||
checkPackages(t, env, []protocol.DocumentURI{env.Editor.DocumentURI("bar")}, false, []command.Package{
|
||||
{
|
||||
Path: "foo/bar",
|
||||
ModulePath: "foo",
|
||||
},
|
||||
}, map[string]command.Module{
|
||||
"foo": {
|
||||
Path: "foo",
|
||||
GoMod: env.Editor.DocumentURI("go.mod"),
|
||||
},
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("workspace", func(t *testing.T) {
|
||||
Run(t, goModView, func(t *testing.T, env *Env) {
|
||||
checkPackages(t, env, []protocol.DocumentURI{env.Editor.DocumentURI("")}, true, []command.Package{
|
||||
{
|
||||
Path: "foo",
|
||||
ModulePath: "foo",
|
||||
},
|
||||
{
|
||||
Path: "foo/bar",
|
||||
ModulePath: "foo",
|
||||
},
|
||||
}, map[string]command.Module{
|
||||
"foo": {
|
||||
Path: "foo",
|
||||
GoMod: env.Editor.DocumentURI("go.mod"),
|
||||
},
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("nested module", func(t *testing.T) {
|
||||
Run(t, goModView, func(t *testing.T, env *Env) {
|
||||
// Load the nested module
|
||||
env.OpenFile("baz/baz.go")
|
||||
|
||||
// Request packages using the URI of the nested module _directory_
|
||||
checkPackages(t, env, []protocol.DocumentURI{env.Editor.DocumentURI("baz")}, true, []command.Package{
|
||||
{
|
||||
Path: "baz",
|
||||
ModulePath: "baz",
|
||||
},
|
||||
}, map[string]command.Module{
|
||||
"baz": {
|
||||
Path: "baz",
|
||||
GoMod: env.Editor.DocumentURI("baz/go.mod"),
|
||||
},
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func checkPackages(t testing.TB, env *Env, files []protocol.DocumentURI, recursive bool, wantPkg []command.Package, wantModule map[string]command.Module) {
|
||||
t.Helper()
|
||||
|
||||
cmd, err := command.NewPackagesCommand("Packages", command.PackagesArgs{Files: files, Recursive: recursive})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var result command.PackagesResult
|
||||
env.ExecuteCommand(&protocol.ExecuteCommandParams{
|
||||
Command: command.Packages.String(),
|
||||
Arguments: cmd.Arguments,
|
||||
}, &result)
|
||||
|
||||
// The ordering of packages is undefined so sort the results to ensure
|
||||
// consistency
|
||||
sort.Slice(result.Packages, func(i, j int) bool {
|
||||
a, b := result.Packages[i], result.Packages[j]
|
||||
return strings.Compare(a.Path, b.Path) < 0
|
||||
})
|
||||
|
||||
if diff := cmp.Diff(wantPkg, result.Packages); diff != "" {
|
||||
t.Errorf("Packages(%v) returned unexpected packages (-want +got):\n%s", files, diff)
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(wantModule, result.Module); diff != "" {
|
||||
t.Errorf("Packages(%v) returned unexpected modules (-want +got):\n%s", files, diff)
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче