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

import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"log"
	"maps"
	"os"
	"path/filepath"
	"regexp"
	"runtime"
	"runtime/pprof"
	"slices"
	"sort"
	"strings"
	"sync"

	"github.com/fatih/gomodifytags/modifytags"
	"golang.org/x/mod/modfile"
	"golang.org/x/telemetry/counter"
	"golang.org/x/tools/go/ast/astutil"
	"golang.org/x/tools/gopls/internal/cache"
	"golang.org/x/tools/gopls/internal/cache/metadata"
	"golang.org/x/tools/gopls/internal/cache/parsego"
	"golang.org/x/tools/gopls/internal/debug"
	"golang.org/x/tools/gopls/internal/file"
	"golang.org/x/tools/gopls/internal/golang"
	"golang.org/x/tools/gopls/internal/progress"
	"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/gopls/internal/util/bug"
	"golang.org/x/tools/gopls/internal/util/tokeninternal"
	"golang.org/x/tools/gopls/internal/vulncheck"
	"golang.org/x/tools/gopls/internal/vulncheck/scan"
	"golang.org/x/tools/internal/diff"
	"golang.org/x/tools/internal/event"
	"golang.org/x/tools/internal/gocommand"
	"golang.org/x/tools/internal/jsonrpc2"
)

func (s *server) ExecuteCommand(ctx context.Context, params *protocol.ExecuteCommandParams) (any, error) {
	ctx, done := event.Start(ctx, "server.ExecuteCommand")
	defer done()

	// For test synchronization, always create a progress notification.
	//
	// This may be in addition to user-facing progress notifications created in
	// the course of command execution.
	if s.Options().VerboseWorkDoneProgress {
		work := s.progress.Start(ctx, params.Command, "Verbose: running command...", nil, nil)
		defer work.End(ctx, "Done.")
	}

	if !slices.Contains(s.Options().SupportedCommands, params.Command) {
		return nil, fmt.Errorf("%s is not a supported command", params.Command)
	}

	if len(params.Arguments) > 0 {
		last := params.Arguments[len(params.Arguments)-1]
		var meta struct {
			Source string `json:"source"`
		}
		if err := json.Unmarshal(last, &meta); err == nil && meta.Source != "" {
			commandName := strings.TrimPrefix(params.Command, "gopls.")
			counterName := fmt.Sprintf("gopls/cmd/source:%s-%s", commandName, meta.Source)
			counter.New(counterName).Inc()
			params.Arguments = params.Arguments[:len(params.Arguments)-1]
		}
	}

	if len(params.FormAnswers) != 0 {
		commandName := strings.TrimPrefix(params.Command, "gopls.")
		counterName := fmt.Sprintf("gopls/interactive/command:%s", commandName)
		counter.New(counterName).Inc()
	}

	handler := &commandHandler{
		s:      s,
		params: params,
	}
	return command.Dispatch(ctx, params, handler)
}

type commandHandler struct {
	s      *server
	params *protocol.ExecuteCommandParams
}

func (h *commandHandler) Modules(ctx context.Context, args command.ModulesArgs) (command.ModulesResult, error) {
	// keepModule filters modules based on the command args
	keepModule := func(goMod protocol.DocumentURI) bool {
		// Does the directory enclose the view's go.mod file?
		if !args.Dir.Encloses(goMod) {
			return false
		}

		// Calculate the relative path
		rel, err := filepath.Rel(args.Dir.Path(), goMod.Path())
		if err != nil {
			return false // "can't happen" (see prior Encloses check)
		}

		assert(goMod.Base() == "go.mod", fmt.Sprintf("invalid go.mod path: want go.mod, got %q", goMod.Path()))

		// Invariant: rel is a relative path without "../" segments and the last
		// segment is "go.mod"
		nparts := strings.Count(rel, string(filepath.Separator))
		return args.MaxDepth < 0 || nparts <= args.MaxDepth
	}

	// Views may include:
	//   - go.work views containing one or more modules each;
	//   - go.mod views containing a single module each;
	//   - GOPATH and/or ad hoc views containing no modules.
	//
	// Retrieving a view via the request path would only work for a
	// non-recursive query for a go.mod view, and even in that case
	// [Session.SnapshotOf] doesn't work on directories. Thus we check every
	// view.
	var result command.ModulesResult
	seen := map[protocol.DocumentURI]bool{}
	for _, v := range h.s.session.Views() {
		s, release, err := v.Snapshot()
		if err != nil {
			return command.ModulesResult{}, err
		}
		defer release()

		for _, modFile := range v.ModFiles() {
			if !keepModule(modFile) {
				continue
			}

			// Deduplicate
			if seen[modFile] {
				continue
			}
			seen[modFile] = true

			fh, err := s.ReadFile(ctx, modFile)
			if err != nil {
				return command.ModulesResult{}, err
			}
			mod, err := s.ParseMod(ctx, fh)
			if err != nil {
				return command.ModulesResult{}, err
			}
			if mod.File.Module == nil {
				continue // syntax contains errors
			}
			result.Modules = append(result.Modules, command.Module{
				Path:    mod.File.Module.Mod.Path,
				Version: mod.File.Module.Mod.Version,
				GoMod:   mod.URI,
			})
		}
	}
	return result, nil
}

func (h *commandHandler) Packages(ctx context.Context, args command.PackagesArgs) (command.PackagesResult, error) {
	// Convert file arguments into directories
	dirs := make([]protocol.DocumentURI, len(args.Files))
	for i, file := range args.Files {
		if filepath.Ext(file.Path()) == ".go" {
			dirs[i] = file.Dir()
		} else {
			dirs[i] = file
		}
	}

	keepPackage := func(pkg *metadata.Package) bool {
		for _, file := range pkg.GoFiles {
			for _, dir := range dirs {
				if file.Dir() == dir || args.Recursive && dir.Encloses(file) {
					return true
				}
			}
		}
		return false
	}

	result := command.PackagesResult{
		Module: make(map[string]command.Module),
	}

	err := h.run(ctx, commandConfig{
		progress: "Packages",
	}, func(ctx context.Context, _ commandDeps) error {
		for _, view := range h.s.session.Views() {
			snapshot, release, err := view.Snapshot()
			if err != nil {
				return err
			}
			defer release()

			metas, err := snapshot.WorkspaceMetadata(ctx)
			if err != nil {
				return err
			}

			// Filter out unwanted packages
			metas = slices.DeleteFunc(metas, func(meta *metadata.Package) bool {
				return meta.IsIntermediateTestVariant() ||
					!keepPackage(meta)
			})

			start := len(result.Packages)
			for _, meta := range metas {
				var mod command.Module
				if meta.Module != nil {
					mod = command.Module{
						Path:    meta.Module.Path,
						Version: meta.Module.Version,
						GoMod:   protocol.URIFromPath(meta.Module.GoMod),
					}
					result.Module[mod.Path] = mod // Overwriting is ok
				}

				result.Packages = append(result.Packages, command.Package{
					Path:       string(meta.PkgPath),
					ForTest:    string(meta.ForTest),
					ModulePath: mod.Path,
				})
			}

			if args.Mode&command.NeedTests == 0 {
				continue
			}

			// Make a single request to the index (per snapshot) to minimize the
			// performance hit
			var ids []cache.PackageID
			for _, meta := range metas {
				ids = append(ids, meta.ID)
			}

			allTests, err := snapshot.Tests(ctx, ids...)
			if err != nil {
				return err
			}

			for i, tests := range allTests {
				pkg := &result.Packages[start+i]
				fileByPath := map[protocol.DocumentURI]*command.TestFile{}
				for _, test := range tests.All() {
					test := command.TestCase{
						Name: test.Name,
						Loc:  test.Location,
					}

					file, ok := fileByPath[test.Loc.URI]
					if !ok {
						f := command.TestFile{
							URI: test.Loc.URI,
						}
						i := len(pkg.TestFiles)
						pkg.TestFiles = append(pkg.TestFiles, f)
						file = &pkg.TestFiles[i]
						fileByPath[test.Loc.URI] = file
					}
					file.Tests = append(file.Tests, test)
				}
			}
		}

		return nil
	})
	return result, err
}

func (h *commandHandler) MaybePromptForTelemetry(ctx context.Context) error {
	// if the server's TelemetryPrompt is true, it's likely the server already
	// handled prompting for it. Don't try to prompt again.
	if !h.s.options.TelemetryPrompt {
		go h.s.maybePromptForTelemetry(ctx, true)
	}
	return nil
}

