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

import (
	"context"
	"encoding/json"
	"fmt"
	"go/ast"
	"go/token"
	"go/types"
	"reflect"
	"slices"
	"strings"

	goastutil "golang.org/x/tools/go/ast/astutil"
	"golang.org/x/tools/go/ast/edge"
	"golang.org/x/tools/go/ast/inspector"
	"golang.org/x/tools/gopls/internal/analysis/fillstruct"
	"golang.org/x/tools/gopls/internal/analysis/fillswitch"
	"golang.org/x/tools/gopls/internal/cache"
	"golang.org/x/tools/gopls/internal/cache/parsego"
	"golang.org/x/tools/gopls/internal/file"
	"golang.org/x/tools/gopls/internal/golang/stubmethods"
	"golang.org/x/tools/gopls/internal/label"
	"golang.org/x/tools/gopls/internal/protocol"
	"golang.org/x/tools/gopls/internal/protocol/command"
	"golang.org/x/tools/gopls/internal/settings"
	"golang.org/x/tools/internal/astutil"
	"golang.org/x/tools/internal/event"
	"golang.org/x/tools/internal/imports"
	"golang.org/x/tools/internal/typesinternal"
)

// CodeActions returns all enabled code actions (edits and other
// commands) available for the selected range.
//
// Depending on how the request was triggered, fewer actions may be
// offered, e.g. to avoid UI distractions after mere cursor motion.
//
// See ../protocol/codeactionkind.go for some code action theory.
func CodeActions(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, rng protocol.Range, diagnostics []protocol.Diagnostic, enabled func(protocol.CodeActionKind) bool, trigger protocol.CodeActionTriggerKind) (actions []protocol.CodeAction, _ error) {
	loc := fh.URI().Location(rng)

	pgf, err := snapshot.ParseGo(ctx, fh, parsego.Full)
	if err != nil {
		return nil, err
	}
	start, end, err := pgf.RangePos(rng)
	if err != nil {
		return nil, err
	}

	// Scan to see if any enabled producer needs type information.
	var enabledMemo [len(codeActionProducers)]bool
	needTypes := false
	for i, p := range codeActionProducers {
		if enabled(p.kind) {
			enabledMemo[i] = true
			if p.needPkg {
				needTypes = true
			}
		}
	}

	// Compute type information if needed.
	// Also update pgf, start, end to be consistent with pkg.
	// They may differ in case of parse cache miss.
	var pkg *cache.Package
	if needTypes {
		var err error
		pkg, pgf, err = NarrowestPackageForFile(ctx, snapshot, loc.URI)
		if err != nil {
			return nil, err
		}
		start, end, err = pgf.RangePos(loc.Range)
		if err != nil {
			return nil, err
		}
	}

	// Execute each enabled producer function.
	req := &codeActionsRequest{
		actions:     &actions,
		lazy:        make(map[reflect.Type]any),
		snapshot:    snapshot,
		fh:          fh,
		pgf:         pgf,
		loc:         loc,
		start:       start,
		end:         end,
		diagnostics: diagnostics,
		trigger:     trigger,
		pkg:         pkg,
	}
	for i, p := range codeActionProducers {
		if !enabledMemo[i] {
			continue
		}
		req.kind = p.kind
		if p.needPkg {
			req.pkg = pkg
		} else {
			req.pkg = nil
		}
		if err := p.fn(ctx, req); err != nil {
			// An error in one code action producer
			// should not affect the others.
			if ctx.Err() != nil {
				return nil, err
			}
			event.Error(ctx, fmt.Sprintf("CodeAction producer %s failed", p.kind), err)
			continue
		}
	}

	// Return code actions in the order their providers are listed.
	return actions, nil
}

// A codeActionsRequest is passed to each function
// that produces code actions.
type codeActionsRequest struct {
	// internal fields for use only by [CodeActions].
	actions *[]protocol.CodeAction // pointer to output slice; call addAction to populate
	lazy    map[reflect.Type]any   // lazy construction

	// inputs to the producer function:
	kind        protocol.CodeActionKind
	snapshot    *cache.Snapshot
	fh          file.Handle
	pgf         *parsego.File
	loc         protocol.Location
	start, end  token.Pos
	diagnostics []protocol.Diagnostic
	trigger     protocol.CodeActionTriggerKind
	pkg         *cache.Package // set only if producer.needPkg
}

// addApplyFixAction adds an ApplyFix command-based CodeAction to the result.
func (req *codeActionsRequest) addApplyFixAction(title, fix string, loc protocol.Location) {
	cmd := command.NewApplyFixCommand(title, command.ApplyFixArgs{
		Fix:          fix,
		Location:     loc,
		ResolveEdits: req.resolveEdits(),
	})
	req.addCommandAction(cmd, true)
}

// addCommandAction adds a CodeAction to the result based on the provided command.
//
// If allowResolveEdits (and the client supports codeAction/resolve)
// then the command is embedded into the code action data field so
// that the client can later ask the server to "resolve" a command
// into an edit that they can preview and apply selectively.
// IMPORTANT: set allowResolveEdits only for actions that are 'edit aware',
// meaning they can detect when they are being executed in the context of a
// codeAction/resolve request, and return edits rather than applying them using
// workspace/applyEdit. In golang/go#71405, edits were being apply during the
// codeAction/resolve request handler.
// TODO(rfindley): refactor the command and code lens registration APIs so that
// resolve edit support is inferred from the command signature, not dependent
// on coordination between codeAction and command logic.
//
// Otherwise, the command is set as the code action operation.
func (req *codeActionsRequest) addCommandAction(cmd *protocol.Command, allowResolveEdits bool) {
	act := protocol.CodeAction{
		Title: cmd.Title,
		Kind:  req.kind,
	}
	if allowResolveEdits && req.resolveEdits() {
		data, err := json.Marshal(cmd)
		if err != nil {
			panic("unable to marshal")
		}
		msg := json.RawMessage(data)
		act.Data = &msg
	} else {
		act.Command = cmd
	}
	req.addAction(act)
}

