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

import (
	"bytes"
	"context"
	"errors"
	"fmt"
	"os"
	"path"
	"path/filepath"
	"regexp"
	"strings"
	"sync"

	"golang.org/x/tools/gopls/internal/lsp/command"
	"golang.org/x/tools/gopls/internal/lsp/glob"
	"golang.org/x/tools/gopls/internal/lsp/protocol"
	"golang.org/x/tools/gopls/internal/lsp/source"
	"golang.org/x/tools/gopls/internal/span"
	"golang.org/x/tools/internal/jsonrpc2"
	"golang.org/x/tools/internal/jsonrpc2/servertest"
	"golang.org/x/tools/internal/xcontext"
)

// Editor is a fake editor client.  It keeps track of client state and can be
// used for writing LSP tests.
type Editor struct {

	// Server, client, and sandbox are concurrency safe and written only
	// at construction time, so do not require synchronization.
	Server     protocol.Server
	cancelConn func()
	serverConn jsonrpc2.Conn
	client     *Client
	sandbox    *Sandbox
	defaultEnv map[string]string

	// TODO(adonovan): buffers should be keyed by protocol.DocumentURI.
	mu                 sync.Mutex
	config             EditorConfig                // editor configuration
	buffers            map[string]buffer           // open buffers (relative path -> buffer content)
	serverCapabilities protocol.ServerCapabilities // capabilities / options
	watchPatterns      []*glob.Glob                // glob patterns to watch

	// Call metrics for the purpose of expectations. This is done in an ad-hoc
	// manner for now. Perhaps in the future we should do something more
	// systematic. Guarded with a separate mutex as calls may need to be accessed
	// asynchronously via callbacks into the Editor.
	callsMu sync.Mutex
	calls   CallCounts
}

// CallCounts tracks the number of protocol notifications of different types.
type CallCounts struct {
	DidOpen, DidChange, DidSave, DidChangeWatchedFiles, DidClose uint64
}

// buffer holds information about an open buffer in the editor.
type buffer struct {
	version int              // monotonic version; incremented on edits
	path    string           // relative path in the workspace
	mapper  *protocol.Mapper // buffer content
	dirty   bool             // if true, content is unsaved (TODO(rfindley): rename this field)
}

func (b buffer) text() string {
	return string(b.mapper.Content)
}

// EditorConfig configures the editor's LSP session. This is similar to
// source.UserOptions, but we use a separate type here so that we expose only
// that configuration which we support.
//
// The zero value for EditorConfig should correspond to its defaults.
type EditorConfig struct {
	// Env holds environment variables to apply on top of the default editor
	// environment. When applying these variables, the special string
	// $SANDBOX_WORKDIR is replaced by the absolute path to the sandbox working
	// directory.
	Env map[string]string

	// WorkspaceFolders is the workspace folders to configure on the LSP server,
	// relative to the sandbox workdir.
	//
	// As a special case, if WorkspaceFolders is nil the editor defaults to
	// configuring a single workspace folder corresponding to the workdir root.
	// To explicitly send no workspace folders, use an empty (non-nil) slice.
	WorkspaceFolders []string

	// Whether to edit files with windows line endings.
	WindowsLineEndings bool

	// Map of language ID -> regexp to match, used to set the file type of new
	// buffers. Applied as an overlay on top of the following defaults:
	//  "go" -> ".*\.go"
	//  "go.mod" -> "go\.mod"
	//  "go.sum" -> "go\.sum"
	//  "gotmpl" -> ".*tmpl"
	FileAssociations map[string]string

	// Settings holds user-provided configuration for the LSP server.
	Settings map[string]interface{}
}

// NewEditor Creates a new Editor.
func NewEditor(sandbox *Sandbox, config EditorConfig) *Editor {
	return &Editor{
		buffers:    make(map[string]buffer),
		sandbox:    sandbox,
		defaultEnv: sandbox.GoEnv(),
		config:     config,
	}
}

// Connect configures the editor to communicate with an LSP server on conn. It
// is not concurrency safe, and should be called at most once, before using the
// editor.
//
// It returns the editor, so that it may be called as follows:
//
//	editor, err := NewEditor(s).Connect(ctx, conn, hooks)
func (e *Editor) Connect(ctx context.Context, connector servertest.Connector, hooks ClientHooks) (*Editor, error) {
	bgCtx, cancelConn := context.WithCancel(xcontext.Detach(ctx))
	conn := connector.Connect(bgCtx)
	e.cancelConn = cancelConn

	e.serverConn = conn
	e.Server = protocol.ServerDispatcher(conn)
	e.client = &Client{editor: e, hooks: hooks}
	conn.Go(bgCtx,
		protocol.Handlers(
			protocol.ClientHandler(e.client,
				jsonrpc2.MethodNotFound)))

	if err := e.initialize(ctx); err != nil {
		return nil, err
	}
	e.sandbox.Workdir.AddWatcher(e.onFileChanges)
	return e, nil
}

func (e *Editor) Stats() CallCounts {
	e.callsMu.Lock()
	defer e.callsMu.Unlock()
	return e.calls
}

// Shutdown issues the 'shutdown' LSP notification.
func (e *Editor) Shutdown(ctx context.Context) error {
	if e.Server != nil {
		if err := e.Server.Shutdown(ctx); err != nil {
			return fmt.Errorf("Shutdown: %w", err)
		}
	}
	return nil
}

// Exit issues the 'exit' LSP notification.
func (e *Editor) Exit(ctx context.Context) error {
	if e.Server != nil {
		// Not all LSP clients issue the exit RPC, but we do so here to ensure that
		// we gracefully handle it on multi-session servers.
		if err := e.Server.Exit(ctx); err != nil {
			return fmt.Errorf("Exit: %w", err)
		}
	}
	return nil
}

// Close issues the shutdown and exit sequence an editor should.
func (e *Editor) Close(ctx context.Context) error {
	if err := e.Shutdown(ctx); err != nil {
		return err
	}
	if err := e.Exit(ctx); err != nil {
		return err
	}
	defer func() {
		e.cancelConn()
	}()

	// called close on the editor should result in the connection closing
	select {
	case <-e.serverConn.Done():
		// connection closed itself
		return nil
	case <-ctx.Done():
		return fmt.Errorf("connection not closed: %w", ctx.Err())
	}
}