func (*commandHandler) AddTelemetryCounters(_ context.Context, args command.AddTelemetryCountersArgs) error {
	if len(args.Names) != len(args.Values) {
		return fmt.Errorf("Names and Values must have the same length")
	}
	// invalid counter update requests will be silently dropped. (no audience)
	for i, n := range args.Names {
		v := args.Values[i]
		if n == "" || v < 0 {
			continue
		}
		counter.Add("fwd/"+n, v)
	}
	return nil
}

func (c *commandHandler) AddTest(ctx context.Context, loc protocol.Location) (*protocol.WorkspaceEdit, error) {
	var result *protocol.WorkspaceEdit
	err := c.run(ctx, commandConfig{
		forURI: loc.URI,
	}, func(ctx context.Context, deps commandDeps) error {
		if deps.snapshot.FileKind(deps.fh) != file.Go {
			return fmt.Errorf("can't add test for non-Go file")
		}
		docedits, show, err := golang.AddTestForFunc(ctx, deps.snapshot, loc)
		if err != nil {
			return err
		}
		if err := applyChanges(ctx, c.s.client, docedits); err != nil {
			return err
		}

		if show != nil {
			showDocumentImpl(ctx, c.s.client, protocol.URI(show.URI), &show.Range, c.s.options)
		}
		return nil
	})
	return result, err
}

func (c *commandHandler) LSP(ctx context.Context, param command.LSPArgs) (any, error) {
	response, valid, err := protocol.ServerDispatchCall(ctx, c.s, param.Method, param.Param)
	if !valid {
		return nil, fmt.Errorf("method %s does not exist", param.Method)
	}

	return response, err
}

// commandConfig configures common command set-up and execution.
type commandConfig struct {
	requireSave   bool                           // whether all files must be saved for the command to work
	progress      string                         // title to use for progress reporting. If empty, no progress will be reported.
	progressStyle settings.WorkDoneProgressStyle // style information for client-side progress display.
	forView       string                         // view to resolve to a snapshot; incompatible with forURI
	forURI        protocol.DocumentURI           // URI to resolve to a snapshot. If unset, snapshot will be nil.
}

// commandDeps is evaluated from a commandConfig. Note that not all fields may
// be populated, depending on which configuration is set. See comments in-line
// for details.
type commandDeps struct {
	snapshot *cache.Snapshot    // present if cfg.forURI or forView was set
	fh       file.Handle        // present if cfg.forURI was set
	work     *progress.WorkDone // present if cfg.progress was set
}

type commandFunc func(context.Context, commandDeps) error

// These strings are reported as the final WorkDoneProgressEnd message
// for each workspace/executeCommand request.
const (
	CommandCanceled  = "canceled"
	CommandFailed    = "failed"
	CommandCompleted = "completed"
)

// run performs command setup for command execution, and invokes the given run
// function. If cfg.async is set, run executes the given func in a separate
// goroutine, and returns as soon as setup is complete and the goroutine is
// scheduled.
//
// Invariant: if the resulting error is non-nil, the given run func will
// (eventually) be executed exactly once.
func (c *commandHandler) run(ctx context.Context, cfg commandConfig, run commandFunc) (err error) {
	if cfg.requireSave {
		var unsaved []string
		for _, overlay := range c.s.session.Overlays() {
			if !overlay.SameContentsOnDisk() {
				unsaved = append(unsaved, overlay.URI().Path())
			}
		}
		if len(unsaved) > 0 {
			return fmt.Errorf("All files must be saved first (unsaved: %v).", unsaved)
		}
	}
	var deps commandDeps
	var release func()
	if cfg.forURI != "" && cfg.forView != "" {
		return bug.Errorf("internal error: forURI=%q, forView=%q", cfg.forURI, cfg.forView)
	}
	if cfg.forURI != "" {
		deps.fh, deps.snapshot, release, err = c.s.session.FileOf(ctx, cfg.forURI)
		if err != nil {
			return err
		}

	} else if cfg.forView != "" {
		view, err := c.s.session.View(cfg.forView)
		if err != nil {
			return err
		}
		deps.snapshot, release, err = view.Snapshot()
		if err != nil {
			return err
		}

	} else {
		release = func() {}
	}
	// Inv: release() must be called exactly once after this point.
	// In the async case, runcmd may outlive run().

	ctx, cancel := context.WithCancel(context.WithoutCancel(ctx))
	if cfg.progress != "" {
		header := ""
		if _, ok := c.s.options.SupportedWorkDoneProgressFormats[cfg.progressStyle]; ok && cfg.progressStyle != "" {
			header = fmt.Sprintf("style: %s\n\n", cfg.progressStyle)
		}
		deps.work = c.s.progress.Start(ctx, cfg.progress, header+"Running...", c.params.WorkDoneToken, cancel)
	}
	runcmd := func() error {
		defer release()
		defer cancel()
		err := run(ctx, deps)
		if deps.work != nil {
			switch {
			case errors.Is(err, context.Canceled):
				deps.work.End(ctx, CommandCanceled)
			case err != nil:
				event.Error(ctx, "command error", err)
				deps.work.End(ctx, CommandFailed)
			default:
				deps.work.End(ctx, CommandCompleted)
			}
		}
		return err
	}

	// For legacy reasons, gopls.run_govulncheck must run asynchronously.
	// TODO(golang/vscode-go#3572): remove this (along with the
	// gopls.run_govulncheck command entirely) once VS Code only uses the new
	// gopls.vulncheck command.
	if c.params.Command == "gopls.run_govulncheck" {
		if cfg.progress == "" {
			log.Fatalf("asynchronous command gopls.run_govulncheck does not enable progress reporting")
		}
		go func() {
			if err := runcmd(); err != nil {
				showMessage(ctx, c.s.client, protocol.Error, err.Error())
			}
		}()
		return nil
	}

	return runcmd()
}

func (c *commandHandler) ApplyFix(ctx context.Context, args command.ApplyFixArgs) (*protocol.WorkspaceEdit, error) {
	var result *protocol.WorkspaceEdit
	err := c.run(ctx, commandConfig{
		// Note: no progress here. Applying fixes should be quick.
		forURI: args.Location.URI,
	}, func(ctx context.Context, deps commandDeps) error {
		changes, err := golang.ApplyFix(ctx, args.Fix, deps.snapshot, deps.fh, args.Location.Range)
		if err != nil {
			return err
		}
		wsedit := protocol.NewWorkspaceEdit(changes...)
		if args.ResolveEdits {
			result = wsedit
			return nil
		}
		return applyChanges(ctx, c.s.client, changes)
	})
	return result, err
}

func (c *commandHandler) RegenerateCgo(ctx context.Context, args command.URIArg) error {
	return c.run(ctx, commandConfig{
		progress: "Regenerating Cgo",
	}, func(ctx context.Context, _ commandDeps) error {
		return c.modifyState(ctx, FromRegenerateCgo, func() (*cache.Snapshot, func(), error) {
			// Resetting the view causes cgo to be regenerated via `go list`.
			v, err := c.s.session.ResetView(ctx, args.URI)
			if err != nil {
				return nil, nil, err
			}
			return v.Snapshot()
		})
	})
}

// modifyState performs an operation that modifies the snapshot state.
//
// It causes a snapshot diagnosis for the provided ModificationSource.
func (c *commandHandler) modifyState(ctx context.Context, source ModificationSource, work func() (*cache.Snapshot, func(), error)) error {
	var wg sync.WaitGroup // tracks work done on behalf of this function, incl. diagnostics
	wg.Add(1)
	defer wg.Done()

	// Track progress on this operation for testing.
	if c.s.Options().VerboseWorkDoneProgress {
		work := c.s.progress.Start(ctx, DiagnosticWorkTitle(source), "Calculating file diagnostics...", nil, nil)
		go func() {
			wg.Wait()
			work.End(ctx, "Done.")
		}()
	}
	snapshot, release, err := work()
	if err != nil {
		return err
	}
	wg.Go(func() {
		// Diagnosing with the background context ensures new snapshots are fully
		// diagnosed.
		c.s.diagnoseSnapshot(snapshot.BackgroundContext(), snapshot, nil, 0)
		release()
	})
	return nil
}

func (c *commandHandler) CheckUpgrades(ctx context.Context, args command.CheckUpgradesArgs) error {
	return c.run(ctx, commandConfig{
		forURI:   args.URI,
		progress: "Checking for upgrades",
	}, func(ctx context.Context, deps commandDeps) error {
		return c.modifyState(ctx, FromCheckUpgrades, func() (*cache.Snapshot, func(), error) {
			upgrades, err := c.s.getUpgrades(ctx, deps.snapshot, args.URI, args.Modules)
			if err != nil {
				return nil, nil, err
			}
			return c.s.session.InvalidateView(ctx, deps.snapshot.View(), cache.StateChange{
				ModuleUpgrades: map[protocol.DocumentURI]map[string]string{args.URI: upgrades},
			})
		})
	})
}