// addEditAction adds an edit-based CodeAction to the result.
func (req *codeActionsRequest) addEditAction(title string, fixedDiagnostics []protocol.Diagnostic, changes ...protocol.DocumentChange) {
	req.addAction(protocol.CodeAction{
		Title:       title,
		Kind:        req.kind,
		Diagnostics: fixedDiagnostics,
		Edit:        protocol.NewWorkspaceEdit(changes...),
	})
}

// addAction adds a code action to the response.
func (req *codeActionsRequest) addAction(act protocol.CodeAction) {
	*req.actions = append(*req.actions, act)
}

// resolveEdits reports whether the client can resolve edits lazily.
func (req *codeActionsRequest) resolveEdits() bool {
	opts := req.snapshot.Options()
	return opts.CodeActionResolveOptions != nil &&
		slices.Contains(opts.CodeActionResolveOptions, "edit")
}

// lazyInit[*T](ctx, req) returns a pointer to an instance of T,
// calling new(T).init(ctx.req) on the first request.
//
// It is conceptually a (generic) method of req.
func lazyInit[P interface {
	init(ctx context.Context, req *codeActionsRequest)
	*T
}, T any](ctx context.Context, req *codeActionsRequest) P {
	t := reflect.TypeFor[T]()
	v, ok := req.lazy[t].(P)
	if !ok {
		v = new(T)
		v.init(ctx, req)
		req.lazy[t] = v
	}
	return v
}

// -- producers --

// A codeActionProducer describes a function that produces CodeActions
// of a particular kind.
// The function is only called if that kind is enabled.
type codeActionProducer struct {
	kind    protocol.CodeActionKind
	fn      func(ctx context.Context, req *codeActionsRequest) error
	needPkg bool // fn needs type information (req.pkg)
}

// Code Actions are returned in the order their producers are listed below.
// Depending on the client, this may influence the order they appear in the UI.
var codeActionProducers = [...]codeActionProducer{
	{kind: protocol.QuickFix, fn: quickFix, needPkg: true},
	{kind: protocol.SourceOrganizeImports, fn: sourceOrganizeImports},
	{kind: settings.AddTest, fn: addTest, needPkg: true},
	{kind: settings.GoAssembly, fn: goAssembly, needPkg: true},
	{kind: settings.GoDoc, fn: goDoc, needPkg: true},
	{kind: settings.GoFreeSymbols, fn: goFreeSymbols},
	{kind: settings.GoSplitPackage, fn: goSplitPackage, needPkg: true},
	{kind: settings.GoTest, fn: goTest, needPkg: true},
	{kind: settings.GoToggleCompilerOptDetails, fn: toggleCompilerOptDetails},
	{kind: settings.RefactorExtractFunction, fn: refactorExtractFunction},
	{kind: settings.RefactorExtractMethod, fn: refactorExtractMethod},
	{kind: settings.RefactorExtractToNewFile, fn: refactorExtractToNewFile},
	{kind: settings.RefactorExtractConstant, fn: refactorExtractVariable, needPkg: true},
	{kind: settings.RefactorExtractVariable, fn: refactorExtractVariable, needPkg: true},
	{kind: settings.RefactorExtractConstantAll, fn: refactorExtractVariableAll, needPkg: true},
	{kind: settings.RefactorExtractVariableAll, fn: refactorExtractVariableAll, needPkg: true},
	{kind: settings.RefactorInlineCall, fn: refactorInlineCall, needPkg: true},
	{kind: settings.RefactorInlineVariable, fn: refactorInlineVariable, needPkg: true},
	// {kind: settings.RefactorMoveType, fn: refactorMoveType, needPkg: true},
	{kind: settings.RefactorRewriteChangeQuote, fn: refactorRewriteChangeQuote},
	{kind: settings.RefactorRewriteFillStruct, fn: refactorRewriteFillStruct, needPkg: true},
	{kind: settings.RefactorRewriteFillSwitch, fn: refactorRewriteFillSwitch, needPkg: true},
	{kind: settings.RefactorRewriteInvertIf, fn: refactorRewriteInvertIf},
	{kind: settings.RefactorRewriteJoinLines, fn: refactorRewriteJoinLines, needPkg: true},
	{kind: settings.RefactorRewriteRemoveUnusedParam, fn: refactorRewriteRemoveUnusedParam, needPkg: true},
	{kind: settings.RefactorRewriteMoveParamLeft, fn: refactorRewriteMoveParamLeft, needPkg: true},
	{kind: settings.RefactorRewriteMoveParamRight, fn: refactorRewriteMoveParamRight, needPkg: true},
	{kind: settings.RefactorRewriteSplitLines, fn: refactorRewriteSplitLines, needPkg: true},
	{kind: settings.RefactorRewriteEliminateDotImport, fn: refactorRewriteEliminateDotImport, needPkg: true},
	{kind: settings.RefactorRewriteAddTags, fn: refactorRewriteAddStructTags, needPkg: true},
	{kind: settings.RefactorRewriteRemoveTags, fn: refactorRewriteRemoveStructTags, needPkg: true},
	{kind: settings.GoplsDocFeatures, fn: goplsDocFeatures}, // offer this one last (#72742)

	// Note: don't forget to update the allow-list in Server.CodeAction
	// when adding new query operations like GoTest and GoDoc that
	// are permitted even in generated source files.
}