// Client returns the LSP client for this editor.
func (e *Editor) Client() *Client {
	return e.client
}

// settingsLocked builds the settings map for use in LSP settings RPCs.
//
// e.mu must be held while calling this function.
func (e *Editor) settingsLocked() map[string]interface{} {
	env := make(map[string]string)
	for k, v := range e.defaultEnv {
		env[k] = v
	}
	for k, v := range e.config.Env {
		env[k] = v
	}
	for k, v := range env {
		v = strings.ReplaceAll(v, "$SANDBOX_WORKDIR", e.sandbox.Workdir.RootURI().SpanURI().Filename())
		env[k] = v
	}

	settings := map[string]interface{}{
		"env": env,

		// Use verbose progress reporting so that regtests can assert on
		// asynchronous operations being completed (such as diagnosing a snapshot).
		"verboseWorkDoneProgress": true,

		// Set a generous completion budget, so that tests don't flake because
		// completions are too slow.
		"completionBudget": "10s",

		// Shorten the diagnostic delay to speed up test execution (else we'd add
		// the default delay to each assertion about diagnostics)
		"diagnosticsDelay": "10ms",
	}

	for k, v := range e.config.Settings {
		if k == "env" {
			panic("must not provide env via the EditorConfig.Settings field: use the EditorConfig.Env field instead")
		}
		settings[k] = v
	}

	return settings
}

func (e *Editor) initialize(ctx context.Context) error {
	params := &protocol.ParamInitialize{}
	params.ClientInfo.Name = "fakeclient"
	params.ClientInfo.Version = "v1.0.0"
	e.mu.Lock()
	params.WorkspaceFolders = e.makeWorkspaceFoldersLocked()
	params.InitializationOptions = e.settingsLocked()
	e.mu.Unlock()
	params.Capabilities.Workspace.Configuration = true
	params.Capabilities.Window.WorkDoneProgress = true

	// TODO: set client capabilities
	params.Capabilities.TextDocument.Completion.CompletionItem.TagSupport.ValueSet = []protocol.CompletionItemTag{protocol.ComplDeprecated}

	params.Capabilities.TextDocument.Completion.CompletionItem.SnippetSupport = true
	params.Capabilities.TextDocument.SemanticTokens.Requests.Full = true
	// copied from lsp/semantic.go to avoid import cycle in tests
	params.Capabilities.TextDocument.SemanticTokens.TokenTypes = []string{
		"namespace", "type", "class", "enum", "interface",
		"struct", "typeParameter", "parameter", "variable", "property", "enumMember",
		"event", "function", "method", "macro", "keyword", "modifier", "comment",
		"string", "number", "regexp", "operator",
	}
	params.Capabilities.TextDocument.SemanticTokens.TokenModifiers = []string{
		"declaration", "definition", "readonly", "static",
		"deprecated", "abstract", "async", "modification", "documentation", "defaultLibrary",
	}

	// This is a bit of a hack, since the fake editor doesn't actually support
	// watching changed files that match a specific glob pattern. However, the
	// editor does send didChangeWatchedFiles notifications, so set this to
	// true.
	params.Capabilities.Workspace.DidChangeWatchedFiles.DynamicRegistration = true
	params.Capabilities.Workspace.WorkspaceEdit = &protocol.WorkspaceEditClientCapabilities{
		ResourceOperations: []protocol.ResourceOperationKind{
			"rename",
		},
	}

	params.Trace = "messages"
	// TODO: support workspace folders.
	if e.Server != nil {
		resp, err := e.Server.Initialize(ctx, params)
		if err != nil {
			return fmt.Errorf("initialize: %w", err)
		}
		e.mu.Lock()
		e.serverCapabilities = resp.Capabilities
		e.mu.Unlock()

		if err := e.Server.Initialized(ctx, &protocol.InitializedParams{}); err != nil {
			return fmt.Errorf("initialized: %w", err)
		}
	}
	// TODO: await initial configuration here, or expect gopls to manage that?
	return nil
}

// makeWorkspaceFoldersLocked creates a slice of workspace folders to use for
// this editing session, based on the editor configuration.
//
// e.mu must be held while calling this function.
func (e *Editor) makeWorkspaceFoldersLocked() (folders []protocol.WorkspaceFolder) {
	paths := e.config.WorkspaceFolders
	if len(paths) == 0 {
		paths = append(paths, string(e.sandbox.Workdir.RelativeTo))
	}

	for _, path := range paths {
		uri := string(e.sandbox.Workdir.URI(path))
		folders = append(folders, protocol.WorkspaceFolder{
			URI:  uri,
			Name: filepath.Base(uri),
		})
	}

	return folders
}

// onFileChanges is registered to be called by the Workdir on any writes that
// go through the Workdir API. It is called synchronously by the Workdir.
func (e *Editor) onFileChanges(ctx context.Context, evts []protocol.FileEvent) {
	if e.Server == nil {
		return
	}

	// e may be locked when onFileChanges is called, but it is important that we
	// synchronously increment this counter so that we can subsequently assert on
	// the number of expected DidChangeWatchedFiles calls.
	e.callsMu.Lock()
	e.calls.DidChangeWatchedFiles++
	e.callsMu.Unlock()

	// Since e may be locked, we must run this mutation asynchronously.
	go func() {
		e.mu.Lock()
		defer e.mu.Unlock()
		for _, evt := range evts {
			// Always send an on-disk change, even for events that seem useless
			// because they're shadowed by an open buffer.
			path := e.sandbox.Workdir.URIToPath(evt.URI)
			if buf, ok := e.buffers[path]; ok {
				// Following VS Code, don't honor deletions or changes to dirty buffers.
				if buf.dirty || evt.Type == protocol.Deleted {
					continue
				}

				content, err := e.sandbox.Workdir.ReadFile(path)
				if err != nil {
					continue // A race with some other operation.
				}
				// No need to update if the buffer content hasn't changed.
				if string(content) == buf.text() {
					continue
				}
				// During shutdown, this call will fail. Ignore the error.
				_ = e.setBufferContentLocked(ctx, path, false, content, nil)
			}
		}
		var matchedEvts []protocol.FileEvent
		for _, evt := range evts {
			filename := filepath.ToSlash(evt.URI.SpanURI().Filename())
			for _, g := range e.watchPatterns {
				if g.Match(filename) {
					matchedEvts = append(matchedEvts, evt)
					break
				}
			}
		}

		// TODO(rfindley): don't send notifications while locked.
		e.Server.DidChangeWatchedFiles(ctx, &protocol.DidChangeWatchedFilesParams{
			Changes: matchedEvts,
		})
	}()
}