func (c *commandHandler) AddDependency(ctx context.Context, args command.DependencyArgs) error {
	return c.GoGetModule(ctx, args)
}

func (c *commandHandler) UpgradeDependency(ctx context.Context, args command.DependencyArgs) error {
	return c.GoGetModule(ctx, args)
}

func (c *commandHandler) ResetGoModDiagnostics(ctx context.Context, args command.ResetGoModDiagnosticsArgs) error {
	return c.run(ctx, commandConfig{
		forURI: args.URI,
	}, func(ctx context.Context, deps commandDeps) error {
		return c.modifyState(ctx, FromResetGoModDiagnostics, func() (*cache.Snapshot, func(), error) {
			return c.s.session.InvalidateView(ctx, deps.snapshot.View(), cache.StateChange{
				ModuleUpgrades: map[protocol.DocumentURI]map[string]string{
					deps.fh.URI(): nil,
				},
				Vulns: map[protocol.DocumentURI]*vulncheck.Result{
					deps.fh.URI(): nil,
				},
			})
		})
	})
}

func (c *commandHandler) GoGetModule(ctx context.Context, args command.DependencyArgs) error {
	return c.run(ctx, commandConfig{
		progress: "Running go get",
		forURI:   args.URI,
	}, func(ctx context.Context, deps commandDeps) error {
		return c.s.runGoModUpdateCommands(ctx, deps.snapshot, args.URI, func(invoke func(...string) (*bytes.Buffer, error)) error {
			return runGoGetModule(invoke, args.AddRequire, args.GoCmdArgs)
		})
	})
}

// TODO(rFindley): UpdateGoSum, Tidy, and Vendor could probably all be one command.
func (c *commandHandler) UpdateGoSum(ctx context.Context, args command.URIArgs) error {
	return c.run(ctx, commandConfig{
		progress: "Updating go.sum",
	}, func(ctx context.Context, _ commandDeps) error {
		for _, uri := range args.URIs {
			fh, snapshot, release, err := c.s.session.FileOf(ctx, uri)
			if err != nil {
				return err
			}
			defer release()
			if err := c.s.runGoModUpdateCommands(ctx, snapshot, fh.URI(), func(invoke func(...string) (*bytes.Buffer, error)) error {
				_, err := invoke("list", "all")
				return err
			}); err != nil {
				return err
			}
		}
		return nil
	})
}

func (c *commandHandler) Tidy(ctx context.Context, args command.URIArgs) error {
	return c.run(ctx, commandConfig{
		progress: "Running go mod tidy",
	}, func(ctx context.Context, _ commandDeps) error {
		for _, uri := range args.URIs {
			fh, snapshot, release, err := c.s.session.FileOf(ctx, uri)
			if err != nil {
				return err
			}
			defer release()
			if err := c.s.runGoModUpdateCommands(ctx, snapshot, fh.URI(), func(invoke func(...string) (*bytes.Buffer, error)) error {
				_, err := invoke("mod", "tidy")
				return err
			}); err != nil {
				return err
			}
		}
		return nil
	})
}

func (c *commandHandler) Vendor(ctx context.Context, args command.URIArg) error {
	return c.run(ctx, commandConfig{
		requireSave: true, // TODO(adonovan): probably not needed; but needs a test.
		progress:    "Running go mod vendor",
		forURI:      args.URI,
	}, func(ctx context.Context, deps commandDeps) error {
		// Use RunGoCommandPiped here so that we don't compete with any other go
		// command invocations. go mod vendor deletes modules.txt before recreating
		// it, and therefore can run into file locking issues on Windows if that
		// file is in use by another process, such as go list.
		//
		// If golang/go#44119 is resolved, go mod vendor will instead modify
		// modules.txt in-place. In that case we could theoretically allow this
		// command to run concurrently.
		stderr := new(bytes.Buffer)
		inv, cleanupInvocation, err := deps.snapshot.GoCommandInvocation(cache.NetworkOK, args.URI.DirPath(), "mod", []string{"vendor"})
		if err != nil {
			return err
		}
		defer cleanupInvocation()
		err = deps.snapshot.View().GoCommandRunner().RunPiped(ctx, *inv, &bytes.Buffer{}, stderr)
		if err != nil {
			return fmt.Errorf("running go mod vendor failed: %v\nstderr:\n%s", err, stderr.String())
		}
		return nil
	})
}

func (c *commandHandler) EditGoDirective(ctx context.Context, args command.EditGoDirectiveArgs) error {
	return c.run(ctx, commandConfig{
		requireSave: true, // if go.mod isn't saved it could cause a problem
		forURI:      args.URI,
	}, func(ctx context.Context, _ commandDeps) error {
		fh, snapshot, release, err := c.s.session.FileOf(ctx, args.URI)
		if err != nil {
			return err
		}
		defer release()
		if err := c.s.runGoModUpdateCommands(ctx, snapshot, fh.URI(), func(invoke func(...string) (*bytes.Buffer, error)) error {
			_, err := invoke("mod", "edit", "-go", args.Version)
			return err
		}); err != nil {
			return err
		}
		return nil
	})
}

func (c *commandHandler) RemoveDependency(ctx context.Context, args command.RemoveDependencyArgs) error {
	return c.run(ctx, commandConfig{
		progress: "Removing dependency",
		forURI:   args.URI,
	}, func(ctx context.Context, deps commandDeps) error {
		// See the documentation for OnlyDiagnostic.
		//
		// TODO(rfindley): In Go 1.17+, we will be able to use the go command
		// without checking if the module is tidy.
		if args.OnlyDiagnostic {
			return c.s.runGoModUpdateCommands(ctx, deps.snapshot, args.URI, func(invoke func(...string) (*bytes.Buffer, error)) error {
				if err := runGoGetModule(invoke, false, []string{args.ModulePath + "@none"}); err != nil {
					return err
				}
				_, err := invoke("mod", "tidy")
				return err
			})
		}
		pm, err := deps.snapshot.ParseMod(ctx, deps.fh)
		if err != nil {
			return err
		}
		edits, err := dropDependency(pm, args.ModulePath)
		if err != nil {
			return err
		}
		return applyChanges(ctx, c.s.client, []protocol.DocumentChange{protocol.DocumentChangeEdit(deps.fh, edits)})
	})
}

// dropDependency returns the edits to remove the given require from the go.mod
// file.
func dropDependency(pm *cache.ParsedModule, modulePath string) ([]protocol.TextEdit, error) {
	// We need a private copy of the parsed go.mod file, since we're going to
	// modify it.
	copied, err := modfile.Parse("", pm.Mapper.Content, nil)
	if err != nil {
		return nil, err
	}
	if err := copied.DropRequire(modulePath); err != nil {
		return nil, err
	}
	copied.Cleanup()
	newContent, err := copied.Format()
	if err != nil {
		return nil, err
	}
	// Calculate the edits to be made due to the change.
	diff := diff.Bytes(pm.Mapper.Content, newContent)
	return protocol.EditsFromDiffEdits(pm.Mapper, diff)
}

func (c *commandHandler) Doc(ctx context.Context, args command.DocArgs) (protocol.URI, error) {
	if args.Location.URI == "" {
		return "", errors.New("missing location URI")
	}

	var result protocol.URI
	err := c.run(ctx, commandConfig{
		progress: "", // the operation should be fast
		forURI:   args.Location.URI,
	}, func(ctx context.Context, deps commandDeps) error {
		pkg, pgf, err := golang.NarrowestPackageForFile(ctx, deps.snapshot, args.Location.URI)
		if err != nil {
			return err
		}
		start, end, err := pgf.RangePos(args.Location.Range)
		if err != nil {
			return err
		}

		// Start web server.
		web, err := c.s.getWeb()
		if err != nil {
			return err
		}

		// Compute package path and optional symbol fragment
		// (e.g. "#Buffer.Len") from the selection.
		pkgpath, fragment, _ := golang.DocFragment(pkg, pgf, start, end)

		// Direct the client to open the /pkg page.
		result = web.PkgURL(deps.snapshot.View().ID(), pkgpath, fragment)
		if args.ShowDocument {
			openClientBrowser(ctx, c.s.client, "Doc", result, c.s.Options())
		}

		return nil
	})
	return result, err
}

func (c *commandHandler) RunTests(ctx context.Context, args command.RunTestsArgs) error {
	return c.run(ctx, commandConfig{
		progress:    "Running go test", // (asynchronous)
		requireSave: true,              // go test honors overlays, but tests themselves cannot
		forURI:      args.URI,
	}, func(ctx context.Context, deps commandDeps) error {
		jsonrpc2.Async(ctx) // don't block RPCs behind this command, since it can take a while
		return c.runTests(ctx, deps.snapshot, deps.work, args.URI, args.Tests, args.Benchmarks)
	})
}