// sourceOrganizeImports produces "Organize Imports" code actions.
func sourceOrganizeImports(ctx context.Context, req *codeActionsRequest) error {
	res := lazyInit[*allImportsFixesResult](ctx, req)

	// Send all of the import edits as one code action
	// if the file is being organized.
	if len(res.allFixEdits) > 0 {
		req.addEditAction("Organize Imports", nil, protocol.DocumentChangeEdit(req.fh, res.allFixEdits))
	}

	return nil
}

// quickFix produces code actions that fix errors,
// for example by adding/deleting/renaming imports,
// or declaring the missing methods of a type.
func quickFix(ctx context.Context, req *codeActionsRequest) error {
	// Only compute quick fixes if there are any diagnostics to fix.
	if len(req.diagnostics) == 0 {
		return nil
	}

	// Process any missing imports and pair them with the diagnostics they fix.
	res := lazyInit[*allImportsFixesResult](ctx, req)
	if res.err != nil {
		return nil
	}

	// Separate this into a set of codeActions per diagnostic, where
	// each action is the addition, removal, or renaming of one import.
	for _, importFix := range res.editsPerFix {
		fixedDiags := fixedByImportFix(importFix.fix, req.diagnostics)
		if len(fixedDiags) == 0 {
			continue
		}
		req.addEditAction(importFixTitle(importFix.fix), fixedDiags, protocol.DocumentChangeEdit(req.fh, importFix.edits))
	}

	// Quick fixes for type errors.
	info := req.pkg.TypesInfo()
	for _, typeError := range req.pkg.TypeErrors() {
		// Does type error overlap with CodeAction range?
		start, end := typeError.Pos, typeError.Pos
		if _, _, endPos, ok := typesinternal.ErrorCodeStartEnd(typeError); ok {
			end = endPos
		}
		typeErrorRange, err := req.pgf.PosRange(start, end)
		if err != nil || !protocol.Intersect(typeErrorRange, req.loc.Range) {
			continue
		}

		msg := typeError.Msg
		switch {
		// "Missing method" error? (stubmethods)
		// Offer a "Declare missing methods of INTERFACE" code action.
		// See [stubMissingInterfaceMethodsFixer] for command implementation.
		case strings.Contains(msg, "missing method"),
			strings.HasPrefix(msg, "cannot convert"),
			strings.Contains(msg, "not implement"):
			si := stubmethods.GetIfaceStubInfo(req.pkg.FileSet(), info, req.pgf, start, end)
			if si != nil {
				qual := typesinternal.FileQualifier(req.pgf.File, si.Concrete.Obj().Pkg())
				iface := types.TypeString(si.Interface.Type(), qual)
				msg := fmt.Sprintf("Declare missing methods of %s", iface)
				req.addApplyFixAction(msg, fixMissingInterfaceMethods, req.loc)
			}

		// "type X has no field or method Y" compiler error.
		// Offer a "Declare missing method T.f" code action.
		// See [stubMissingCalledFunctionFixer] for command implementation.
		case strings.Contains(msg, "has no field or method"):
			si := stubmethods.GetCallStubInfo(req.pkg.FileSet(), info, req.pgf, start, end)
			if si != nil {
				msg := fmt.Sprintf("Declare missing method %s.%s", si.Receiver.Obj().Name(), si.MethodName)
				req.addApplyFixAction(msg, fixMissingCalledFunction, req.loc)
			}

		// "undeclared name: X" or "undefined: X" compiler error.
		// Offer a "Create variable/function X" code action.
		// See [createUndeclared] for command implementation.
		case strings.HasPrefix(msg, "undeclared name: "),
			strings.HasPrefix(msg, "undefined: "):
			cur, _ := req.pgf.Cursor().FindByPos(start, end)
			title := undeclaredFixTitle(cur, msg)
			if title != "" {
				req.addApplyFixAction(title, fixCreateUndeclared, req.loc)
			}
		}
	}

	return nil
}

// allImportsFixesResult is the result of a lazy call to allImportsFixes.
// It implements the codeActionsRequest lazyInit interface.
type allImportsFixesResult struct {
	allFixEdits []protocol.TextEdit
	editsPerFix []*importFix
	err         error
}

func (res *allImportsFixesResult) init(ctx context.Context, req *codeActionsRequest) {
	res.allFixEdits, res.editsPerFix, res.err = allImportsFixes(ctx, req.snapshot, req.pgf)
	if res.err != nil {
		event.Error(ctx, "imports fixes", res.err, label.File.Of(req.loc.URI.Path()))
	}
}

func importFixTitle(fix *imports.ImportFix) string {
	var str string
	switch fix.FixType {
	case imports.AddImport:
		str = fmt.Sprintf("Add import: %s %q", fix.StmtInfo.Name, fix.StmtInfo.ImportPath)
	case imports.DeleteImport:
		str = fmt.Sprintf("Delete import: %s %q", fix.StmtInfo.Name, fix.StmtInfo.ImportPath)
	case imports.SetImportName:
		str = fmt.Sprintf("Rename import: %s %q", fix.StmtInfo.Name, fix.StmtInfo.ImportPath)
	}
	return str
}

// fixedByImportFix filters the provided slice of diagnostics to those that
// would be fixed by the provided imports fix.
func fixedByImportFix(fix *imports.ImportFix, diagnostics []protocol.Diagnostic) []protocol.Diagnostic {
	var results []protocol.Diagnostic
	for _, diagnostic := range diagnostics {
		switch {
		// "undeclared name: X" may be an unresolved import.
		case strings.HasPrefix(diagnostic.Message, "undeclared name: "):
			ident := strings.TrimPrefix(diagnostic.Message, "undeclared name: ")
			if ident == fix.IdentName {
				results = append(results, diagnostic)
			}
		// "undefined: X" may be an unresolved import at Go 1.20+.
		case strings.HasPrefix(diagnostic.Message, "undefined: "):
			ident := strings.TrimPrefix(diagnostic.Message, "undefined: ")
			if ident == fix.IdentName {
				results = append(results, diagnostic)
			}
		// "could not import: X" may be an invalid import.
		case strings.HasPrefix(diagnostic.Message, "could not import: "):
			ident := strings.TrimPrefix(diagnostic.Message, "could not import: ")
			if ident == fix.IdentName {
				results = append(results, diagnostic)
			}
		// "X imported but not used" is an unused import.
		// "X imported but not used as Y" is an unused import.
		case strings.Contains(diagnostic.Message, " imported but not used"):
			idx := strings.Index(diagnostic.Message, " imported but not used")
			importPath := diagnostic.Message[:idx]
			if importPath == fmt.Sprintf("%q", fix.StmtInfo.ImportPath) {
				results = append(results, diagnostic)
			}
		}
	}
	return results
}