// OpenFile creates a buffer for the given workdir-relative file.
//
// If the file is already open, it is a no-op.
func (e *Editor) OpenFile(ctx context.Context, path string) error {
	if e.HasBuffer(path) {
		return nil
	}
	content, err := e.sandbox.Workdir.ReadFile(path)
	if err != nil {
		return err
	}
	if e.Config().WindowsLineEndings {
		content = toWindowsLineEndings(content)
	}
	return e.createBuffer(ctx, path, false, content)
}

// toWindowsLineEndings checks whether content has windows line endings.
//
// If so, it returns content unmodified. If not, it returns a new byte slice modified to use CRLF line endings.
func toWindowsLineEndings(content []byte) []byte {
	abnormal := false
	for i, b := range content {
		if b == '\n' && (i == 0 || content[i-1] != '\r') {
			abnormal = true
			break
		}
	}
	if !abnormal {
		return content
	}
	var buf bytes.Buffer
	for i, b := range content {
		if b == '\n' && (i == 0 || content[i-1] != '\r') {
			buf.WriteByte('\r')
		}
		buf.WriteByte(b)
	}
	return buf.Bytes()
}

// CreateBuffer creates a new unsaved buffer corresponding to the workdir path,
// containing the given textual content.
func (e *Editor) CreateBuffer(ctx context.Context, path, content string) error {
	return e.createBuffer(ctx, path, true, []byte(content))
}

func (e *Editor) createBuffer(ctx context.Context, path string, dirty bool, content []byte) error {
	e.mu.Lock()

	if _, ok := e.buffers[path]; ok {
		e.mu.Unlock()
		return fmt.Errorf("buffer %q already exists", path)
	}

	uri := e.sandbox.Workdir.URI(path).SpanURI()
	buf := buffer{
		version: 1,
		path:    path,
		mapper:  protocol.NewMapper(uri, content),
		dirty:   dirty,
	}
	e.buffers[path] = buf

	item := e.textDocumentItem(buf)
	e.mu.Unlock()

	return e.sendDidOpen(ctx, item)
}

// textDocumentItem builds a protocol.TextDocumentItem for the given buffer.
//
// Precondition: e.mu must be held.
func (e *Editor) textDocumentItem(buf buffer) protocol.TextDocumentItem {
	return protocol.TextDocumentItem{
		URI:        e.sandbox.Workdir.URI(buf.path),
		LanguageID: languageID(buf.path, e.config.FileAssociations),
		Version:    int32(buf.version),
		Text:       buf.text(),
	}
}

func (e *Editor) sendDidOpen(ctx context.Context, item protocol.TextDocumentItem) error {
	if e.Server != nil {
		if err := e.Server.DidOpen(ctx, &protocol.DidOpenTextDocumentParams{
			TextDocument: item,
		}); err != nil {
			return fmt.Errorf("DidOpen: %w", err)
		}
		e.callsMu.Lock()
		e.calls.DidOpen++
		e.callsMu.Unlock()
	}
	return nil
}

var defaultFileAssociations = map[string]*regexp.Regexp{
	"go":      regexp.MustCompile(`^.*\.go$`), // '$' is important: don't match .gotmpl!
	"go.mod":  regexp.MustCompile(`^go\.mod$`),
	"go.sum":  regexp.MustCompile(`^go(\.work)?\.sum$`),
	"go.work": regexp.MustCompile(`^go\.work$`),
	"gotmpl":  regexp.MustCompile(`^.*tmpl$`),
}

// languageID returns the language identifier for the path p given the user
// configured fileAssociations.
func languageID(p string, fileAssociations map[string]string) string {
	base := path.Base(p)
	for lang, re := range fileAssociations {
		re := regexp.MustCompile(re)
		if re.MatchString(base) {
			return lang
		}
	}
	for lang, re := range defaultFileAssociations {
		if re.MatchString(base) {
			return lang
		}
	}
	return ""
}

// CloseBuffer removes the current buffer (regardless of whether it is saved).
func (e *Editor) CloseBuffer(ctx context.Context, path string) error {
	e.mu.Lock()
	_, ok := e.buffers[path]
	if !ok {
		e.mu.Unlock()
		return ErrUnknownBuffer
	}
	delete(e.buffers, path)
	e.mu.Unlock()

	return e.sendDidClose(ctx, e.TextDocumentIdentifier(path))
}

func (e *Editor) sendDidClose(ctx context.Context, doc protocol.TextDocumentIdentifier) error {
	if e.Server != nil {
		if err := e.Server.DidClose(ctx, &protocol.DidCloseTextDocumentParams{
			TextDocument: doc,
		}); err != nil {
			return fmt.Errorf("DidClose: %w", err)
		}
		e.callsMu.Lock()
		e.calls.DidClose++
		e.callsMu.Unlock()
	}
	return nil
}

func (e *Editor) TextDocumentIdentifier(path string) protocol.TextDocumentIdentifier {
	return protocol.TextDocumentIdentifier{
		URI: e.sandbox.Workdir.URI(path),
	}
}

// SaveBuffer writes the content of the buffer specified by the given path to
// the filesystem.
func (e *Editor) SaveBuffer(ctx context.Context, path string) error {
	if err := e.OrganizeImports(ctx, path); err != nil {
		return fmt.Errorf("organizing imports before save: %w", err)
	}
	if err := e.FormatBuffer(ctx, path); err != nil {
		return fmt.Errorf("formatting before save: %w", err)
	}
	return e.SaveBufferWithoutActions(ctx, path)
}