func (c *commandHandler) runTests(ctx context.Context, snapshot *cache.Snapshot, work *progress.WorkDone, uri protocol.DocumentURI, tests, benchmarks []string) error {
	// TODO: fix the error reporting when this runs async.
	meta, err := snapshot.NarrowestMetadataForFile(ctx, uri)
	if err != nil {
		return err
	}
	pkgPath := string(meta.ForTest)

	// create output
	buf := &bytes.Buffer{}
	ew := progress.NewEventWriter(ctx, "test")
	out := io.MultiWriter(ew, progress.NewWorkDoneWriter(ctx, work), buf)

	// Run `go test -run Func` on each test.
	var failedTests int
	for _, funcName := range tests {
		args := []string{pkgPath, "-v", "-count=1", fmt.Sprintf("-run=^%s$", regexp.QuoteMeta(funcName))}
		inv, cleanupInvocation, err := snapshot.GoCommandInvocation(cache.NoNetwork, uri.DirPath(), "test", args)
		if err != nil {
			return err
		}
		defer cleanupInvocation()
		if err := snapshot.View().GoCommandRunner().RunPiped(ctx, *inv, out, out); err != nil {
			if errors.Is(err, context.Canceled) {
				return err
			}
			failedTests++
		}
	}

	// Run `go test -run=^$ -bench Func` on each test.
	var failedBenchmarks int
	for _, funcName := range benchmarks {
		inv, cleanupInvocation, err := snapshot.GoCommandInvocation(cache.NoNetwork, uri.DirPath(), "test", []string{
			pkgPath, "-v", "-run=^$", fmt.Sprintf("-bench=^%s$", regexp.QuoteMeta(funcName)),
		})
		if err != nil {
			return err
		}
		defer cleanupInvocation()
		if err := snapshot.View().GoCommandRunner().RunPiped(ctx, *inv, out, out); err != nil {
			if errors.Is(err, context.Canceled) {
				return err
			}
			failedBenchmarks++
		}
	}

	var title string
	if len(tests) > 0 && len(benchmarks) > 0 {
		title = "tests and benchmarks"
	} else if len(tests) > 0 {
		title = "tests"
	} else if len(benchmarks) > 0 {
		title = "benchmarks"
	} else {
		return errors.New("No functions were provided")
	}
	message := fmt.Sprintf("all %s passed", title)
	if failedTests > 0 && failedBenchmarks > 0 {
		message = fmt.Sprintf("%d / %d tests failed and %d / %d benchmarks failed", failedTests, len(tests), failedBenchmarks, len(benchmarks))
	} else if failedTests > 0 {
		message = fmt.Sprintf("%d / %d tests failed", failedTests, len(tests))
	} else if failedBenchmarks > 0 {
		message = fmt.Sprintf("%d / %d benchmarks failed", failedBenchmarks, len(benchmarks))
	}
	if failedTests > 0 || failedBenchmarks > 0 {
		message += "\n" + buf.String()
	}

	showMessage(ctx, c.s.client, protocol.Info, message)

	if failedTests > 0 || failedBenchmarks > 0 {
		return errors.New("gopls.test command failed")
	}
	return nil
}

func (c *commandHandler) Generate(ctx context.Context, args command.GenerateArgs) error {
	title := "Running go generate ."
	if args.Recursive {
		title = "Running go generate ./..."
	}
	return c.run(ctx, commandConfig{
		requireSave: true, // commands executed by go generate cannot honor overlays
		progress:    title,
		forURI:      args.Dir,
	}, func(ctx context.Context, deps commandDeps) error {
		er := progress.NewEventWriter(ctx, "generate")

		pattern := "."
		if args.Recursive {
			pattern = "./..."
		}
		inv, cleanupInvocation, err := deps.snapshot.GoCommandInvocation(cache.NetworkOK, args.Dir.Path(), "generate", []string{"-x", pattern})
		if err != nil {
			return err
		}
		defer cleanupInvocation()
		stderr := io.MultiWriter(er, progress.NewWorkDoneWriter(ctx, deps.work))
		if err := deps.snapshot.View().GoCommandRunner().RunPiped(ctx, *inv, er, stderr); err != nil {
			return err
		}
		return nil
	})
}

func (c *commandHandler) GoGetPackage(ctx context.Context, args command.GoGetPackageArgs) error {
	return c.run(ctx, commandConfig{
		forURI:   args.URI,
		progress: "Running go get",
	}, func(ctx context.Context, deps commandDeps) error {
		snapshot := deps.snapshot
		modURI := snapshot.GoModForFile(args.URI)
		if modURI == "" {
			return fmt.Errorf("no go.mod file found for %s", args.URI)
		}
		tempDir, cleanupModDir, err := cache.TempModDir(ctx, snapshot, modURI)
		if err != nil {
			return fmt.Errorf("creating a temp go.mod: %v", err)
		}
		defer cleanupModDir()

		inv, cleanupInvocation, err := snapshot.GoCommandInvocation(cache.NetworkOK, modURI.DirPath(), "list",
			[]string{"-f", "{{.Module.Path}}@{{.Module.Version}}", "-mod=mod", "-modfile=" + filepath.Join(tempDir, "go.mod"), args.Pkg},
			"GOWORK=off",
		)
		if err != nil {
			return err
		}
		defer cleanupInvocation()
		stdout, err := snapshot.View().GoCommandRunner().Run(ctx, *inv)
		if err != nil {
			return err
		}
		ver := strings.TrimSpace(stdout.String())
		return c.s.runGoModUpdateCommands(ctx, snapshot, args.URI, func(invoke func(...string) (*bytes.Buffer, error)) error {
			if args.AddRequire {
				if err := addModuleRequire(invoke, []string{ver}); err != nil {
					return err
				}
			}
			_, err := invoke(append([]string{"get", "-d"}, args.Pkg)...)
			return err
		})
	})
}

func (s *server) runGoModUpdateCommands(ctx context.Context, snapshot *cache.Snapshot, uri protocol.DocumentURI, run func(invoke func(...string) (*bytes.Buffer, error)) error) error {
	// TODO(rfindley): can/should this use findRootPattern?
	modURI := snapshot.GoModForFile(uri)
	if modURI == "" {
		return fmt.Errorf("no go.mod file found for %s", uri.Path())
	}
	newModBytes, newSumBytes, err := snapshot.RunGoModUpdateCommands(ctx, modURI, run)
	if err != nil {
		return err
	}
	sumURI := protocol.URIFromPath(strings.TrimSuffix(modURI.Path(), ".mod") + ".sum")

	modChange, err := computeEditChange(ctx, snapshot, modURI, newModBytes)
	if err != nil {
		return err
	}
	sumChange, err := computeEditChange(ctx, snapshot, sumURI, newSumBytes)
	if err != nil {
		return err
	}

	var changes []protocol.DocumentChange
	if modChange.Valid() {
		changes = append(changes, modChange)
	}
	if sumChange.Valid() {
		changes = append(changes, sumChange)
	}
	return applyChanges(ctx, s.client, changes)
}

// computeEditChange computes the edit change required to transform the
// snapshot file specified by uri to the provided new content.
// Beware: returns a DocumentChange that is !Valid() if none were necessary.
//
// If the file is not open, computeEditChange simply writes the new content to
// disk.
//
// TODO(rfindley): fix this API asymmetry. It should be up to the caller to
// write the file or apply the edits.
func computeEditChange(ctx context.Context, snapshot *cache.Snapshot, uri protocol.DocumentURI, newContent []byte) (protocol.DocumentChange, error) {
	fh, err := snapshot.ReadFile(ctx, uri)
	if err != nil {
		return protocol.DocumentChange{}, err
	}
	oldContent, err := fh.Content()
	if err != nil && !os.IsNotExist(err) {
		return protocol.DocumentChange{}, err
	}

	if bytes.Equal(oldContent, newContent) {
		return protocol.DocumentChange{}, nil // note: result is !Valid()
	}

	// Sending a workspace edit to a closed file causes VS Code to open the
	// file and leave it unsaved. We would rather apply the changes directly,
	// especially to go.sum, which should be mostly invisible to the user.
	if !snapshot.IsOpen(uri) {
		err := os.WriteFile(uri.Path(), newContent, 0666)
		return protocol.DocumentChange{}, err
	}

	m := protocol.NewMapper(fh.URI(), oldContent)
	diff := diff.Bytes(oldContent, newContent)
	textedits, err := protocol.EditsFromDiffEdits(m, diff)
	if err != nil {
		return protocol.DocumentChange{}, err
	}
	return protocol.DocumentChangeEdit(fh, textedits), nil
}

