internal/lsp/cmd: change vulncheck to directly call the hook

Instead of invoking the command through the LSP custom command,
call the vulncheck command hook directly. That reduces the extra
overhead of bringing up the full gopls server & package loading.
The vulncheck hook loads packages again any way, so the benefit
of running the check inside gopls's custom command framework
is not huge any more.

Still `gopls vulncheck` is useful - editors don't need to install
another binary for vulncheck feature, and it will output the
result in the format easier to handle than what `govulncheck`
currently offers.

Updates golang/go#50577

Change-Id: Ia21e6d7e0c37c4a1b02dc8bbca860143524c3d1b
Reviewed-on: https://go-review.googlesource.com/c/tools/+/404574
Reviewed-by: Robert Findley <rfindley@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
Run-TryBot: Hyang-Ah Hana Kim <hyangah@gmail.com>
This commit is contained in:
Hana 2022-05-06 09:33:05 -04:00 committed by Hyang-Ah Hana Kim
parent 72a884b2d6
commit 22b709631a
2 changed files with 23 additions and 15 deletions

View File

@ -5,5 +5,9 @@ Usage:
WARNING: this command is experimental.
By default, the command outputs a JSON-encoded
golang.org/x/tools/internal/lsp/command.VulncheckResult
message.
Example:
$ gopls vulncheck <packages>

View File

@ -11,8 +11,10 @@ import (
"fmt"
"os"
"golang.org/x/tools/go/packages"
"golang.org/x/tools/internal/lsp/command"
"golang.org/x/tools/internal/lsp/protocol"
"golang.org/x/tools/internal/lsp/source"
"golang.org/x/tools/internal/tool"
)
@ -31,6 +33,10 @@ func (v *vulncheck) DetailedHelp(f *flag.FlagSet) {
fmt.Fprint(f.Output(), `
WARNING: this command is experimental.
By default, the command outputs a JSON-encoded
golang.org/x/tools/internal/lsp/command.VulncheckResult
message.
Example:
$ gopls vulncheck <packages>
`)
@ -46,34 +52,32 @@ func (v *vulncheck) Run(ctx context.Context, args ...string) error {
pattern = args[0]
}
conn, err := v.app.connect(ctx)
if err != nil {
return err
}
defer conn.terminate(ctx)
cwd, err := os.Getwd()
if err != nil {
return err
return tool.CommandLineErrorf("failed to get current directory: %v", err)
}
cmd, err := command.NewRunVulncheckExpCommand("", command.VulncheckArgs{
opts := source.DefaultOptions().Clone()
v.app.options(opts) // register hook
if opts == nil || opts.Hooks.Govulncheck == nil {
return tool.CommandLineErrorf("vulncheck feature is not available")
}
loadCfg := &packages.Config{
Context: ctx,
}
res, err := opts.Hooks.Govulncheck(ctx, loadCfg, command.VulncheckArgs{
Dir: protocol.URIFromPath(cwd),
Pattern: pattern,
})
if err != nil {
return err
}
params := &protocol.ExecuteCommandParams{Command: cmd.Command, Arguments: cmd.Arguments}
res, err := conn.ExecuteCommand(ctx, params)
if err != nil {
return fmt.Errorf("executing server command: %v", err)
}
data, err := json.MarshalIndent(res, " ", " ")
if err != nil {
return fmt.Errorf("failed to decode results: %v", err)
}
fmt.Printf("%s\n", data)
fmt.Printf("%s", data)
return nil
}