func (e *Editor) SaveBufferWithoutActions(ctx context.Context, path string) error {
	e.mu.Lock()
	defer e.mu.Unlock()
	buf, ok := e.buffers[path]
	if !ok {
		return fmt.Errorf(fmt.Sprintf("unknown buffer: %q", path))
	}
	content := buf.text()
	includeText := false
	syncOptions, ok := e.serverCapabilities.TextDocumentSync.(protocol.TextDocumentSyncOptions)
	if ok {
		includeText = syncOptions.Save.IncludeText
	}

	docID := e.TextDocumentIdentifier(buf.path)
	if e.Server != nil {
		if err := e.Server.WillSave(ctx, &protocol.WillSaveTextDocumentParams{
			TextDocument: docID,
			Reason:       protocol.Manual,
		}); err != nil {
			return fmt.Errorf("WillSave: %w", err)
		}
	}
	if err := e.sandbox.Workdir.WriteFile(ctx, path, content); err != nil {
		return fmt.Errorf("writing %q: %w", path, err)
	}

	buf.dirty = false
	e.buffers[path] = buf

	if e.Server != nil {
		params := &protocol.DidSaveTextDocumentParams{
			TextDocument: docID,
		}
		if includeText {
			params.Text = &content
		}
		if err := e.Server.DidSave(ctx, params); err != nil {
			return fmt.Errorf("DidSave: %w", err)
		}
		e.callsMu.Lock()
		e.calls.DidSave++
		e.callsMu.Unlock()
	}
	return nil
}

// ErrNoMatch is returned if a regexp search fails.
var (
	ErrNoMatch       = errors.New("no match")
	ErrUnknownBuffer = errors.New("unknown buffer")
)

// regexpLocation returns the location of the first occurrence of either re
// or its singular subgroup. It returns ErrNoMatch if the regexp doesn't match.
func regexpLocation(mapper *protocol.Mapper, re string) (protocol.Location, error) {
	var start, end int
	rec, err := regexp.Compile(re)
	if err != nil {
		return protocol.Location{}, err
	}
	indexes := rec.FindSubmatchIndex(mapper.Content)
	if indexes == nil {
		return protocol.Location{}, ErrNoMatch
	}
	switch len(indexes) {
	case 2:
		// no subgroups: return the range of the regexp expression
		start, end = indexes[0], indexes[1]
	case 4:
		// one subgroup: return its range
		start, end = indexes[2], indexes[3]
	default:
		return protocol.Location{}, fmt.Errorf("invalid search regexp %q: expect either 0 or 1 subgroups, got %d", re, len(indexes)/2-1)
	}
	return mapper.OffsetLocation(start, end)
}

// RegexpSearch returns the Location of the first match for re in the buffer
// bufName. For convenience, RegexpSearch supports the following two modes:
//  1. If re has no subgroups, return the position of the match for re itself.
//  2. If re has one subgroup, return the position of the first subgroup.
//
// It returns an error re is invalid, has more than one subgroup, or doesn't
// match the buffer.
func (e *Editor) RegexpSearch(bufName, re string) (protocol.Location, error) {
	e.mu.Lock()
	buf, ok := e.buffers[bufName]
	e.mu.Unlock()
	if !ok {
		return protocol.Location{}, ErrUnknownBuffer
	}
	return regexpLocation(buf.mapper, re)
}

// RegexpReplace edits the buffer corresponding to path by replacing the first
// instance of re, or its first subgroup, with the replace text. See
// RegexpSearch for more explanation of these two modes.
// It returns an error if re is invalid, has more than one subgroup, or doesn't
// match the buffer.
func (e *Editor) RegexpReplace(ctx context.Context, path, re, replace string) error {
	e.mu.Lock()
	defer e.mu.Unlock()
	buf, ok := e.buffers[path]
	if !ok {
		return ErrUnknownBuffer
	}
	loc, err := regexpLocation(buf.mapper, re)
	if err != nil {
		return err
	}
	edits := []protocol.TextEdit{{
		Range:   loc.Range,
		NewText: replace,
	}}
	patched, err := applyEdits(buf.mapper, edits, e.config.WindowsLineEndings)
	if err != nil {
		return fmt.Errorf("editing %q: %v", path, err)
	}
	return e.setBufferContentLocked(ctx, path, true, patched, edits)
}

// EditBuffer applies the given test edits to the buffer identified by path.
func (e *Editor) EditBuffer(ctx context.Context, path string, edits []protocol.TextEdit) error {
	e.mu.Lock()
	defer e.mu.Unlock()
	return e.editBufferLocked(ctx, path, edits)
}

func (e *Editor) SetBufferContent(ctx context.Context, path, content string) error {
	e.mu.Lock()
	defer e.mu.Unlock()
	return e.setBufferContentLocked(ctx, path, true, []byte(content), nil)
}

// HasBuffer reports whether the file name is open in the editor.
func (e *Editor) HasBuffer(name string) bool {
	e.mu.Lock()
	defer e.mu.Unlock()
	_, ok := e.buffers[name]
	return ok
}

// BufferText returns the content of the buffer with the given name, or "" if
// the file at that path is not open. The second return value reports whether
// the file is open.
func (e *Editor) BufferText(name string) (string, bool) {
	e.mu.Lock()
	defer e.mu.Unlock()
	buf, ok := e.buffers[name]
	if !ok {
		return "", false
	}
	return buf.text(), true
}

// BufferVersion returns the current version of the buffer corresponding to
// name (or 0 if it is not being edited).
func (e *Editor) BufferVersion(name string) int {
	e.mu.Lock()
	defer e.mu.Unlock()
	return e.buffers[name].version
}

func (e *Editor) editBufferLocked(ctx context.Context, path string, edits []protocol.TextEdit) error {
	buf, ok := e.buffers[path]
	if !ok {
		return fmt.Errorf("unknown buffer %q", path)
	}
	content, err := applyEdits(buf.mapper, edits, e.config.WindowsLineEndings)
	if err != nil {
		return fmt.Errorf("editing %q: %v; edits:\n%v", path, err, edits)
	}
	return e.setBufferContentLocked(ctx, path, true, content, edits)
}