func applyChanges(ctx context.Context, cli protocol.Client, changes []protocol.DocumentChange) error {
	if len(changes) == 0 {
		return nil
	}
	response, err := cli.ApplyEdit(ctx, &protocol.ApplyWorkspaceEditParams{
		Edit: *protocol.NewWorkspaceEdit(changes...),
	})
	if err != nil {
		return err
	}
	if !response.Applied {
		return fmt.Errorf("edits not applied because of %s", response.FailureReason)
	}
	return nil
}

func runGoGetModule(invoke func(...string) (*bytes.Buffer, error), addRequire bool, args []string) error {
	if addRequire {
		if err := addModuleRequire(invoke, args); err != nil {
			return err
		}
	}
	_, err := invoke(append([]string{"get", "-d"}, args...)...)
	return err
}

func addModuleRequire(invoke func(...string) (*bytes.Buffer, error), args []string) error {
	// Using go get to create a new dependency results in an
	// `// indirect` comment we may not want. The only way to avoid it
	// is to add the require as direct first. Then we can use go get to
	// update go.sum and tidy up.
	_, err := invoke(append([]string{"mod", "edit", "-require"}, args...)...)
	return err
}

// TODO(rfindley): inline.
func (s *server) getUpgrades(ctx context.Context, snapshot *cache.Snapshot, uri protocol.DocumentURI, modules []string) (map[string]string, error) {
	args := append([]string{"-mod=readonly", "-m", "-u", "-json"}, modules...)
	inv, cleanup, err := snapshot.GoCommandInvocation(cache.NetworkOK, uri.DirPath(), "list", args)
	if err != nil {
		return nil, err
	}
	defer cleanup()
	stdout, err := snapshot.View().GoCommandRunner().Run(ctx, *inv)
	if err != nil {
		return nil, err
	}

	upgrades := map[string]string{}
	for dec := json.NewDecoder(stdout); dec.More(); {
		mod := &gocommand.ModuleJSON{}
		if err := dec.Decode(mod); err != nil {
			return nil, err
		}
		if mod.Update == nil {
			continue
		}
		upgrades[mod.Path] = mod.Update.Version
	}
	return upgrades, nil
}

func (c *commandHandler) GCDetails(ctx context.Context, uri protocol.DocumentURI) error {
	return c.run(ctx, commandConfig{
		forURI: uri,
	}, func(ctx context.Context, deps commandDeps) error {
		return c.modifyState(ctx, FromToggleCompilerOptDetails, func() (*cache.Snapshot, func(), error) {
			// Don't blindly use "dir := deps.fh.URI().Dir()"; validate.
			meta, err := deps.snapshot.NarrowestMetadataForFile(ctx, deps.fh.URI())
			if err != nil {
				return nil, nil, err
			}
			if len(meta.CompiledGoFiles) == 0 {
				return nil, nil, fmt.Errorf("package %q does not compile file %q", meta.ID, deps.fh.URI())
			}
			dir := meta.CompiledGoFiles[0].Dir()

			want := !deps.snapshot.WantCompilerOptDetails(dir) // toggle per-directory flag
			return c.s.session.InvalidateView(ctx, deps.snapshot.View(), cache.StateChange{
				CompilerOptDetails: map[protocol.DocumentURI]bool{dir: want},
			})
		})
	})
}

func (c *commandHandler) ListKnownPackages(ctx context.Context, args command.URIArg) (command.ListKnownPackagesResult, error) {
	var result command.ListKnownPackagesResult
	err := c.run(ctx, commandConfig{
		progress: "Listing packages",
		forURI:   args.URI,
	}, func(ctx context.Context, deps commandDeps) error {
		pkgs, err := golang.KnownPackagePaths(ctx, deps.snapshot, deps.fh)
		for _, pkg := range pkgs {
			result.Packages = append(result.Packages, string(pkg))
		}
		return err
	})
	return result, err
}

func (c *commandHandler) ListImports(ctx context.Context, args command.URIArg) (command.ListImportsResult, error) {
	var result command.ListImportsResult
	err := c.run(ctx, commandConfig{
		forURI: args.URI,
	}, func(ctx context.Context, deps commandDeps) error {
		fh, err := deps.snapshot.ReadFile(ctx, args.URI)
		if err != nil {
			return err
		}
		pgf, err := deps.snapshot.ParseGo(ctx, fh, parsego.Header)
		if err != nil {
			return err
		}
		fset := tokeninternal.FileSetFor(pgf.Tok)
		for _, group := range astutil.Imports(fset, pgf.File) {
			for _, imp := range group {
				if imp.Path == nil {
					continue
				}
				var name string
				if imp.Name != nil {
					name = imp.Name.Name
				}
				result.Imports = append(result.Imports, command.FileImport{
					Path: string(metadata.UnquoteImportPath(imp)),
					Name: name,
				})
			}
		}
		meta, err := deps.snapshot.NarrowestMetadataForFile(ctx, args.URI)
		if err != nil {
			return err // e.g. cancelled
		}
		for pkgPath := range meta.DepsByPkgPath {
			result.PackageImports = append(result.PackageImports,
				command.PackageImport{Path: string(pkgPath)})
		}
		sort.Slice(result.PackageImports, func(i, j int) bool {
			return result.PackageImports[i].Path < result.PackageImports[j].Path
		})
		return nil
	})
	return result, err
}

func (c *commandHandler) AddImport(ctx context.Context, args command.AddImportArgs) error {
	return c.run(ctx, commandConfig{
		progress: "Adding import",
		forURI:   args.URI,
	}, func(ctx context.Context, deps commandDeps) error {
		edits, err := golang.AddImport(ctx, deps.snapshot, deps.fh, args.ImportPath)
		if err != nil {
			return fmt.Errorf("could not add import: %v", err)
		}
		return applyChanges(ctx, c.s.client, []protocol.DocumentChange{protocol.DocumentChangeEdit(deps.fh, edits)})
	})
}

func (c *commandHandler) ExtractToNewFile(ctx context.Context, args protocol.Location) error {
	return c.run(ctx, commandConfig{
		progress: "Extract to a new file",
		forURI:   args.URI,
	}, func(ctx context.Context, deps commandDeps) error {
		changes, err := golang.ExtractToNewFile(ctx, deps.snapshot, deps.fh, args.Range)
		if err != nil {
			return err
		}
		return applyChanges(ctx, c.s.client, changes)
	})
}

func (c *commandHandler) StartDebugging(ctx context.Context, args command.DebuggingArgs) (result command.DebuggingResult, _ error) {
	addr := args.Addr
	if addr == "" {
		addr = "localhost:0"
	}
	di := debug.GetInstance(ctx)
	if di == nil {
		return result, errors.New("internal error: server has no debugging instance")
	}
	listenedAddr, err := di.Serve(ctx, addr)
	if err != nil {
		return result, fmt.Errorf("starting debug server: %w", err)
	}
	result.URLs = []string{"http://" + listenedAddr}
	openClientBrowser(ctx, c.s.client, "Debug", result.URLs[0], c.s.Options())
	return result, nil
}

func (c *commandHandler) StartProfile(ctx context.Context, args command.StartProfileArgs) (result command.StartProfileResult, _ error) {
	file, err := os.CreateTemp("", "gopls-profile-*")
	if err != nil {
		return result, fmt.Errorf("creating temp profile file: %v", err)
	}

	c.s.ongoingProfileMu.Lock()
	defer c.s.ongoingProfileMu.Unlock()

	if c.s.ongoingProfile != nil {
		file.Close() // ignore error
		return result, fmt.Errorf("profile already started (for %q)", c.s.ongoingProfile.Name())
	}

	if err := pprof.StartCPUProfile(file); err != nil {
		file.Close() // ignore error
		return result, fmt.Errorf("starting profile: %v", err)
	}

	c.s.ongoingProfile = file
	return result, nil
}

func (c *commandHandler) StopProfile(ctx context.Context, args command.StopProfileArgs) (result command.StopProfileResult, _ error) {
	c.s.ongoingProfileMu.Lock()
	defer c.s.ongoingProfileMu.Unlock()

	prof := c.s.ongoingProfile
	c.s.ongoingProfile = nil

	if prof == nil {
		return result, fmt.Errorf("no ongoing profile")
	}

	pprof.StopCPUProfile()
	if err := prof.Close(); err != nil {
		return result, fmt.Errorf("closing profile file: %v", err)
	}
	result.File = prof.Name()
	return result, nil
}

