// 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 protocol

// This file defines constants for non-standard CodeActions and CodeLenses.

// CodeAction kinds specific to gopls
//
// See tsprotocol.go for LSP standard kinds, including
//
//	"quickfix"
//	"refactor"
//	"refactor.extract"
//	"refactor.inline"
//	"refactor.move"
//	"refactor.rewrite"
//	"source"
//	"source.organizeImports"
//	"source.fixAll"
//	"notebook"
//
// The effects of CodeActionKind on the behavior of VS Code are
// baffling and undocumented. Here's what we have observed.
//
// Clicking on the "Refactor..." menu item shows a submenu of actions
// with kind="refactor.*", and clicking on "Source action..." shows
// actions with kind="source.*". A lightbulb appears in both cases.
// A third menu, "Quick fix...", not found on the usual context
// menu but accessible through the command palette or "⌘.",
// displays code actions of kind "quickfix.*" and "refactor.*".
// All of these CodeAction requests have triggerkind=Invoked.
//
// Cursor motion also performs a CodeAction request, but with
// triggerkind=Automatic. Even if this returns a mix of action kinds,
// only the "refactor" and "quickfix" actions seem to matter.
// A lightbulb appears if that subset of actions is non-empty, and the
// menu displays them. (This was noisy--see #65167--so gopls now only
// reports diagnostic-associated code actions if kind is Invoked or
// missing.)
//
// None of these CodeAction requests specifies a "kind" restriction;
// the filtering is done on the response, by the client.
//
// In all these menus, VS Code organizes the actions' menu items
// into groups based on their kind, with hardwired captions such as
// "Extract", "Inline", "More actions", and "Quick fix".
//
// The special category "source.fixAll" is intended for actions that
// are unambiguously safe to apply so that clients may automatically
// apply all actions matching this category on save. (That said, this
// is not VS Code's default behavior; see editor.codeActionsOnSave.)
//
// TODO(adonovan): the intent of CodeActionKind is a hierarchy. We
// should changes gopls so that we don't create instances of the
// predefined kinds directly, but treat them as interfaces.
//
// For example,
//
//	instead of:		we should create:
//	refactor.extract	refactor.extract.const
//				refactor.extract.var
//				refactor.extract.func
//	refactor.rewrite	refactor.rewrite.fillstruct
//				refactor.rewrite.unusedparam
//	quickfix		quickfix.govulncheck.reset
//				quickfix.govulncheck.upgrade
//
// etc, so that client editors and scripts can be more specific in
// their requests.
//
// This entails that we use a segmented-path matching operator
// instead of == for CodeActionKinds throughout gopls.
// See golang/go#40438 for related discussion.
const (
	GoTest        CodeActionKind = "goTest"
	GoDoc         CodeActionKind = "source.doc"
	GoFreeSymbols CodeActionKind = "source.freesymbols"
)

// A CodeLensSource identifies an (algorithmic) source of code lenses.
type CodeLensSource string

// CodeLens sources
//
// These identifiers appear in the "codelenses" configuration setting,
// and in the user documentation thereof, which is generated by
// gopls/doc/generate/generate.go parsing this file.
//
// Doc comments should use GitHub Markdown.
// The first line becomes the title.
//
// (For historical reasons, each code lens source identifier typically
// matches the name of one of the command.Commands returned by it,
// but that isn't essential.)
const (
	// Toggle display of Go compiler optimization decisions
	//
	// This codelens source causes the `package` declaration of
	// each file to be annotated with a command to toggle the
	// state of the per-session variable that controls whether
	// optimization decisions from the Go compiler (formerly known
	// as "gc") should be displayed as diagnostics.
	//
	// Optimization decisions include:
	// - whether a variable escapes, and how escape is inferred;
	// - whether a nil-pointer check is implied or eliminated;
	// - whether a function can be inlined.
	//
	// TODO(adonovan): this source is off by default because the
	// annotation is annoying and because VS Code has a separate
	// "Toggle gc details" command. Replace it with a Code Action
	// ("Source action...").
	CodeLensGCDetails CodeLensSource = "gc_details"

	// Run `go generate`
	//
	// This codelens source annotates any `//go:generate` comments
	// with commands to run `go generate` in this directory, on
	// all directories recursively beneath this one.
	//
	// See [Generating code](https://go.dev/blog/generate) for
	// more details.
	CodeLensGenerate CodeLensSource = "generate"

	// Re-generate cgo declarations
	//
	// This codelens source annotates an `import "C"` declaration
	// with a command to re-run the [cgo
	// command](https://pkg.go.dev/cmd/cgo) to regenerate the
	// corresponding Go declarations.
	//
	// Use this after editing the C code in comments attached to
	// the import, or in C header files included by it.
	CodeLensRegenerateCgo CodeLensSource = "regenerate_cgo"

	// Run govulncheck
	//
	// This codelens source annotates the `module` directive in a
	// go.mod file with a command to run Govulncheck.
	//
	// [Govulncheck](https://go.dev/blog/vuln) is a static
	// analysis tool that computes the set of functions reachable
	// within your application, including dependencies;
	// queries a database of known security vulnerabilities; and
	// reports any potential problems it finds.
	CodeLensRunGovulncheck CodeLensSource = "run_govulncheck"

	// Run tests and benchmarks
	//
	// This codelens source annotates each `Test` and `Benchmark`
	// function in a `*_test.go` file with a command to run it.
	//
	// This source is off by default because VS Code has
	// a client-side custom UI for testing, and because progress
	// notifications are not a great UX for streamed test output.
	// See:
	// - golang/go#67400 for a discussion of this feature.
	// - https://github.com/joaotavora/eglot/discussions/1402
	//   for an alternative approach.
	CodeLensTest CodeLensSource = "test"

	// Tidy go.mod file
	//
	// This codelens source annotates the `module` directive in a
	// go.mod file with a command to run [`go mod
	// tidy`](https://go.dev/ref/mod#go-mod-tidy), which ensures
	// that the go.mod file matches the source code in the module.
	CodeLensTidy CodeLensSource = "tidy"

	// Update dependencies
	//
	// This codelens source annotates the `module` directive in a
	// go.mod file with commands to:
	//
	// - check for available upgrades,
	// - upgrade direct dependencies, and
	// - upgrade all dependencies transitively.
	CodeLensUpgradeDependency CodeLensSource = "upgrade_dependency"

	// Update vendor directory
	//
	// This codelens source annotates the `module` directive in a
	// go.mod file with a command to run [`go mod
	// vendor`](https://go.dev/ref/mod#go-mod-vendor), which
	// creates or updates the directory named `vendor` in the
	// module root so that it contains an up-to-date copy of all
	// necessary package dependencies.
	CodeLensVendor CodeLensSource = "vendor"
)