func (e *Editor) setBufferContentLocked(ctx context.Context, path string, dirty bool, content []byte, fromEdits []protocol.TextEdit) error {
	buf, ok := e.buffers[path]
	if !ok {
		return fmt.Errorf("unknown buffer %q", path)
	}
	buf.mapper = protocol.NewMapper(buf.mapper.URI, content)
	buf.version++
	buf.dirty = dirty
	e.buffers[path] = buf
	// A simple heuristic: if there is only one edit, send it incrementally.
	// Otherwise, send the entire content.
	var evts []protocol.TextDocumentContentChangeEvent
	if len(fromEdits) == 1 {
		evts = append(evts, EditToChangeEvent(fromEdits[0]))
	} else {
		evts = append(evts, protocol.TextDocumentContentChangeEvent{
			Text: buf.text(),
		})
	}
	params := &protocol.DidChangeTextDocumentParams{
		TextDocument: protocol.VersionedTextDocumentIdentifier{
			Version:                int32(buf.version),
			TextDocumentIdentifier: e.TextDocumentIdentifier(buf.path),
		},
		ContentChanges: evts,
	}
	if e.Server != nil {
		if err := e.Server.DidChange(ctx, params); err != nil {
			return fmt.Errorf("DidChange: %w", err)
		}
		e.callsMu.Lock()
		e.calls.DidChange++
		e.callsMu.Unlock()
	}
	return nil
}

// GoToDefinition jumps to the definition of the symbol at the given position
// in an open buffer. It returns the location of the resulting jump.
func (e *Editor) GoToDefinition(ctx context.Context, loc protocol.Location) (protocol.Location, error) {
	if err := e.checkBufferLocation(loc); err != nil {
		return protocol.Location{}, err
	}
	params := &protocol.DefinitionParams{}
	params.TextDocument.URI = loc.URI
	params.Position = loc.Range.Start

	resp, err := e.Server.Definition(ctx, params)
	if err != nil {
		return protocol.Location{}, fmt.Errorf("definition: %w", err)
	}
	return e.extractFirstLocation(ctx, resp)
}

// GoToTypeDefinition jumps to the type definition of the symbol at the given location
// in an open buffer.
func (e *Editor) GoToTypeDefinition(ctx context.Context, loc protocol.Location) (protocol.Location, error) {
	if err := e.checkBufferLocation(loc); err != nil {
		return protocol.Location{}, err
	}
	params := &protocol.TypeDefinitionParams{}
	params.TextDocument.URI = loc.URI
	params.Position = loc.Range.Start

	resp, err := e.Server.TypeDefinition(ctx, params)
	if err != nil {
		return protocol.Location{}, fmt.Errorf("type definition: %w", err)
	}
	return e.extractFirstLocation(ctx, resp)
}

// extractFirstPathAndPos returns the first location.
// It opens the file if needed.
func (e *Editor) extractFirstLocation(ctx context.Context, locs []protocol.Location) (protocol.Location, error) {
	if len(locs) == 0 {
		return protocol.Location{}, nil
	}

	newPath := e.sandbox.Workdir.URIToPath(locs[0].URI)
	if !e.HasBuffer(newPath) {
		if err := e.OpenFile(ctx, newPath); err != nil {
			return protocol.Location{}, fmt.Errorf("OpenFile: %w", err)
		}
	}
	return locs[0], nil
}

// Symbol performs a workspace symbol search using query
func (e *Editor) Symbol(ctx context.Context, query string) ([]protocol.SymbolInformation, error) {
	params := &protocol.WorkspaceSymbolParams{Query: query}
	return e.Server.Symbol(ctx, params)
}

// OrganizeImports requests and performs the source.organizeImports codeAction.
func (e *Editor) OrganizeImports(ctx context.Context, path string) error {
	loc := protocol.Location{URI: e.sandbox.Workdir.URI(path)} // zero Range => whole file
	_, err := e.applyCodeActions(ctx, loc, nil, protocol.SourceOrganizeImports)
	return err
}

// RefactorRewrite requests and performs the source.refactorRewrite codeAction.
func (e *Editor) RefactorRewrite(ctx context.Context, loc protocol.Location) error {
	applied, err := e.applyCodeActions(ctx, loc, nil, protocol.RefactorRewrite)
	if err != nil {
		return err
	}
	if applied == 0 {
		return fmt.Errorf("no refactorings were applied")
	}
	return nil
}

// ApplyQuickFixes requests and performs the quickfix codeAction.
func (e *Editor) ApplyQuickFixes(ctx context.Context, loc protocol.Location, diagnostics []protocol.Diagnostic) error {
	applied, err := e.applyCodeActions(ctx, loc, diagnostics, protocol.SourceFixAll, protocol.QuickFix)
	if applied == 0 {
		return fmt.Errorf("no quick fixes were applied")
	}
	return err
}

// ApplyCodeAction applies the given code action.
func (e *Editor) ApplyCodeAction(ctx context.Context, action protocol.CodeAction) error {
	for _, change := range action.Edit.DocumentChanges {
		if change.TextDocumentEdit != nil {
			path := e.sandbox.Workdir.URIToPath(change.TextDocumentEdit.TextDocument.URI)
			if int32(e.buffers[path].version) != change.TextDocumentEdit.TextDocument.Version {
				// Skip edits for old versions.
				continue
			}
			if err := e.EditBuffer(ctx, path, change.TextDocumentEdit.Edits); err != nil {
				return fmt.Errorf("editing buffer %q: %w", path, err)
			}
		}
	}
	// Execute any commands. The specification says that commands are
	// executed after edits are applied.
	if action.Command != nil {
		if _, err := e.ExecuteCommand(ctx, &protocol.ExecuteCommandParams{
			Command:   action.Command.Command,
			Arguments: action.Command.Arguments,
		}); err != nil {
			return err
		}
	}
	// Some commands may edit files on disk.
	return e.sandbox.Workdir.CheckForFileChanges(ctx)
}

// GetQuickFixes returns the available quick fix code actions.
func (e *Editor) GetQuickFixes(ctx context.Context, loc protocol.Location, diagnostics []protocol.Diagnostic) ([]protocol.CodeAction, error) {
	return e.getCodeActions(ctx, loc, diagnostics, protocol.QuickFix, protocol.SourceFixAll)
}