func (c *commandHandler) FetchVulncheckResult(ctx context.Context, arg command.URIArg) (map[protocol.DocumentURI]*vulncheck.Result, error) {
	ret := map[protocol.DocumentURI]*vulncheck.Result{}
	err := c.run(ctx, commandConfig{forURI: arg.URI}, func(ctx context.Context, deps commandDeps) error {
		if deps.snapshot.Options().Vulncheck == settings.ModeVulncheckImports {
			for _, modfile := range deps.snapshot.View().ModFiles() {
				res, err := deps.snapshot.ModVuln(ctx, modfile)
				if err != nil {
					return err
				}
				ret[modfile] = res
			}
		}
		// Overwrite if there is any govulncheck-based result.
		maps.Copy(ret, deps.snapshot.Vulnerabilities())
		return nil
	})
	return ret, err
}

const GoVulncheckCommandTitle = "govulncheck"

func (c *commandHandler) Vulncheck(ctx context.Context, args command.VulncheckArgs) (command.VulncheckResult, error) {
	if args.URI == "" {
		return command.VulncheckResult{}, errors.New("VulncheckArgs is missing URI field")
	}

	var commandResult command.VulncheckResult
	err := c.run(ctx, commandConfig{
		progress:      GoVulncheckCommandTitle,
		progressStyle: settings.WorkDoneProgressStyleLog,
		requireSave:   true, // govulncheck cannot honor overlays
		forURI:        args.URI,
	}, func(ctx context.Context, deps commandDeps) error {
		jsonrpc2.Async(ctx) // run this in parallel with other requests: vulncheck can be slow.

		workDoneWriter := progress.NewWorkDoneWriter(ctx, deps.work)
		result, err := c.s.runVulncheck(ctx, deps.snapshot, args.URI, args.Pattern, workDoneWriter)
		if err != nil {
			return err
		}
		commandResult.Result = result
		commandResult.Token = deps.work.Token()

		affecting := make(map[string]bool, len(result.Entries))
		for _, finding := range result.Findings {
			if len(finding.Trace) > 1 { // at least 2 frames if callstack exists (vulnerability, entry)
				affecting[finding.OSV] = true
			}
		}
		if len(affecting) == 0 {
			showMessage(ctx, c.s.client, protocol.Info, "No vulnerabilities found")
			return nil
		}
		affectingOSVs := make([]string, 0, len(affecting))
		for id := range affecting {
			affectingOSVs = append(affectingOSVs, id)
		}
		sort.Strings(affectingOSVs)

		showMessage(ctx, c.s.client, protocol.Warning, fmt.Sprintf("Found %v", strings.Join(affectingOSVs, ", ")))
		return nil
	})
	if err != nil {
		return command.VulncheckResult{}, err
	}
	return commandResult, nil
}

// RunGovulncheck is like Vulncheck (in fact, a copy), but is tweaked slightly
// to run asynchronously rather than return a result.
//
// This logic was copied, rather than factored out, as this implementation is
// slated for deletion.
//
// TODO(golang/vscode-go#3572)
// TODO(hxjiang): deprecate gopls.run_govulncheck.
func (c *commandHandler) RunGovulncheck(ctx context.Context, args command.VulncheckArgs) (command.RunVulncheckResult, error) {
	// Deduplicate the RunGovulncheck command so only one is running at a time.
	if !c.s.runGovulncheckInProgress.CompareAndSwap(false, true) {
		c.s.client.ShowMessage(ctx, &protocol.ShowMessageParams{
			Type:    protocol.Info,
			Message: "A govulncheck scan is already in progress.",
		})
		return command.RunVulncheckResult{}, nil
	}

	defer c.s.runGovulncheckInProgress.Store(false)

	if args.URI == "" {
		return command.RunVulncheckResult{}, errors.New("VulncheckArgs is missing URI field")
	}

	// Return the workdone token so that clients can identify when this
	// vulncheck invocation is complete.
	//
	// Since the run function executes asynchronously, we use a channel to
	// synchronize the start of the run and return the token.
	tokenChan := make(chan protocol.ProgressToken, 1)
	err := c.run(ctx, commandConfig{
		progress:    GoVulncheckCommandTitle,
		requireSave: true, // govulncheck cannot honor overlays
		forURI:      args.URI,
	}, func(ctx context.Context, deps commandDeps) error {
		tokenChan <- deps.work.Token()

		workDoneWriter := progress.NewWorkDoneWriter(ctx, deps.work)
		result, err := c.s.runVulncheck(ctx, deps.snapshot, args.URI, args.Pattern, workDoneWriter)
		if err != nil {
			return err
		}

		affecting := make(map[string]bool, len(result.Entries))
		for _, finding := range result.Findings {
			if len(finding.Trace) > 1 { // at least 2 frames if callstack exists (vulnerability, entry)
				affecting[finding.OSV] = true
			}
		}
		if len(affecting) == 0 {
			showMessage(ctx, c.s.client, protocol.Info, "No vulnerabilities found")
			return nil
		}
		affectingOSVs := make([]string, 0, len(affecting))
		for id := range affecting {
			affectingOSVs = append(affectingOSVs, id)
		}
		sort.Strings(affectingOSVs)

		showMessage(ctx, c.s.client, protocol.Warning, fmt.Sprintf("Found %v", strings.Join(affectingOSVs, ", ")))
		return nil
	})
	if err != nil {
		return command.RunVulncheckResult{}, err
	}
	select {
	case <-ctx.Done():
		return command.RunVulncheckResult{}, ctx.Err()
	case token := <-tokenChan:
		return command.RunVulncheckResult{Token: token}, nil
	}
}

// runVulncheck executes a vulnerability scan and updates the server's state.
func (s *server) runVulncheck(ctx context.Context, snapshot *cache.Snapshot, uri protocol.DocumentURI, pattern string, out io.Writer) (*vulncheck.Result, error) {
	dir := uri.DirPath()
	result, err := scan.RunGovulncheck(ctx, pattern, snapshot, dir, out)
	if err != nil {
		return nil, err
	}

	// Invalidate the view to store findings in the vulnerability cache.
	newSnapshot, release, err := s.session.InvalidateView(ctx, snapshot.View(), cache.StateChange{
		Vulns: map[protocol.DocumentURI]*vulncheck.Result{uri: result},
	})
	if err != nil {
		return nil, err
	}
	defer release()

	// Diagnosing with the background context ensures new snapshots are fully
	// diagnosed.
	s.diagnoseSnapshot(newSnapshot.BackgroundContext(), newSnapshot, nil, 0)

	return result, nil
}

// MemStats implements the MemStats command. It returns an error as a
// future-proof API, but the resulting error is currently always nil.
func (c *commandHandler) MemStats(ctx context.Context) (command.MemStatsResult, error) {
	// GC a few times for stable results.
	runtime.GC()
	runtime.GC()
	runtime.GC()
	var m runtime.MemStats
	runtime.ReadMemStats(&m)
	return command.MemStatsResult{
		HeapAlloc:  m.HeapAlloc,
		HeapInUse:  m.HeapInuse,
		TotalAlloc: m.TotalAlloc,
	}, nil
}

// WorkspaceStats implements the WorkspaceStats command, reporting information
// about the current state of the loaded workspace for the current session.
func (c *commandHandler) WorkspaceStats(ctx context.Context) (command.WorkspaceStatsResult, error) {
	var res command.WorkspaceStatsResult
	res.Files = c.s.session.Cache().FileStats()

	for _, view := range c.s.session.Views() {
		vs, err := collectViewStats(ctx, view)
		if err != nil {
			return res, err
		}
		res.Views = append(res.Views, vs)
	}
	return res, nil
}

func collectViewStats(ctx context.Context, view *cache.View) (command.ViewStats, error) {
	s, release, err := view.Snapshot()
	if err != nil {
		return command.ViewStats{}, err
	}
	defer release()

	allMD, err := s.AllMetadata(ctx)
	if err != nil {
		return command.ViewStats{}, err
	}
	allPackages := collectPackageStats(allMD)

	wsMD, err := s.WorkspaceMetadata(ctx)
	if err != nil {
		return command.ViewStats{}, err
	}
	workspacePackages := collectPackageStats(wsMD)

	var ids []golang.PackageID
	for _, mp := range wsMD {
		ids = append(ids, mp.ID)
	}

	diags, err := s.PackageDiagnostics(ctx, ids...)
	if err != nil {
		return command.ViewStats{}, err
	}

	ndiags := 0
	for _, d := range diags {
		ndiags += len(d)
	}

	return command.ViewStats{
		GoCommandVersion:  view.GoVersionString(),
		AllPackages:       allPackages,
		WorkspacePackages: workspacePackages,
		Diagnostics:       ndiags,
	}, nil
}

