internal/lsp/command: add missing doc and support for result parameters

This CL cleans up doc/commands.md to include missing command
documentation and add support for result parameters.

Included are some quick-and-dirty extensions to the command metadata
loader that handle slices and arrays of struct types.

Change-Id: I43a85e88c9c53e21b790d89a45a9de444addcc63
Reviewed-on: https://go-review.googlesource.com/c/tools/+/326909
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
diff --git a/internal/lsp/source/api_json.go b/internal/lsp/source/api_json.go
index 2d7db9a..f87aadc 100755
--- a/internal/lsp/source/api_json.go
+++ b/internal/lsp/source/api_json.go
@@ -731,124 +731,144 @@
 	},
 	Commands: []*CommandJSON{
 		{
-			Command: "gopls.add_dependency",
-			Title:   "Add dependency",
-			Doc:     "Adds a dependency to the go.mod file for a module.",
-			ArgDoc:  "{\n\t// The go.mod file URI.\n\t\"URI\": string,\n\t// Additional args to pass to the go command.\n\t\"GoCmdArgs\": []string,\n\t// Whether to add a require directive.\n\t\"AddRequire\": bool,\n}",
+			Command:   "gopls.add_dependency",
+			Title:     "Add a dependency",
+			Doc:       "Adds a dependency to the go.mod file for a module.",
+			ArgDoc:    "{\n\t// The go.mod file URI.\n\t\"URI\": string,\n\t// Additional args to pass to the go command.\n\t\"GoCmdArgs\": []string,\n\t// Whether to add a require directive.\n\t\"AddRequire\": bool,\n}",
+			ResultDoc: "",
 		},
 		{
-			Command: "gopls.add_import",
-			Title:   "asks the server to add an import path to a given Go file.",
-			Doc:     "The method will call applyEdit on the client so that clients don't have\nto apply the edit themselves.",
-			ArgDoc:  "{\n\t// ImportPath is the target import path that should\n\t// be added to the URI file\n\t\"ImportPath\": string,\n\t// URI is the file that the ImportPath should be\n\t// added to\n\t\"URI\": string,\n}",
+			Command:   "gopls.add_import",
+			Title:     "Add an import",
+			Doc:       "Ask the server to add an import path to a given Go file.  The method will\ncall applyEdit on the client so that clients don't have to apply the edit\nthemselves.",
+			ArgDoc:    "{\n\t// ImportPath is the target import path that should\n\t// be added to the URI file\n\t\"ImportPath\": string,\n\t// URI is the file that the ImportPath should be\n\t// added to\n\t\"URI\": string,\n}",
+			ResultDoc: "",
 		},
 		{
-			Command: "gopls.apply_fix",
-			Title:   "Apply a fix",
-			Doc:     "Applies a fix to a region of source code.",
-			ArgDoc:  "{\n\t// The fix to apply.\n\t\"Fix\": string,\n\t// The file URI for the document to fix.\n\t\"URI\": string,\n\t// The document range to scan for fixes.\n\t\"Range\": {\n\t\t\"start\": {\n\t\t\t\"line\": uint32,\n\t\t\t\"character\": uint32,\n\t\t},\n\t\t\"end\": {\n\t\t\t\"line\": uint32,\n\t\t\t\"character\": uint32,\n\t\t},\n\t},\n}",
+			Command:   "gopls.apply_fix",
+			Title:     "Apply a fix",
+			Doc:       "Applies a fix to a region of source code.",
+			ArgDoc:    "{\n\t// The fix to apply.\n\t\"Fix\": string,\n\t// The file URI for the document to fix.\n\t\"URI\": string,\n\t// The document range to scan for fixes.\n\t\"Range\": {\n\t\t\"start\": {\n\t\t\t\"line\": uint32,\n\t\t\t\"character\": uint32,\n\t\t},\n\t\t\"end\": {\n\t\t\t\"line\": uint32,\n\t\t\t\"character\": uint32,\n\t\t},\n\t},\n}",
+			ResultDoc: "",
 		},
 		{
-			Command: "gopls.check_upgrades",
-			Title:   "Check for upgrades",
-			Doc:     "Checks for module upgrades.",
-			ArgDoc:  "{\n\t// The go.mod file URI.\n\t\"URI\": string,\n\t// The modules to check.\n\t\"Modules\": []string,\n}",
+			Command:   "gopls.check_upgrades",
+			Title:     "Check for upgrades",
+			Doc:       "Checks for module upgrades.",
+			ArgDoc:    "{\n\t// The go.mod file URI.\n\t\"URI\": string,\n\t// The modules to check.\n\t\"Modules\": []string,\n}",
+			ResultDoc: "",
 		},
 		{
-			Command: "gopls.gc_details",
-			Title:   "Toggle gc_details",
-			Doc:     "Toggle the calculation of gc annotations.",
-			ArgDoc:  "string",
+			Command:   "gopls.gc_details",
+			Title:     "Toggle gc_details",
+			Doc:       "Toggle the calculation of gc annotations.",
+			ArgDoc:    "string",
+			ResultDoc: "",
 		},
 		{
-			Command: "gopls.generate",
-			Title:   "Run go generate",
-			Doc:     "Runs `go generate` for a given directory.",
-			ArgDoc:  "{\n\t// URI for the directory to generate.\n\t\"Dir\": string,\n\t// Whether to generate recursively (go generate ./...)\n\t\"Recursive\": bool,\n}",
+			Command:   "gopls.generate",
+			Title:     "Run go generate",
+			Doc:       "Runs `go generate` for a given directory.",
+			ArgDoc:    "{\n\t// URI for the directory to generate.\n\t\"Dir\": string,\n\t// Whether to generate recursively (go generate ./...)\n\t\"Recursive\": bool,\n}",
+			ResultDoc: "",
 		},
 		{
-			Command: "gopls.generate_gopls_mod",
-			Title:   "Generate gopls.mod",
-			Doc:     "(Re)generate the gopls.mod file for a workspace.",
-			ArgDoc:  "{\n\t// The file URI.\n\t\"URI\": string,\n}",
+			Command:   "gopls.generate_gopls_mod",
+			Title:     "Generate gopls.mod",
+			Doc:       "(Re)generate the gopls.mod file for a workspace.",
+			ArgDoc:    "{\n\t// The file URI.\n\t\"URI\": string,\n}",
+			ResultDoc: "",
 		},
 		{
-			Command: "gopls.go_get_package",
-			Title:   "go get package",
-			Doc:     "Runs `go get` to fetch a package.",
-			ArgDoc:  "{\n\t// Any document URI within the relevant module.\n\t\"URI\": string,\n\t// The package to go get.\n\t\"Pkg\": string,\n\t\"AddRequire\": bool,\n}",
+			Command:   "gopls.go_get_package",
+			Title:     "go get a package",
+			Doc:       "Runs `go get` to fetch a package.",
+			ArgDoc:    "{\n\t// Any document URI within the relevant module.\n\t\"URI\": string,\n\t// The package to go get.\n\t\"Pkg\": string,\n\t\"AddRequire\": bool,\n}",
+			ResultDoc: "",
 		},
 		{
-			Command: "gopls.list_known_packages",
-			Title:   "retrieves a list of packages",
-			Doc:     "that are importable from the given URI.",
-			ArgDoc:  "{\n\t// The file URI.\n\t\"URI\": string,\n}",
+			Command:   "gopls.list_known_packages",
+			Title:     "List known packages",
+			Doc:       "Retrieve a list of packages that are importable from the given URI.",
+			ArgDoc:    "{\n\t// The file URI.\n\t\"URI\": string,\n}",
+			ResultDoc: "{\n\t// Packages is a list of packages relative\n\t// to the URIArg passed by the command request.\n\t// In other words, it omits paths that are already\n\t// imported or cannot be imported due to compiler\n\t// restrictions.\n\t\"Packages\": []string,\n}",
 		},
 		{
-			Command: "gopls.regenerate_cgo",
-			Title:   "Regenerate cgo",
-			Doc:     "Regenerates cgo definitions.",
-			ArgDoc:  "{\n\t// The file URI.\n\t\"URI\": string,\n}",
+			Command:   "gopls.regenerate_cgo",
+			Title:     "Regenerate cgo",
+			Doc:       "Regenerates cgo definitions.",
+			ArgDoc:    "{\n\t// The file URI.\n\t\"URI\": string,\n}",
+			ResultDoc: "",
 		},
 		{
-			Command: "gopls.remove_dependency",
-			Title:   "Remove dependency",
-			Doc:     "Removes a dependency from the go.mod file of a module.",
-			ArgDoc:  "{\n\t// The go.mod file URI.\n\t\"URI\": string,\n\t// The module path to remove.\n\t\"ModulePath\": string,\n\t\"OnlyDiagnostic\": bool,\n}",
+			Command:   "gopls.remove_dependency",
+			Title:     "Remove a dependency",
+			Doc:       "Removes a dependency from the go.mod file of a module.",
+			ArgDoc:    "{\n\t// The go.mod file URI.\n\t\"URI\": string,\n\t// The module path to remove.\n\t\"ModulePath\": string,\n\t\"OnlyDiagnostic\": bool,\n}",
+			ResultDoc: "",
 		},
 		{
-			Command: "gopls.run_tests",
-			Title:   "Run test(s)",
-			Doc:     "Runs `go test` for a specific set of test or benchmark functions.",
-			ArgDoc:  "{\n\t// The test file containing the tests to run.\n\t\"URI\": string,\n\t// Specific test names to run, e.g. TestFoo.\n\t\"Tests\": []string,\n\t// Specific benchmarks to run, e.g. BenchmarkFoo.\n\t\"Benchmarks\": []string,\n}",
+			Command:   "gopls.run_tests",
+			Title:     "Run test(s)",
+			Doc:       "Runs `go test` for a specific set of test or benchmark functions.",
+			ArgDoc:    "{\n\t// The test file containing the tests to run.\n\t\"URI\": string,\n\t// Specific test names to run, e.g. TestFoo.\n\t\"Tests\": []string,\n\t// Specific benchmarks to run, e.g. BenchmarkFoo.\n\t\"Benchmarks\": []string,\n}",
+			ResultDoc: "",
 		},
 		{
-			Command: "gopls.start_debugging",
-			Title:   "",
-			Doc:     "",
-			ArgDoc:  "{\n\t// Optional: the address (including port) for the debug server to listen on.\n\t// If not provided, the debug server will bind to \"localhost:0\", and the\n\t// full debug URL will be contained in the result.\n\t// \n\t// If there is more than one gopls instance along the serving path (i.e. you\n\t// are using a daemon), each gopls instance will attempt to start debugging.\n\t// If Addr specifies a port, only the daemon will be able to bind to that\n\t// port, and each intermediate gopls instance will fail to start debugging.\n\t// For this reason it is recommended not to specify a port (or equivalently,\n\t// to specify \":0\").\n\t// \n\t// If the server was already debugging this field has no effect, and the\n\t// result will contain the previously configured debug URL(s).\n\t\"Addr\": string,\n}",
+			Command:   "gopls.start_debugging",
+			Title:     "Start the gopls debug server if it isn't running, and",
+			Doc:       "return the debug address.",
+			ArgDoc:    "{\n\t// Optional: the address (including port) for the debug server to listen on.\n\t// If not provided, the debug server will bind to \"localhost:0\", and the\n\t// full debug URL will be contained in the result.\n\t// \n\t// If there is more than one gopls instance along the serving path (i.e. you\n\t// are using a daemon), each gopls instance will attempt to start debugging.\n\t// If Addr specifies a port, only the daemon will be able to bind to that\n\t// port, and each intermediate gopls instance will fail to start debugging.\n\t// For this reason it is recommended not to specify a port (or equivalently,\n\t// to specify \":0\").\n\t// \n\t// If the server was already debugging this field has no effect, and the\n\t// result will contain the previously configured debug URL(s).\n\t\"Addr\": string,\n}",
+			ResultDoc: "{\n\t// The URLs to use to access the debug servers, for all gopls instances in\n\t// the serving path. For the common case of a single gopls instance (i.e. no\n\t// daemon), this will be exactly one address.\n\t// \n\t// In the case of one or more gopls instances forwarding the LSP to a daemon,\n\t// URLs will contain debug addresses for each server in the serving path, in\n\t// serving order. The daemon debug address will be the last entry in the\n\t// slice. If any intermediate gopls instance fails to start debugging, no\n\t// error will be returned but the debug URL for that server in the URLs slice\n\t// will be empty.\n\t\"URLs\": []string,\n}",
 		},
 		{
-			Command: "gopls.test",
-			Title:   "Run test(s) (legacy)",
-			Doc:     "Runs `go test` for a specific set of test or benchmark functions.",
-			ArgDoc:  "string,\n[]string,\n[]string",
+			Command:   "gopls.test",
+			Title:     "Run test(s) (legacy)",
+			Doc:       "Runs `go test` for a specific set of test or benchmark functions.",
+			ArgDoc:    "string,\n[]string,\n[]string",
+			ResultDoc: "",
 		},
 		{
-			Command: "gopls.tidy",
-			Title:   "Run go mod tidy",
-			Doc:     "Runs `go mod tidy` for a module.",
-			ArgDoc:  "{\n\t// The file URIs.\n\t\"URIs\": []string,\n}",
+			Command:   "gopls.tidy",
+			Title:     "Run go mod tidy",
+			Doc:       "Runs `go mod tidy` for a module.",
+			ArgDoc:    "{\n\t// The file URIs.\n\t\"URIs\": []string,\n}",
+			ResultDoc: "",
 		},
 		{
-			Command: "gopls.toggle_gc_details",
-			Title:   "Toggle gc_details",
-			Doc:     "Toggle the calculation of gc annotations.",
-			ArgDoc:  "{\n\t// The file URI.\n\t\"URI\": string,\n}",
+			Command:   "gopls.toggle_gc_details",
+			Title:     "Toggle gc_details",
+			Doc:       "Toggle the calculation of gc annotations.",
+			ArgDoc:    "{\n\t// The file URI.\n\t\"URI\": string,\n}",
+			ResultDoc: "",
 		},
 		{
-			Command: "gopls.update_go_sum",
-			Title:   "Update go.sum",
-			Doc:     "Updates the go.sum file for a module.",
-			ArgDoc:  "{\n\t// The file URIs.\n\t\"URIs\": []string,\n}",
+			Command:   "gopls.update_go_sum",
+			Title:     "Update go.sum",
+			Doc:       "Updates the go.sum file for a module.",
+			ArgDoc:    "{\n\t// The file URIs.\n\t\"URIs\": []string,\n}",
+			ResultDoc: "",
 		},
 		{
-			Command: "gopls.upgrade_dependency",
-			Title:   "Upgrade dependency",
-			Doc:     "Upgrades a dependency in the go.mod file for a module.",
-			ArgDoc:  "{\n\t// The go.mod file URI.\n\t\"URI\": string,\n\t// Additional args to pass to the go command.\n\t\"GoCmdArgs\": []string,\n\t// Whether to add a require directive.\n\t\"AddRequire\": bool,\n}",
+			Command:   "gopls.upgrade_dependency",
+			Title:     "Upgrade a dependency",
+			Doc:       "Upgrades a dependency in the go.mod file for a module.",
+			ArgDoc:    "{\n\t// The go.mod file URI.\n\t\"URI\": string,\n\t// Additional args to pass to the go command.\n\t\"GoCmdArgs\": []string,\n\t// Whether to add a require directive.\n\t\"AddRequire\": bool,\n}",
+			ResultDoc: "",
 		},
 		{
-			Command: "gopls.vendor",
-			Title:   "Run go mod vendor",
-			Doc:     "Runs `go mod vendor` for a module.",
-			ArgDoc:  "{\n\t// The file URI.\n\t\"URI\": string,\n}",
+			Command:   "gopls.vendor",
+			Title:     "Run go mod vendor",
+			Doc:       "Runs `go mod vendor` for a module.",
+			ArgDoc:    "{\n\t// The file URI.\n\t\"URI\": string,\n}",
+			ResultDoc: "",
 		},
 		{
-			Command: "gopls.workspace_metadata",
-			Title:   "",
-			Doc:     "",
-			ArgDoc:  "",
+			Command:   "gopls.workspace_metadata",
+			Title:     "Query workspace metadata",
+			Doc:       "Query the server for information about active workspaces.",
+			ArgDoc:    "",
+			ResultDoc: "{\n\t// All workspaces for this session.\n\t\"Workspaces\": []{\n\t\t\"Name\": string,\n\t\t\"ModuleDir\": string,\n\t},\n}",
 		},
 	},
 	Lenses: []*LensJSON{
@@ -879,7 +899,7 @@
 		},
 		{
 			Lens:  "upgrade_dependency",
-			Title: "Upgrade dependency",
+			Title: "Upgrade a dependency",
 			Doc:   "Upgrades a dependency in the go.mod file for a module.",
 		},
 		{