func (e *Editor) applyCodeActions(ctx context.Context, loc protocol.Location, diagnostics []protocol.Diagnostic, only ...protocol.CodeActionKind) (int, error) {
	actions, err := e.getCodeActions(ctx, loc, diagnostics, only...)
	if err != nil {
		return 0, err
	}
	applied := 0
	for _, action := range actions {
		if action.Title == "" {
			return 0, fmt.Errorf("empty title for code action")
		}
		var match bool
		for _, o := range only {
			if action.Kind == o {
				match = true
				break
			}
		}
		if !match {
			continue
		}
		applied++
		if err := e.ApplyCodeAction(ctx, action); err != nil {
			return 0, err
		}
	}
	return applied, nil
}

func (e *Editor) getCodeActions(ctx context.Context, loc protocol.Location, diagnostics []protocol.Diagnostic, only ...protocol.CodeActionKind) ([]protocol.CodeAction, error) {
	if e.Server == nil {
		return nil, nil
	}
	params := &protocol.CodeActionParams{}
	params.TextDocument.URI = loc.URI
	params.Context.Only = only
	params.Range = loc.Range // may be zero => whole file
	if diagnostics != nil {
		params.Context.Diagnostics = diagnostics
	}
	return e.Server.CodeAction(ctx, params)
}

func (e *Editor) ExecuteCommand(ctx context.Context, params *protocol.ExecuteCommandParams) (interface{}, error) {
	if e.Server == nil {
		return nil, nil
	}
	var match bool
	// Ensure that this command was actually listed as a supported command.
	for _, command := range e.serverCapabilities.ExecuteCommandProvider.Commands {
		if command == params.Command {
			match = true
			break
		}
	}
	if !match {
		return nil, fmt.Errorf("unsupported command %q", params.Command)
	}
	result, err := e.Server.ExecuteCommand(ctx, params)
	if err != nil {
		return nil, err
	}
	// Some commands use the go command, which writes directly to disk.
	// For convenience, check for those changes.
	if err := e.sandbox.Workdir.CheckForFileChanges(ctx); err != nil {
		return nil, err
	}
	return result, nil
}

// FormatBuffer gofmts a Go file.
func (e *Editor) FormatBuffer(ctx context.Context, path string) error {
	if e.Server == nil {
		return nil
	}
	e.mu.Lock()
	version := e.buffers[path].version
	e.mu.Unlock()
	params := &protocol.DocumentFormattingParams{}
	params.TextDocument.URI = e.sandbox.Workdir.URI(path)
	edits, err := e.Server.Formatting(ctx, params)
	if err != nil {
		return fmt.Errorf("textDocument/formatting: %w", err)
	}
	e.mu.Lock()
	defer e.mu.Unlock()
	if versionAfter := e.buffers[path].version; versionAfter != version {
		return fmt.Errorf("before receipt of formatting edits, buffer version changed from %d to %d", version, versionAfter)
	}
	if len(edits) == 0 {
		return nil
	}
	return e.editBufferLocked(ctx, path, edits)
}

func (e *Editor) checkBufferLocation(loc protocol.Location) error {
	e.mu.Lock()
	defer e.mu.Unlock()
	path := e.sandbox.Workdir.URIToPath(loc.URI)
	buf, ok := e.buffers[path]
	if !ok {
		return fmt.Errorf("buffer %q is not open", path)
	}

	_, _, err := buf.mapper.RangeOffsets(loc.Range)
	return err
}

// RunGenerate runs `go generate` non-recursively in the workdir-relative dir
// path. It does not report any resulting file changes as a watched file
// change, so must be followed by a call to Workdir.CheckForFileChanges once
// the generate command has completed.
// TODO(rFindley): this shouldn't be necessary anymore. Delete it.
func (e *Editor) RunGenerate(ctx context.Context, dir string) error {
	if e.Server == nil {
		return nil
	}
	absDir := e.sandbox.Workdir.AbsPath(dir)
	cmd, err := command.NewGenerateCommand("", command.GenerateArgs{
		Dir:       protocol.URIFromSpanURI(span.URIFromPath(absDir)),
		Recursive: false,
	})
	if err != nil {
		return err
	}
	params := &protocol.ExecuteCommandParams{
		Command:   cmd.Command,
		Arguments: cmd.Arguments,
	}
	if _, err := e.ExecuteCommand(ctx, params); err != nil {
		return fmt.Errorf("running generate: %v", err)
	}
	// Unfortunately we can't simply poll the workdir for file changes here,
	// because server-side command may not have completed. In regtests, we can
	// Await this state change, but here we must delegate that responsibility to
	// the caller.
	return nil
}

// CodeLens executes a codelens request on the server.
func (e *Editor) CodeLens(ctx context.Context, path string) ([]protocol.CodeLens, error) {
	if e.Server == nil {
		return nil, nil
	}
	e.mu.Lock()
	_, ok := e.buffers[path]
	e.mu.Unlock()
	if !ok {
		return nil, fmt.Errorf("buffer %q is not open", path)
	}
	params := &protocol.CodeLensParams{
		TextDocument: e.TextDocumentIdentifier(path),
	}
	lens, err := e.Server.CodeLens(ctx, params)
	if err != nil {
		return nil, err
	}
	return lens, nil
}

// Completion executes a completion request on the server.
func (e *Editor) Completion(ctx context.Context, loc protocol.Location) (*protocol.CompletionList, error) {
	if e.Server == nil {
		return nil, nil
	}
	path := e.sandbox.Workdir.URIToPath(loc.URI)
	e.mu.Lock()
	_, ok := e.buffers[path]
	e.mu.Unlock()
	if !ok {
		return nil, fmt.Errorf("buffer %q is not open", path)
	}
	params := &protocol.CompletionParams{
		TextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),
	}
	completions, err := e.Server.Completion(ctx, params)
	if err != nil {
		return nil, err
	}
	return completions, nil
}

// AcceptCompletion accepts a completion for the given item at the given
// position.
func (e *Editor) AcceptCompletion(ctx context.Context, loc protocol.Location, item protocol.CompletionItem) error {
	if e.Server == nil {
		return nil
	}
	e.mu.Lock()
	defer e.mu.Unlock()
	path := e.sandbox.Workdir.URIToPath(loc.URI)
	_, ok := e.buffers[path]
	if !ok {
		return fmt.Errorf("buffer %q is not open", path)
	}
	return e.editBufferLocked(ctx, path, append([]protocol.TextEdit{
		*item.TextEdit,
	}, item.AdditionalTextEdits...))
}