func collectPackageStats(mps []*metadata.Package) command.PackageStats {
	var stats command.PackageStats
	stats.Packages = len(mps)
	modules := make(map[string]bool)

	for _, mp := range mps {
		n := len(mp.CompiledGoFiles)
		stats.CompiledGoFiles += n
		if n > stats.LargestPackage {
			stats.LargestPackage = n
		}
		if mp.Module != nil {
			modules[mp.Module.Path] = true
		}
	}
	stats.Modules = len(modules)

	return stats
}

// RunGoWorkCommand invokes `go work <args>` with the provided arguments.
//
// args.InitFirst controls whether to first run `go work init`. This allows a
// single command to both create and recursively populate a go.work file -- as
// of writing there is no `go work init -r`.
//
// Some thought went into implementing this command. Unlike the go.mod commands
// above, this command simply invokes the go command and relies on the client
// to notify gopls of file changes via didChangeWatchedFile notifications.
// We could instead run these commands with GOWORK set to a temp file, but that
// poses the following problems:
//   - directory locations in the resulting temp go.work file will be computed
//     relative to the directory containing that go.work. If the go.work is in a
//     tempdir, the directories will need to be translated to/from that dir.
//   - it would be simpler to use a temp go.work file in the workspace
//     directory, or whichever directory contains the real go.work file, but
//     that sets a bad precedent of writing to a user-owned directory. We
//     shouldn't start doing that.
//   - Sending workspace edits to create a go.work file would require using
//     the CreateFile resource operation, which would need to be tested in every
//     client as we haven't used it before. We don't have time for that right
//     now.
//
// Therefore, we simply require that the current go.work file is saved (if it
// exists), and delegate to the go command.
func (c *commandHandler) RunGoWorkCommand(ctx context.Context, args command.RunGoWorkArgs) error {
	return c.run(ctx, commandConfig{
		progress: "Running go work command",
		forView:  args.ViewID,
	}, func(ctx context.Context, deps commandDeps) (runErr error) {
		snapshot := deps.snapshot
		view := snapshot.View()
		viewDir := snapshot.Folder().Path()

		if view.Type() != cache.GoWorkView && view.GoWork() != "" {
			// If we are not using an existing go.work file, GOWORK must be explicitly off.
			// TODO(rfindley): what about GO111MODULE=off?
			return fmt.Errorf("cannot modify go.work files when GOWORK=off")
		}

		var gowork string
		// If the user has explicitly set GOWORK=off, we should warn them
		// explicitly and avoid potentially misleading errors below.
		if view.GoWork() != "" {
			gowork = view.GoWork().Path()
			fh, err := snapshot.ReadFile(ctx, view.GoWork())
			if err != nil {
				return err // e.g. canceled
			}
			if !fh.SameContentsOnDisk() {
				return fmt.Errorf("must save workspace file %s before running go work commands", view.GoWork())
			}
		} else {
			if !args.InitFirst {
				// If go.work does not exist, we should have detected that and asked
				// for InitFirst.
				return bug.Errorf("internal error: cannot run go work command: required go.work file not found")
			}
			gowork = filepath.Join(viewDir, "go.work")
			if err := c.invokeGoWork(ctx, viewDir, gowork, []string{"init"}); err != nil {
				return fmt.Errorf("running `go work init`: %v", err)
			}
		}

		return c.invokeGoWork(ctx, viewDir, gowork, args.Args)
	})
}

func (c *commandHandler) invokeGoWork(ctx context.Context, viewDir, gowork string, args []string) error {
	inv := gocommand.Invocation{
		Verb:       "work",
		Args:       args,
		WorkingDir: viewDir,
		Env:        append(os.Environ(), fmt.Sprintf("GOWORK=%s", gowork)),
	}
	if _, err := c.s.session.GoCommandRunner().Run(ctx, inv); err != nil {
		return fmt.Errorf("running go work command: %v", err)
	}
	return nil
}

// showMessage causes the client to show a progress or error message.
//
// It reports whether it succeeded. If it fails, it writes an error to
// the server log, so most callers can safely ignore the result.
func showMessage(ctx context.Context, cli protocol.Client, typ protocol.MessageType, message string) bool {
	err := cli.ShowMessage(ctx, &protocol.ShowMessageParams{
		Type:    typ,
		Message: message,
	})
	if err != nil {
		event.Error(ctx, "client.showMessage: %v", err)
		return false
	}
	return true
}

// openClientBrowser causes the LSP client to open the specified URL
// in an external browser.
//
// If the client does not support window/showDocument, a window/showMessage
// request is instead used, with the format "$title: open your browser to $url".
func openClientBrowser(ctx context.Context, cli protocol.Client, title string, url protocol.URI, opts *settings.Options) {
	if opts.ShowDocumentSupported {
		showDocumentImpl(ctx, cli, url, nil, opts)
	} else {
		params := &protocol.ShowMessageParams{
			Type:    protocol.Info,
			Message: fmt.Sprintf("%s: open your browser to %s", title, url),
		}
		if err := cli.ShowMessage(ctx, params); err != nil {
			event.Error(ctx, "failed to show browser url", err)
		}
	}
}

// openClientEditor causes the LSP client to open the specified document
// and select the indicated range.
//
// Note that VS Code 1.87.2 doesn't currently raise the window; this is
// https://github.com/microsoft/vscode/issues/207634
func openClientEditor(ctx context.Context, cli protocol.Client, loc protocol.Location, opts *settings.Options) {
	if !opts.ShowDocumentSupported {
		return // no op
	}
	showDocumentImpl(ctx, cli, protocol.URI(loc.URI), &loc.Range, opts)
}

func showDocumentImpl(ctx context.Context, cli protocol.Client, url protocol.URI, rangeOpt *protocol.Range, opts *settings.Options) {
	if !opts.ShowDocumentSupported {
		return // no op
	}
	// In principle we shouldn't send a showDocument request to a
	// client that doesn't support it, as reported by
	// ShowDocumentClientCapabilities. But even clients that do
	// support it may defer the real work of opening the document
	// asynchronously, to avoid deadlocks due to rentrancy.
	//
	// For example: client sends request to server; server sends
	// showDocument to client; client opens editor; editor causes
	// new RPC to be sent to server, which is still busy with
	// previous request. (This happens in eglot.)
	//
	// So we can't rely on the success/failure information.
	// That's the reason this function doesn't return an error.

	// "External" means run the system-wide handler (e.g. open(1)
	// on macOS or xdg-open(1) on Linux) for this URL, ignoring
	// TakeFocus and Selection. Note that this may still end up
	// opening the same editor (e.g. VSCode) for a file: URL.
	res, err := cli.ShowDocument(ctx, &protocol.ShowDocumentParams{
		URI:       url,
		External:  rangeOpt == nil,
		TakeFocus: true,
		Selection: rangeOpt, // optional
	})
	if err != nil {
		event.Error(ctx, "client.showDocument: %v", err)
	} else if res != nil && !res.Success {
		event.Log(ctx, fmt.Sprintf("client declined to open document %v", url))
	}
}

func (c *commandHandler) ChangeSignature(ctx context.Context, args command.ChangeSignatureArgs) (*protocol.WorkspaceEdit, error) {
	countChangeSignature.Inc()
	var result *protocol.WorkspaceEdit
	err := c.run(ctx, commandConfig{
		forURI: args.Location.URI,
	}, func(ctx context.Context, deps commandDeps) error {
		pkg, pgf, err := golang.NarrowestPackageForFile(ctx, deps.snapshot, args.Location.URI)
		if err != nil {
			return err
		}

		// For now, gopls only supports parameter permutation or removal.
		var perm []int
		for _, newParam := range args.NewParams {
			if newParam.NewField != "" {
				return fmt.Errorf("adding new parameters is currently unsupported")
			}
			perm = append(perm, newParam.OldIndex)
		}

		docedits, err := golang.ChangeSignature(ctx, deps.snapshot, pkg, pgf, args.Location.Range, perm)
		if err != nil {
			return err
		}
		wsedit := protocol.NewWorkspaceEdit(docedits...)
		if args.ResolveEdits {
			result = wsedit
			return nil
		}
		return applyChanges(ctx, c.s.client, docedits)
	})
	return result, err
}