// goFreeSymbols produces "Browse free symbols" code actions.
// See [server.commandHandler.FreeSymbols] for command implementation.
func goFreeSymbols(ctx context.Context, req *codeActionsRequest) error {
	if !req.loc.Empty() {
		cmd := command.NewFreeSymbolsCommand("Browse free symbols", req.snapshot.View().ID(), req.loc)
		req.addCommandAction(cmd, false)
	}
	return nil
}

// goSplitPackage produces "Split package p" code actions.
// See [server.commandHandler.SplitPackage] for command implementation.
func goSplitPackage(ctx context.Context, req *codeActionsRequest) error {
	// TODO(adonovan): ideally we would key by the package path,
	// or the ID of the widest package for the current file,
	// so that we don't see different results when toggling
	// between p.go and p_test.go.
	//
	// TODO(adonovan): opt: req should always provide metadata so
	// that we don't have to request type checking (needPkg=true).
	meta := req.pkg.Metadata()
	title := fmt.Sprintf("Split package %q", meta.Name)
	cmd := command.NewSplitPackageCommand(title, req.snapshot.View().ID(), string(meta.ID))
	req.addCommandAction(cmd, false)
	return nil
}

// goplsDocFeatures produces "Browse gopls feature documentation" code actions.
// See [server.commandHandler.ClientOpenURL] for command implementation.
func goplsDocFeatures(ctx context.Context, req *codeActionsRequest) error {
	cmd := command.NewClientOpenURLCommand(
		"Browse gopls feature documentation",
		"https://go.dev/gopls/features")
	req.addCommandAction(cmd, false)
	return nil
}

// goDoc produces "Browse documentation for X" code actions.
// See [server.commandHandler.Doc] for command implementation.
func goDoc(ctx context.Context, req *codeActionsRequest) error {
	_, _, title := DocFragment(req.pkg, req.pgf, req.start, req.end)
	if title != "" {
		cmd := command.NewDocCommand(title, command.DocArgs{Location: req.loc, ShowDocument: true})
		req.addCommandAction(cmd, false)
	}
	return nil
}

// refactorExtractFunction produces "Extract function" code actions.
// See [extractFunction] for command implementation.
func refactorExtractFunction(ctx context.Context, req *codeActionsRequest) error {
	if _, ok, _, _ := canExtractFunction(req.pgf.Cursor(), req.start, req.end); ok {
		req.addApplyFixAction("Extract function", fixExtractFunction, req.loc)
	}
	return nil
}

// refactorExtractMethod produces "Extract method" code actions.
// See [extractMethod] for command implementation.
func refactorExtractMethod(ctx context.Context, req *codeActionsRequest) error {
	if _, ok, methodOK, _ := canExtractFunction(req.pgf.Cursor(), req.start, req.end); ok && methodOK {
		req.addApplyFixAction("Extract method", fixExtractMethod, req.loc)
	}
	return nil
}

// refactorExtractVariable produces "Extract variable|constant" code actions.
// See [extractVariable] for command implementation.
func refactorExtractVariable(ctx context.Context, req *codeActionsRequest) error {
	info := req.pkg.TypesInfo()
	if curExprs, err := canExtractVariable(info, req.pgf.Cursor(), req.start, req.end, false); err == nil && len(curExprs) > 0 {
		// Offer one of refactor.extract.{constant,variable}
		// based on the constness of the expression; this is a
		// limitation of the codeActionProducers mechanism.
		// Beware that future evolutions of the refactorings
		// may make them diverge to become non-complementary,
		// for example because "if const x = ...; y {" is illegal.
		// Same as [refactorExtractVariableAll].
		expr0 := curExprs[0].Node().(ast.Expr)
		constant := info.Types[expr0].Value != nil
		if (req.kind == settings.RefactorExtractConstant) == constant {
			title := "Extract variable"
			if constant {
				title = "Extract constant"
			}
			req.addApplyFixAction(title, fixExtractVariable, req.loc)
		}
	}
	return nil
}

// refactorExtractVariableAll produces "Extract N occurrences of EXPR" code action.
// See [extractVariable] for implementation.
func refactorExtractVariableAll(ctx context.Context, req *codeActionsRequest) error {
	info := req.pkg.TypesInfo()
	// Don't suggest if only one expr is found,
	// otherwise it will duplicate with [refactorExtractVariable]
	if curExprs, err := canExtractVariable(info, req.pgf.Cursor(), req.start, req.end, true); err == nil && len(curExprs) > 1 {
		expr0 := curExprs[0].Node().(ast.Expr)
		text, err := req.pgf.NodeText(expr0)
		if err != nil {
			return err
		}
		desc := string(text)
		if len(desc) >= 40 || strings.Contains(desc, "\n") {
			desc = goastutil.NodeDescription(expr0)
		}
		constant := info.Types[expr0].Value != nil
		if (req.kind == settings.RefactorExtractConstantAll) == constant {
			var title string
			if constant {
				title = fmt.Sprintf("Extract %d occurrences of const expression: %s", len(curExprs), desc)
			} else {
				title = fmt.Sprintf("Extract %d occurrences of %s", len(curExprs), desc)
			}
			req.addApplyFixAction(title, fixExtractVariableAll, req.loc)
		}
	}
	return nil
}