// Symbols executes a workspace/symbols request on the server.
func (e *Editor) Symbols(ctx context.Context, sym string) ([]protocol.SymbolInformation, error) {
	if e.Server == nil {
		return nil, nil
	}
	params := &protocol.WorkspaceSymbolParams{Query: sym}
	ans, err := e.Server.Symbol(ctx, params)
	return ans, err
}

// CodeLens executes a codelens request on the server.
func (e *Editor) InlayHint(ctx context.Context, path string) ([]protocol.InlayHint, error) {
	if e.Server == nil {
		return nil, nil
	}
	e.mu.Lock()
	_, ok := e.buffers[path]
	e.mu.Unlock()
	if !ok {
		return nil, fmt.Errorf("buffer %q is not open", path)
	}
	params := &protocol.InlayHintParams{
		TextDocument: e.TextDocumentIdentifier(path),
	}
	hints, err := e.Server.InlayHint(ctx, params)
	if err != nil {
		return nil, err
	}
	return hints, nil
}

// References returns references to the object at loc, as returned by
// the connected LSP server. If no server is connected, it returns (nil, nil).
func (e *Editor) References(ctx context.Context, loc protocol.Location) ([]protocol.Location, error) {
	if e.Server == nil {
		return nil, nil
	}
	path := e.sandbox.Workdir.URIToPath(loc.URI)
	e.mu.Lock()
	_, ok := e.buffers[path]
	e.mu.Unlock()
	if !ok {
		return nil, fmt.Errorf("buffer %q is not open", path)
	}
	params := &protocol.ReferenceParams{
		TextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),
		Context: protocol.ReferenceContext{
			IncludeDeclaration: true,
		},
	}
	locations, err := e.Server.References(ctx, params)
	if err != nil {
		return nil, err
	}
	return locations, nil
}

// Rename performs a rename of the object at loc to newName, using the
// connected LSP server. If no server is connected, it returns nil.
func (e *Editor) Rename(ctx context.Context, loc protocol.Location, newName string) error {
	if e.Server == nil {
		return nil
	}
	path := e.sandbox.Workdir.URIToPath(loc.URI)

	// Verify that PrepareRename succeeds.
	prepareParams := &protocol.PrepareRenameParams{}
	prepareParams.TextDocument = e.TextDocumentIdentifier(path)
	prepareParams.Position = loc.Range.Start
	if _, err := e.Server.PrepareRename(ctx, prepareParams); err != nil {
		return fmt.Errorf("preparing rename: %v", err)
	}

	params := &protocol.RenameParams{
		TextDocument: e.TextDocumentIdentifier(path),
		Position:     loc.Range.Start,
		NewName:      newName,
	}
	wsEdits, err := e.Server.Rename(ctx, params)
	if err != nil {
		return err
	}
	for _, change := range wsEdits.DocumentChanges {
		if err := e.applyDocumentChange(ctx, change); err != nil {
			return err
		}
	}
	return nil
}

// Implementations returns implementations for the object at loc, as
// returned by the connected LSP server. If no server is connected, it returns
// (nil, nil).
func (e *Editor) Implementations(ctx context.Context, loc protocol.Location) ([]protocol.Location, error) {
	if e.Server == nil {
		return nil, nil
	}
	path := e.sandbox.Workdir.URIToPath(loc.URI)
	e.mu.Lock()
	_, ok := e.buffers[path]
	e.mu.Unlock()
	if !ok {
		return nil, fmt.Errorf("buffer %q is not open", path)
	}
	params := &protocol.ImplementationParams{
		TextDocumentPositionParams: protocol.LocationTextDocumentPositionParams(loc),
	}
	return e.Server.Implementation(ctx, params)
}

func (e *Editor) RenameFile(ctx context.Context, oldPath, newPath string) error {
	closed, opened, err := e.renameBuffers(ctx, oldPath, newPath)
	if err != nil {
		return err
	}

	for _, c := range closed {
		if err := e.sendDidClose(ctx, c); err != nil {
			return err
		}
	}
	for _, o := range opened {
		if err := e.sendDidOpen(ctx, o); err != nil {
			return err
		}
	}

	// Finally, perform the renaming on disk.
	if err := e.sandbox.Workdir.RenameFile(ctx, oldPath, newPath); err != nil {
		return fmt.Errorf("renaming sandbox file: %w", err)
	}
	return nil
}

// renameBuffers renames in-memory buffers affected by the renaming of
// oldPath->newPath, returning the resulting text documents that must be closed
// and opened over the LSP.
func (e *Editor) renameBuffers(ctx context.Context, oldPath, newPath string) (closed []protocol.TextDocumentIdentifier, opened []protocol.TextDocumentItem, _ error) {
	e.mu.Lock()
	defer e.mu.Unlock()

	// In case either oldPath or newPath is absolute, convert to absolute paths
	// before checking for containment.
	oldAbs := e.sandbox.Workdir.AbsPath(oldPath)
	newAbs := e.sandbox.Workdir.AbsPath(newPath)

	// Collect buffers that are affected by the given file or directory renaming.
	buffersToRename := make(map[string]string) // old path -> new path

	for path := range e.buffers {
		abs := e.sandbox.Workdir.AbsPath(path)
		if oldAbs == abs || source.InDir(oldAbs, abs) {
			rel, err := filepath.Rel(oldAbs, abs)
			if err != nil {
				return nil, nil, fmt.Errorf("filepath.Rel(%q, %q): %v", oldAbs, abs, err)
			}
			nabs := filepath.Join(newAbs, rel)
			newPath := e.sandbox.Workdir.RelPath(nabs)
			buffersToRename[path] = newPath
		}
	}

	// Update buffers, and build protocol changes.
	for old, new := range buffersToRename {
		buf := e.buffers[old]
		delete(e.buffers, old)
		buf.version = 1
		buf.path = new
		e.buffers[new] = buf

		closed = append(closed, e.TextDocumentIdentifier(old))
		opened = append(opened, e.textDocumentItem(buf))
	}

	return closed, opened, nil
}