func (c *commandHandler) DiagnoseFiles(ctx context.Context, args command.DiagnoseFilesArgs) error {
	return c.run(ctx, commandConfig{
		progress: "Diagnose files",
	}, func(ctx context.Context, _ commandDeps) error {

		// TODO(rfindley): even better would be textDocument/diagnostics (golang/go#60122).
		// Though note that implementing pull diagnostics may cause some servers to
		// request diagnostics in an ad-hoc manner, and break our intentional pacing.

		ctx, done := event.Start(ctx, "commandHandler.DiagnoseFiles")
		defer done()

		snapshots := make(map[*cache.Snapshot]bool)
		for _, uri := range args.Files {
			fh, snapshot, release, err := c.s.session.FileOf(ctx, uri)
			if err != nil {
				return err
			}
			if snapshots[snapshot] || snapshot.FileKind(fh) != file.Go {
				release()
				continue
			}
			defer release()
			snapshots[snapshot] = true
		}

		var wg sync.WaitGroup
		for snapshot := range snapshots {
			wg.Go(func() {

				// Use the operation context for diagnosis, rather than
				// snapshot.BackgroundContext, because this operation does not create
				// new snapshots (so they should also be diagnosed by other means).
				c.s.diagnoseSnapshot(ctx, snapshot, nil, 0)
			})
		}
		wg.Wait()

		return nil
	})
}

func (c *commandHandler) Views(ctx context.Context) ([]command.View, error) {
	var summaries []command.View
	for _, view := range c.s.session.Views() {
		summaries = append(summaries, command.View{
			ID:         view.ID(),
			Type:       view.Type().String(),
			Root:       view.Root(),
			Folder:     view.Folder().Dir,
			EnvOverlay: view.EnvOverlay(),
		})
	}
	return summaries, nil
}

func (c *commandHandler) FreeSymbols(ctx context.Context, viewID string, loc protocol.Location) error {
	web, err := c.s.getWeb()
	if err != nil {
		return err
	}
	url := web.freesymbolsURL(viewID, loc)
	openClientBrowser(ctx, c.s.client, "Free symbols", url, c.s.Options())
	return nil
}

func (c *commandHandler) SplitPackage(ctx context.Context, viewID, packageID string) error {
	web, err := c.s.getWeb()
	if err != nil {
		return err
	}
	url := web.splitpkgURL(viewID, packageID)
	openClientBrowser(ctx, c.s.client, "SplitPackage", url, c.s.Options())
	return nil
}

func (c *commandHandler) Assembly(ctx context.Context, viewID, packageID, symbol string) error {
	web, err := c.s.getWeb()
	if err != nil {
		return err
	}
	url := web.assemblyURL(viewID, packageID, symbol)
	openClientBrowser(ctx, c.s.client, "Assembly", url, c.s.Options())
	return nil
}

func (c *commandHandler) ClientOpenURL(ctx context.Context, url string) error {
	// Fall back to "Gopls: open your browser..." if we must send a showMessage
	// request, since we don't know the context of this command.
	openClientBrowser(ctx, c.s.client, "Gopls", url, c.s.Options())
	return nil
}

func (c *commandHandler) ScanImports(ctx context.Context) error {
	for _, v := range c.s.session.Views() {
		v.ScanImports()
	}
	return nil
}

func (c *commandHandler) PackageSymbols(ctx context.Context, args command.PackageSymbolsArgs) (command.PackageSymbolsResult, error) {
	var result command.PackageSymbolsResult
	err := c.run(ctx, commandConfig{
		forURI: args.URI,
	}, func(ctx context.Context, deps commandDeps) error {
		if deps.snapshot.FileKind(deps.fh) != file.Go {
			// golang/vscode-go#3681: fail silently, to avoid spurious error popups.
			return nil
		}
		res, err := golang.PackageSymbols(ctx, deps.snapshot, args.URI)
		if err != nil {
			return err
		}
		result = res
		return nil
	})

	// sort symbols for determinism
	sort.SliceStable(result.Symbols, func(i, j int) bool {
		iv, jv := result.Symbols[i], result.Symbols[j]
		if iv.Name == jv.Name {
			return iv.Range.Start.Line < jv.Range.Start.Line
		}
		return iv.Name < jv.Name
	})

	return result, err
}

// optionsStringToMap transforms comma-separated options of the form
// "foo=bar,baz=quux" to a go map. Returns nil if any options are malformed.
func optionsStringToMap(options string) (map[string][]string, error) {
	optionsMap := make(map[string][]string)
	for item := range strings.SplitSeq(options, ",") {
		key, option, found := strings.Cut(item, "=")
		if !found {
			return nil, fmt.Errorf("invalid option %q", item)
		}
		optionsMap[key] = append(optionsMap[key], option)
	}
	return optionsMap, nil
}

func (c *commandHandler) ImplementInterface(ctx context.Context, args command.ImplementInterfaceArgs, params *protocol.InteractiveParams) error {
	return c.run(ctx, commandConfig{
		progress: "Implement interface X",
		forURI:   args.Location.URI,
	}, func(ctx context.Context, deps commandDeps) error {
		iface, err := golang.FormAnswer[string](params, "interface")
		if err != nil {
			return err
		}

		edits, err := golang.ImplementInterface(ctx, deps.snapshot, args.Location, iface)
		if err != nil {
			return err
		}
		return applyChanges(ctx, c.s.client, edits)
	})
}

func (c *commandHandler) ModifyTags(ctx context.Context, args command.ModifyTagsArgs, params *protocol.InteractiveParams) error {
	return c.run(ctx, commandConfig{
		progress: "Modifying tags",
		forURI:   args.URI,
	}, func(ctx context.Context, deps commandDeps) error {
		if len(params.FormAnswers) > 0 {
			switch args.Modification {
			case "add":
				tags, err := golang.FormAnswer[string](params, "tags")
				if err != nil {
					return err
				}
				args.Add, err = golang.SanitizeTags(tags)
				if err != nil {
					return err
				}
				args.Transform, err = golang.FormAnswer[string](params, "transform")
				if err != nil {
					return err
				}
			case "remove":
				tags, err := golang.FormAnswer[string](params, "tags")
				if err != nil {
					return err
				}
				args.Remove, err = golang.SanitizeTags(tags)
				if err != nil {
					return err
				}
			default:
				return fmt.Errorf("unsupported modify tags operation: %s", args.Modification)
			}
		}

		m := &modifytags.Modification{
			Clear:        args.Clear,
			ClearOptions: args.ClearOptions,
			ValueFormat:  args.ValueFormat,
			Overwrite:    args.Overwrite,
		}

		transform, err := parseTransform(args.Transform)
		if err != nil {
			return err
		}
		m.Transform = transform

		// Each command involves either adding or removing tags, depending on
		// whether Add or Clear is set.
		if args.Add != "" {
			countAddStructTags.Inc()
			m.Add = strings.Split(args.Add, ",")
		} else if args.Clear {
			countRemoveStructTags.Inc()
		}
		if args.AddOptions != "" {
			if options, err := optionsStringToMap(args.AddOptions); err != nil {
				return err
			} else {
				m.AddOptions = options
			}
		}
		if args.Remove != "" {
			m.Remove = strings.Split(args.Remove, ",")
		}
		if args.RemoveOptions != "" {
			if options, err := optionsStringToMap(args.RemoveOptions); err != nil {
				return err
			} else {
				m.RemoveOptions = options
			}
		}
		fh, err := deps.snapshot.ReadFile(ctx, args.URI)
		if err != nil {
			return err
		}
		changes, err := golang.ModifyTags(ctx, deps.snapshot, fh, args, m)
		if err != nil {
			return err
		}
		return applyChanges(ctx, c.s.client, changes)
	})
}

func parseTransform(input string) (modifytags.Transform, error) {
	switch input {
	case "camelcase":
		return modifytags.CamelCase, nil
	case "lispcase":
		return modifytags.LispCase, nil
	case "pascalcase":
		return modifytags.PascalCase, nil
	case "titlecase":
		return modifytags.TitleCase, nil
	case "keep":
		return modifytags.Keep, nil
	case "":
		fallthrough
	case "snakecase":
		return modifytags.SnakeCase, nil
	default:
		return modifytags.SnakeCase, fmt.Errorf("invalid Transform value")
	}
}

func (c *commandHandler) MoveType(ctx context.Context, args command.MoveTypeArgs) error {
	err := c.run(ctx, commandConfig{
		forURI: args.Location.URI,
	}, func(ctx context.Context, deps commandDeps) error {
		// TODO(mkalil): implement with interactive params
		destFile := filepath.Join(args.Location.URI.DirPath(), "otherpkg", "destfile.go")
		destURI := protocol.URIFromPath(destFile)
		changes, rng, err := golang.MoveType(ctx, deps.fh, deps.snapshot, args.Location, destURI)
		if err != nil {
			return err
		}
		// Open the file where the type was moved to.
		showDocumentImpl(ctx, c.s.client, protocol.URI(destURI), &rng.Range, c.s.options)
		return applyChanges(ctx, c.s.client, changes)
	})
	return err
}