// refactorExtractToNewFile produces "Extract declarations to new file" code actions.
// See [server.commandHandler.ExtractToNewFile] for command implementation.
func refactorExtractToNewFile(ctx context.Context, req *codeActionsRequest) error {
	if canExtractToNewFile(req.pgf, req.start, req.end) {
		cmd := command.NewExtractToNewFileCommand("Extract declarations to new file", req.loc)
		req.addCommandAction(cmd, false)
	}
	return nil
}

// addTest produces "Add test for FUNC" code actions.
// See [server.commandHandler.AddTest] for command implementation.
func addTest(ctx context.Context, req *codeActionsRequest) error {
	// Reject test package.
	if req.pkg.Metadata().ForTest != "" {
		return nil
	}

	path, _ := goastutil.PathEnclosingInterval(req.pgf.File, req.start, req.end)
	if len(path) < 2 {
		return nil
	}

	decl, ok := path[len(path)-2].(*ast.FuncDecl)
	if !ok {
		return nil
	}

	// Don't offer to create tests of "init" or "_".
	if decl.Name.Name == "_" || decl.Name.Name == "init" {
		return nil
	}

	// TODO(hxjiang): support functions with type parameter.
	if decl.Type.TypeParams != nil {
		return nil
	}

	cmd := command.NewAddTestCommand("Add test for "+decl.Name.String(), req.loc)
	req.addCommandAction(cmd, false)

	// TODO(hxjiang): add code action for generate test for package/file.
	return nil
}

// identityTransform returns a change signature transformation that leaves the
// given fieldlist unmodified.
func identityTransform(fields *ast.FieldList) []command.ChangeSignatureParam {
	var id []command.ChangeSignatureParam
	for i := 0; i < fields.NumFields(); i++ {
		id = append(id, command.ChangeSignatureParam{OldIndex: i})
	}
	return id
}

// refactorRewriteRemoveUnusedParam produces "Remove unused parameter" code actions.
// See [server.commandHandler.ChangeSignature] for command implementation.
func refactorRewriteRemoveUnusedParam(ctx context.Context, req *codeActionsRequest) error {
	if info := removableParameter(req.pkg, req.pgf, req.loc.Range); info != nil {
		var transform []command.ChangeSignatureParam
		for i := 0; i < info.decl.Type.Params.NumFields(); i++ {
			if i != info.paramIndex {
				transform = append(transform, command.ChangeSignatureParam{OldIndex: i})
			}
		}
		cmd := command.NewChangeSignatureCommand("Remove unused parameter", command.ChangeSignatureArgs{
			Location:     req.loc,
			NewParams:    transform,
			NewResults:   identityTransform(info.decl.Type.Results),
			ResolveEdits: req.resolveEdits(),
		})
		req.addCommandAction(cmd, true)
	}
	return nil
}

func refactorRewriteMoveParamLeft(ctx context.Context, req *codeActionsRequest) error {
	if info := findParam(req.pgf, req.loc.Range); info != nil &&
		info.paramIndex > 0 &&
		!is[*ast.Ellipsis](info.field.Type) {

		// ^^ we can't currently handle moving a variadic param.
		// TODO(rfindley): implement.

		transform := identityTransform(info.decl.Type.Params)
		transform[info.paramIndex] = command.ChangeSignatureParam{OldIndex: info.paramIndex - 1}
		transform[info.paramIndex-1] = command.ChangeSignatureParam{OldIndex: info.paramIndex}
		cmd := command.NewChangeSignatureCommand("Move parameter left", command.ChangeSignatureArgs{
			Location:     req.loc,
			NewParams:    transform,
			NewResults:   identityTransform(info.decl.Type.Results),
			ResolveEdits: req.resolveEdits(),
		})

		req.addCommandAction(cmd, true)
	}
	return nil
}

func refactorRewriteMoveParamRight(ctx context.Context, req *codeActionsRequest) error {
	if info := findParam(req.pgf, req.loc.Range); info != nil && info.paramIndex >= 0 {
		params := info.decl.Type.Params
		nparams := params.NumFields()
		if info.paramIndex < nparams-1 { // not the last param
			if info.paramIndex == nparams-2 && is[*ast.Ellipsis](params.List[len(params.List)-1].Type) {
				// We can't currently handle moving a variadic param.
				// TODO(rfindley): implement.
				return nil
			}

			transform := identityTransform(info.decl.Type.Params)
			transform[info.paramIndex] = command.ChangeSignatureParam{OldIndex: info.paramIndex + 1}
			transform[info.paramIndex+1] = command.ChangeSignatureParam{OldIndex: info.paramIndex}
			cmd := command.NewChangeSignatureCommand("Move parameter right", command.ChangeSignatureArgs{
				Location:     req.loc,
				NewParams:    transform,
				NewResults:   identityTransform(info.decl.Type.Results),
				ResolveEdits: req.resolveEdits(),
			})
			req.addCommandAction(cmd, true)
		}
	}
	return nil
}

// refactorRewriteChangeQuote produces "Convert to {raw,interpreted} string literal" code actions.
func refactorRewriteChangeQuote(ctx context.Context, req *codeActionsRequest) error {
	convertStringLiteral(req)
	return nil
}

// refactorRewriteInvertIf produces "Invert 'if' condition" code actions.
// See [invertIfCondition] for command implementation.
func refactorRewriteInvertIf(ctx context.Context, req *codeActionsRequest) error {
	if _, ok, _ := canInvertIfCondition(req.pgf.Cursor(), req.start, req.end); ok {
		req.addApplyFixAction("Invert 'if' condition", fixInvertIfCondition, req.loc)
	}
	return nil
}