func (e *Editor) applyDocumentChange(ctx context.Context, change protocol.DocumentChanges) error {
	if change.RenameFile != nil {
		oldPath := e.sandbox.Workdir.URIToPath(change.RenameFile.OldURI)
		newPath := e.sandbox.Workdir.URIToPath(change.RenameFile.NewURI)

		return e.RenameFile(ctx, oldPath, newPath)
	}
	if change.TextDocumentEdit != nil {
		return e.applyTextDocumentEdit(ctx, *change.TextDocumentEdit)
	}
	panic("Internal error: one of RenameFile or TextDocumentEdit must be set")
}

func (e *Editor) applyTextDocumentEdit(ctx context.Context, change protocol.TextDocumentEdit) error {
	path := e.sandbox.Workdir.URIToPath(change.TextDocument.URI)
	if ver := int32(e.BufferVersion(path)); ver != change.TextDocument.Version {
		return fmt.Errorf("buffer versions for %q do not match: have %d, editing %d", path, ver, change.TextDocument.Version)
	}
	if !e.HasBuffer(path) {
		err := e.OpenFile(ctx, path)
		if os.IsNotExist(err) {
			// TODO: it's unclear if this is correct. Here we create the buffer (with
			// version 1), then apply edits. Perhaps we should apply the edits before
			// sending the didOpen notification.
			e.CreateBuffer(ctx, path, "")
			err = nil
		}
		if err != nil {
			return err
		}
	}
	return e.EditBuffer(ctx, path, change.Edits)
}

// Config returns the current editor configuration.
func (e *Editor) Config() EditorConfig {
	e.mu.Lock()
	defer e.mu.Unlock()
	return e.config
}

// ChangeConfiguration sets the new editor configuration, and if applicable
// sends a didChangeConfiguration notification.
//
// An error is returned if the change notification failed to send.
func (e *Editor) ChangeConfiguration(ctx context.Context, newConfig EditorConfig) error {
	e.mu.Lock()
	e.config = newConfig
	e.mu.Unlock() // don't hold e.mu during server calls
	if e.Server != nil {
		var params protocol.DidChangeConfigurationParams // empty: gopls ignores the Settings field
		if err := e.Server.DidChangeConfiguration(ctx, &params); err != nil {
			return err
		}
	}
	return nil
}

// ChangeWorkspaceFolders sets the new workspace folders, and sends a
// didChangeWorkspaceFolders notification to the server.
//
// The given folders must all be unique.
func (e *Editor) ChangeWorkspaceFolders(ctx context.Context, folders []string) error {
	// capture existing folders so that we can compute the change.
	e.mu.Lock()
	oldFolders := e.makeWorkspaceFoldersLocked()
	e.config.WorkspaceFolders = folders
	newFolders := e.makeWorkspaceFoldersLocked()
	e.mu.Unlock()

	if e.Server == nil {
		return nil
	}

	var params protocol.DidChangeWorkspaceFoldersParams

	// Keep track of old workspace folders that must be removed.
	toRemove := make(map[protocol.URI]protocol.WorkspaceFolder)
	for _, folder := range oldFolders {
		toRemove[folder.URI] = folder
	}

	// Sanity check: if we see a folder twice the algorithm below doesn't work,
	// so track seen folders to ensure that we panic in that case.
	seen := make(map[protocol.URI]protocol.WorkspaceFolder)
	for _, folder := range newFolders {
		if _, ok := seen[folder.URI]; ok {
			panic(fmt.Sprintf("folder %s seen twice", folder.URI))
		}

		// If this folder already exists, we don't want to remove it.
		// Otherwise, we need to add it.
		if _, ok := toRemove[folder.URI]; ok {
			delete(toRemove, folder.URI)
		} else {
			params.Event.Added = append(params.Event.Added, folder)
		}
	}

	for _, v := range toRemove {
		params.Event.Removed = append(params.Event.Removed, v)
	}

	return e.Server.DidChangeWorkspaceFolders(ctx, &params)
}

// CodeAction executes a codeAction request on the server.
// If loc.Range is zero, the whole file is implied.
func (e *Editor) CodeAction(ctx context.Context, loc protocol.Location, diagnostics []protocol.Diagnostic) ([]protocol.CodeAction, error) {
	if e.Server == nil {
		return nil, nil
	}
	path := e.sandbox.Workdir.URIToPath(loc.URI)
	e.mu.Lock()
	_, ok := e.buffers[path]
	e.mu.Unlock()
	if !ok {
		return nil, fmt.Errorf("buffer %q is not open", path)
	}
	params := &protocol.CodeActionParams{
		TextDocument: e.TextDocumentIdentifier(path),
		Context: protocol.CodeActionContext{
			Diagnostics: diagnostics,
		},
		Range: loc.Range, // may be zero
	}
	lens, err := e.Server.CodeAction(ctx, params)
	if err != nil {
		return nil, err
	}
	return lens, nil
}

// Hover triggers a hover at the given position in an open buffer.
func (e *Editor) Hover(ctx context.Context, loc protocol.Location) (*protocol.MarkupContent, protocol.Location, error) {
	if err := e.checkBufferLocation(loc); err != nil {
		return nil, protocol.Location{}, err
	}
	params := &protocol.HoverParams{}
	params.TextDocument.URI = loc.URI
	params.Position = loc.Range.Start

	resp, err := e.Server.Hover(ctx, params)
	if err != nil {
		return nil, protocol.Location{}, fmt.Errorf("hover: %w", err)
	}
	if resp == nil {
		return nil, protocol.Location{}, nil
	}
	return &resp.Contents, protocol.Location{URI: loc.URI, Range: resp.Range}, nil
}

func (e *Editor) DocumentLink(ctx context.Context, path string) ([]protocol.DocumentLink, error) {
	if e.Server == nil {
		return nil, nil
	}
	params := &protocol.DocumentLinkParams{}
	params.TextDocument.URI = e.sandbox.Workdir.URI(path)
	return e.Server.DocumentLink(ctx, params)
}

func (e *Editor) DocumentHighlight(ctx context.Context, loc protocol.Location) ([]protocol.DocumentHighlight, error) {
	if e.Server == nil {
		return nil, nil
	}
	if err := e.checkBufferLocation(loc); err != nil {
		return nil, err
	}
	params := &protocol.DocumentHighlightParams{}
	params.TextDocument.URI = loc.URI
	params.Position = loc.Range.Start

	return e.Server.DocumentHighlight(ctx, params)
}
