| // Copyright 2020 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 cmd |
| |
| import ( |
| "context" |
| "encoding/json" |
| "flag" |
| "fmt" |
| "log" |
| "os" |
| |
| "golang.org/x/tools/internal/lsp/command" |
| "golang.org/x/tools/internal/lsp/lsprpc" |
| errors "golang.org/x/xerrors" |
| ) |
| |
| type remote struct { |
| subcommands |
| |
| // For backward compatibility, allow aliasing this command (it was previously |
| // called 'inspect'). |
| // |
| // TODO(rFindley): delete this after allowing some transition time in case |
| // there were any users of 'inspect' (I suspect not). |
| alias string |
| } |
| |
| func newRemote(app *Application, alias string) *remote { |
| return &remote{ |
| subcommands: subcommands{ |
| &listSessions{app: app}, |
| &startDebugging{app: app}, |
| }, |
| alias: alias, |
| } |
| } |
| |
| func (r *remote) Name() string { |
| if r.alias != "" { |
| return r.alias |
| } |
| return "remote" |
| } |
| |
| func (r *remote) ShortHelp() string { |
| short := "interact with the gopls daemon" |
| if r.alias != "" { |
| short += " (deprecated: use 'remote')" |
| } |
| return short |
| } |
| |
| // listSessions is an inspect subcommand to list current sessions. |
| type listSessions struct { |
| app *Application |
| } |
| |
| func (c *listSessions) Name() string { return "sessions" } |
| func (c *listSessions) Usage() string { return "" } |
| func (c *listSessions) ShortHelp() string { |
| return "print information about current gopls sessions" |
| } |
| |
| const listSessionsExamples = ` |
| Examples: |
| |
| 1) list sessions for the default daemon: |
| |
| $ gopls -remote=auto remote sessions |
| or just |
| $ gopls remote sessions |
| |
| 2) list sessions for a specific daemon: |
| |
| $ gopls -remote=localhost:8082 remote sessions |
| ` |
| |
| func (c *listSessions) DetailedHelp(f *flag.FlagSet) { |
| fmt.Fprint(f.Output(), listSessionsExamples) |
| f.PrintDefaults() |
| } |
| |
| func (c *listSessions) Run(ctx context.Context, args ...string) error { |
| remote := c.app.Remote |
| if remote == "" { |
| remote = "auto" |
| } |
| state, err := lsprpc.QueryServerState(ctx, remote) |
| if err != nil { |
| return err |
| } |
| v, err := json.MarshalIndent(state, "", "\t") |
| if err != nil { |
| log.Fatal(err) |
| } |
| os.Stdout.Write(v) |
| return nil |
| } |
| |
| type startDebugging struct { |
| app *Application |
| } |
| |
| func (c *startDebugging) Name() string { return "debug" } |
| func (c *startDebugging) Usage() string { return "[host:port]" } |
| func (c *startDebugging) ShortHelp() string { |
| return "start the debug server" |
| } |
| |
| const startDebuggingExamples = ` |
| Examples: |
| |
| 1) start a debug server for the default daemon, on an arbitrary port: |
| |
| $ gopls -remote=auto remote debug |
| or just |
| $ gopls remote debug |
| |
| 2) start for a specific daemon, on a specific port: |
| |
| $ gopls -remote=localhost:8082 remote debug localhost:8083 |
| ` |
| |
| func (c *startDebugging) DetailedHelp(f *flag.FlagSet) { |
| fmt.Fprint(f.Output(), startDebuggingExamples) |
| f.PrintDefaults() |
| } |
| |
| func (c *startDebugging) Run(ctx context.Context, args ...string) error { |
| if len(args) > 1 { |
| fmt.Fprintln(os.Stderr, c.Usage()) |
| return errors.New("invalid usage") |
| } |
| remote := c.app.Remote |
| if remote == "" { |
| remote = "auto" |
| } |
| debugAddr := "" |
| if len(args) > 0 { |
| debugAddr = args[0] |
| } |
| debugArgs := command.DebuggingArgs{ |
| Addr: debugAddr, |
| } |
| var result command.DebuggingResult |
| if err := lsprpc.ExecuteCommand(ctx, remote, command.StartDebugging.ID(), debugArgs, &result); err != nil { |
| return err |
| } |
| if len(result.URLs) == 0 { |
| return errors.New("no debugging URLs") |
| } |
| for _, url := range result.URLs { |
| fmt.Printf("debugging on %s\n", url) |
| } |
| return nil |
| } |