// refactorRewriteSplitLines produces "Split ITEMS into separate lines" code actions.
// See [splitLines] for command implementation.
func refactorRewriteSplitLines(ctx context.Context, req *codeActionsRequest) error {
	// TODO(adonovan): opt: don't set needPkg just for FileSet.
	if msg, ok, _ := canSplitLines(req.pgf.Cursor(), req.pkg.FileSet(), req.start, req.end); ok {
		req.addApplyFixAction(msg, fixSplitLines, req.loc)
	}
	return nil
}

func refactorRewriteEliminateDotImport(ctx context.Context, req *codeActionsRequest) error {
	// Figure out if the request is placed over a dot import.
	var importSpec *ast.ImportSpec
	for _, imp := range req.pgf.File.Imports {
		if posRangeContains(imp.Pos(), imp.End(), req.start, req.end) {
			importSpec = imp
			break
		}
	}
	if importSpec == nil {
		return nil
	}
	if importSpec.Name == nil || importSpec.Name.Name != "." {
		return nil
	}

	// dotImported package path and its imported name after removing the dot.
	imported := req.pkg.TypesInfo().PkgNameOf(importSpec).Imported()
	newName := imported.Name()

	rng, err := req.pgf.PosRange(importSpec.Name.Pos(), importSpec.Path.Pos())
	if err != nil {
		return err
	}
	// Delete the '.' part of the import.
	edits := []protocol.TextEdit{{
		Range: rng,
	}}

	fileScope, ok := req.pkg.TypesInfo().Scopes[req.pgf.File]
	if !ok {
		return nil
	}

	// Go through each use of the dot imported package, checking its scope for
	// shadowing and calculating an edit to qualify the identifier.
	for curId := range req.pgf.Cursor().Preorder((*ast.Ident)(nil)) {
		ident := curId.Node().(*ast.Ident)

		// Only keep identifiers that use a symbol from the
		// dot imported package.
		use := req.pkg.TypesInfo().Uses[ident]
		if use == nil || use.Pkg() == nil {
			continue
		}
		if use.Pkg() != imported {
			continue
		}

		// Only qualify unqualified identifiers (due to dot imports)
		// that reference package-level symbols.
		// All other references to a symbol imported from another package
		// are nested within a select expression (pkg.Foo, v.Method, v.Field).
		if astutil.IsChildOf(curId, edge.SelectorExpr_Sel) {
			continue // qualified identifier (pkg.X) or selector (T.X or e.X)
		}
		if !typesinternal.IsPackageLevel(use) {
			continue // unqualified field reference T{X: ...}
		}

		// Make sure that the package name will not be shadowed by something else in scope.
		// If it is then we cannot offer this particular code action.
		//
		// TODO: If the object found in scope is the package imported without a
		// dot, or some builtin not used in the file, the code action could be
		// allowed to go through.
		sc := fileScope.Innermost(ident.Pos())
		if sc == nil {
			continue
		}
		_, obj := sc.LookupParent(newName, ident.Pos())
		if obj != nil {
			continue
		}

		rng, err := req.pgf.PosRange(ident.Pos(), ident.Pos()) // sic, zero-width range before ident
		if err != nil {
			continue
		}
		edits = append(edits, protocol.TextEdit{
			Range:   rng,
			NewText: newName + ".",
		})
	}

	req.addEditAction("Eliminate dot import", nil, protocol.DocumentChangeEdit(
		req.fh,
		edits,
	))
	return nil
}

// refactorRewriteJoinLines produces "Join ITEMS into one line" code actions.
// See [joinLines] for command implementation.
func refactorRewriteJoinLines(ctx context.Context, req *codeActionsRequest) error {
	// TODO(adonovan): opt: don't set needPkg just for FileSet.
	if msg, ok, _ := canJoinLines(req.pgf.Cursor(), req.pkg.FileSet(), req.start, req.end); ok {
		req.addApplyFixAction(msg, fixJoinLines, req.loc)
	}
	return nil
}

// refactorRewriteFillStruct produces "Fill STRUCT" code actions.
// See [fillstruct.SuggestedFix] for command implementation.
func refactorRewriteFillStruct(ctx context.Context, req *codeActionsRequest) error {
	// fillstruct.Diagnose is a lazy analyzer: all it gives us is
	// the (start, end, message) of each SuggestedFix; the actual
	// edit is computed only later by ApplyFix, which calls fillstruct.SuggestedFix.
	for _, diag := range fillstruct.Diagnose(req.pgf.File, req.start, req.end, req.pkg.Types(), req.pkg.TypesInfo()) {
		loc, err := req.pgf.Mapper.PosLocation(req.pgf.Tok, diag.Pos, diag.End)
		if err != nil {
			return err
		}
		for _, fix := range diag.SuggestedFixes {
			req.addApplyFixAction(fix.Message, diag.Category, loc)
		}
	}
	return nil
}

// refactorRewriteFillSwitch produces "Add cases for TYPE/ENUM" code actions.
func refactorRewriteFillSwitch(ctx context.Context, req *codeActionsRequest) error {
	for _, diag := range fillswitch.Diagnose(req.pgf.File, req.start, req.end, req.pkg.Types(), req.pkg.TypesInfo()) {
		changes, err := suggestedFixToDocumentChange(ctx, req.snapshot, req.pkg.FileSet(), &diag.SuggestedFixes[0])
		if err != nil {
			return err
		}
		req.addEditAction(diag.Message, nil, changes...)
	}

	return nil
}

// selectionContainsStructField returns true if the given struct contains a
// field between start and end pos. If needsTag is true, it only returns true if
// the struct field found contains a struct tag.
func selectionContainsStructField(node *ast.StructType, start, end token.Pos, needsTag bool) bool {
	for _, field := range node.Fields.List {
		if start <= field.End() && end >= field.Pos() {
			if !needsTag || field.Tag != nil {
				return true
			}
		}
	}
	return false
}

// selectionContainsStruct returns true if there exists a struct containing
// fields within start and end positions. If removeTags is true, it means the
// current command is for remove tags rather than add tags, so we only return
// true if the struct field found contains a struct tag to remove.
func selectionContainsStruct(cursor inspector.Cursor, start, end token.Pos, removeTags bool) bool {
	cur, ok := cursor.FindByPos(start, end)
	if !ok {
		return false
	}
	if _, ok := cur.Node().(*ast.StructType); ok {
		return true
	}

	// Handles case where selection is within struct.
	for c := range cur.Enclosing((*ast.StructType)(nil)) {
		if selectionContainsStructField(c.Node().(*ast.StructType), start, end, removeTags) {
			return true
		}
	}

	// Handles case where selection contains struct but may contain other nodes, including other structs.
	for c := range cur.Preorder((*ast.StructType)(nil)) {
		node := c.Node().(*ast.StructType)
		// Check that at least one field is located within the selection. If we are removing tags, that field
		// must also have a struct tag, otherwise we do not provide the code action.
		if selectionContainsStructField(node, start, end, removeTags) {
			return true
		}
	}
	return false
}

// refactorRewriteAddStructTags produces "Add struct tags" code actions.
// See [server.commandHandler.ModifyTags] for command implementation.
func refactorRewriteAddStructTags(ctx context.Context, req *codeActionsRequest) error {
	if selectionContainsStruct(req.pgf.Cursor(), req.start, req.end, false) {
		// TODO(mkalil): Prompt user for modification args once we have dialogue capabilities.
		cmdAdd := command.NewModifyTagsCommand("Add struct tags", command.ModifyTagsArgs{
			URI:   req.loc.URI,
			Range: req.loc.Range,
			Add:   "json",
		})
		req.addCommandAction(cmdAdd, false)
	}
	return nil
}

// refactorRewriteRemoveStructTags produces "Remove struct tags" code actions.
// See [server.commandHandler.ModifyTags] for command implementation.
func refactorRewriteRemoveStructTags(ctx context.Context, req *codeActionsRequest) error {
	// TODO(mkalil): Prompt user for modification args once we have dialogue capabilities.
	if selectionContainsStruct(req.pgf.Cursor(), req.start, req.end, true) {
		cmdRemove := command.NewModifyTagsCommand("Remove struct tags", command.ModifyTagsArgs{
			URI:   req.loc.URI,
			Range: req.loc.Range,
			Clear: true,
		})
		req.addCommandAction(cmdRemove, false)
	}
	return nil
}

// removableParameter returns paramInfo about a removable parameter indicated
// by the given [start, end) range, or nil if no such removal is available.
//
// Removing a parameter is possible if
//   - there are no parse or type errors, and
//   - [start, end) is contained within an unused field or parameter name
//   - ... of a non-method function declaration.
//
// (Note that the unusedparam analyzer also computes this property, but
// much more precisely, allowing it to report its findings as diagnostics.)
//
// TODO(adonovan): inline into refactorRewriteRemoveUnusedParam.
func removableParameter(pkg *cache.Package, pgf *parsego.File, rng protocol.Range) *paramInfo {
	if perrors, terrors := pkg.ParseErrors(), pkg.TypeErrors(); len(perrors) > 0 || len(terrors) > 0 {
		return nil // can't remove parameters from packages with errors
	}
	info := findParam(pgf, rng)
	if info == nil || info.field == nil {
		return nil // range does not span a parameter
	}
	if info.decl.Body == nil {
		return nil // external function
	}
	if len(info.field.Names) == 0 {
		return info // no names => field is unused
	}
	if info.name == nil {
		return nil // no name is indicated
	}
	if info.name.Name == "_" {
		return info // trivially unused
	}

	obj := pkg.TypesInfo().Defs[info.name]
	if obj == nil {
		return nil // something went wrong
	}

	used := false
	ast.Inspect(info.decl.Body, func(node ast.Node) bool {
		if n, ok := node.(*ast.Ident); ok && pkg.TypesInfo().Uses[n] == obj {
			used = true
		}
		return !used // keep going until we find a use
	})
	if used {
		return nil
	}
	return info
}

// refactorInlineCall produces "Inline call to FUNC" code actions.
// See [inlineCall] for command implementation.
func refactorInlineCall(ctx context.Context, req *codeActionsRequest) error {
	// To avoid distraction (e.g. VS Code lightbulb), offer "inline"
	// only after a selection or explicit menu operation.
	// TODO(adonovan): remove this (and req.trigger); see comment at TestVSCodeIssue65167.
	if req.trigger == protocol.CodeActionAutomatic && req.loc.Empty() {
		return nil
	}

	// If range is within call expression, offer to inline the call.
	if _, fn, err := enclosingStaticCall(req.pkg, req.pgf, req.start, req.end); err == nil {
		req.addApplyFixAction("Inline call to "+fn.Name(), fixInlineCall, req.loc)
	}
	return nil
}

// refactorInlineVariable produces the "Inline variable 'v'" code action.
// See [inlineVariableOne] for command implementation.
func refactorInlineVariable(ctx context.Context, req *codeActionsRequest) error {
	// TODO(adonovan): offer "inline all" variant that eliminates the var (see #70085).
	if curUse, _, ok := canInlineVariable(req.pkg.TypesInfo(), req.pgf.Cursor(), req.start, req.end); ok {
		title := fmt.Sprintf("Inline variable %q", curUse.Node().(*ast.Ident).Name)
		req.addApplyFixAction(title, fixInlineVariable, req.loc)
	}
	return nil
}

// goTest produces "Run tests and benchmarks" code actions.
// See [server.commandHandler.runTests] for command implementation.
func goTest(ctx context.Context, req *codeActionsRequest) error {
	testFuncs, benchFuncs, err := testsAndBenchmarks(req.pkg.TypesInfo(), req.pgf)
	if err != nil {
		return err
	}

	var tests, benchmarks []string
	for _, fn := range testFuncs {
		if protocol.Intersect(fn.rng, req.loc.Range) {
			tests = append(tests, fn.name)
		}
	}
	for _, fn := range benchFuncs {
		if protocol.Intersect(fn.rng, req.loc.Range) {
			benchmarks = append(benchmarks, fn.name)
		}
	}

	if len(tests) == 0 && len(benchmarks) == 0 {
		return nil
	}

	cmd := command.NewRunTestsCommand("Run tests and benchmarks", command.RunTestsArgs{
		URI:        req.loc.URI,
		Tests:      tests,
		Benchmarks: benchmarks,
	})
	req.addCommandAction(cmd, false)
	return nil
}

// goAssembly produces "Browse ARCH assembly for FUNC" code actions.
// See [server.commandHandler.Assembly] for command implementation.
func goAssembly(ctx context.Context, req *codeActionsRequest) error {
	view := req.snapshot.View()

	// Find the enclosing toplevel function or method,
	// and compute its symbol name (e.g. "pkgpath.(T).method").
	// The report will show this method and all its nested
	// functions (FuncLit, defers, etc).
	//
	// TODO(adonovan): this is no good for generics, since they
	// will always be uninstantiated when they enclose the cursor.
	// Instead, we need to query the func symbol under the cursor,
	// rather than the enclosing function. It may be an explicitly
	// or implicitly instantiated generic, and it may be defined
	// in another package, though we would still need to compile
	// the current package to see its assembly. The challenge,
	// however, is that computing the linker name for a generic
	// symbol is quite tricky. Talk with the compiler team for
	// ideas.
	//
	// TODO(adonovan): think about a smoother UX for jumping
	// directly to (say) a lambda of interest.
	// Perhaps we could scroll to STEXT for the innermost
	// enclosing nested function?

	// Compute the linker symbol of the enclosing function or var initializer.
	var sym strings.Builder
	if pkg := req.pkg.Types(); pkg.Name() == "main" {
		sym.WriteString("main")
	} else {
		sym.WriteString(pkg.Path())
	}
	sym.WriteString(".")

	curSel, _ := req.pgf.Cursor().FindByPos(req.start, req.end)
	for cur := range curSel.Enclosing((*ast.FuncDecl)(nil), (*ast.ValueSpec)(nil)) {
		var name string // in command title
		switch node := cur.Node().(type) {
		case *ast.FuncDecl:
			// package-level func or method
			if fn, ok := req.pkg.TypesInfo().Defs[node.Name].(*types.Func); ok &&
				fn.Name() != "_" { // blank functions are not compiled

				// Source-level init functions are compiled (along with
				// package-level var initializers) in into a single pkg.init
				// function, so this falls out of the logic below.

				if sig := fn.Signature(); sig.TypeParams() == nil && sig.RecvTypeParams() == nil { // generic => no assembly
					if sig.Recv() != nil {
						if isPtr, named := typesinternal.ReceiverNamed(sig.Recv()); named != nil {
							if isPtr {
								fmt.Fprintf(&sym, "(*%s)", named.Obj().Name())
							} else {
								sym.WriteString(named.Obj().Name())
							}
							sym.WriteByte('.')
						}
					}
					sym.WriteString(fn.Name())

					name = node.Name.Name // success
				}
			}

		case *ast.ValueSpec:
			// package-level var initializer?
			if len(node.Names) > 0 && len(node.Values) > 0 {
				v := req.pkg.TypesInfo().Defs[node.Names[0]]
				if v != nil && typesinternal.IsPackageLevel(v) {
					sym.WriteString("init")
					name = "package initializer" // success
				}
			}
		}

		if name != "" {
			cmd := command.NewAssemblyCommand(
				fmt.Sprintf("Browse %s assembly for %s", view.GOARCH(), name),
				view.ID(),
				string(req.pkg.Metadata().ID),
				sym.String())
			req.addCommandAction(cmd, false)
			break
		}
	}
	return nil
}

// toggleCompilerOptDetails produces "{Show,Hide} compiler optimization details" code action.
// See [server.commandHandler.GCDetails] for command implementation.
func toggleCompilerOptDetails(ctx context.Context, req *codeActionsRequest) error {
	// TODO(adonovan): errors from code action providers should probably be
	// logged, even if they aren't visible to the client; see https://go.dev/issue/71275.
	if meta, err := req.snapshot.NarrowestMetadataForFile(ctx, req.fh.URI()); err == nil {
		if len(meta.CompiledGoFiles) == 0 {
			return fmt.Errorf("package %q does not compile file %q", meta.ID, req.fh.URI())
		}
		dir := meta.CompiledGoFiles[0].Dir()

		title := fmt.Sprintf("%s compiler optimization details for %q",
			cond(req.snapshot.WantCompilerOptDetails(dir), "Hide", "Show"),
			dir.Base())
		cmd := command.NewGCDetailsCommand(title, req.fh.URI())
		req.addCommandAction(cmd, false)
	}
	return nil
}

func refactorMoveType(ctx context.Context, req *codeActionsRequest) error {
	curSel, _ := req.pgf.Cursor().FindByPos(req.start, req.end)
	if _, _, _, typeName, ok := selectionContainsType(curSel); ok {
		cmd := command.NewMoveTypeCommand(fmt.Sprintf("Move type %s", typeName), command.MoveTypeArgs{Location: req.loc})
		req.addCommandAction(cmd, false)
	}
	return nil
}
