func (e *Env) NoDiagnosticAtRegexp(name, re string) DiagnosticExpectation {
	e.T.Helper()
	pos := e.RegexpSearch(name, re)
	return DiagnosticExpectation{path: name, pos: &pos, re: re, present: false}
}
NoDiagnosticAtRegexp expects that there is no diagnostic entry at the start
position matching the regexp search string re in the buffer specified by
name. Note that this currently ignores the end position.
This should only be used in combination with OnceMet for a given condition,
otherwise it may always succeed.
package regtest
import (
	"fmt"
	"regexp"
	"strings"
	"github.com/govim/govim/cmd/govim/internal/golang_org_x_tools/lsp"
	"github.com/govim/govim/cmd/govim/internal/golang_org_x_tools/lsp/fake"
	"github.com/govim/govim/cmd/govim/internal/golang_org_x_tools/lsp/protocol"
	"github.com/govim/govim/cmd/govim/internal/golang_org_x_tools/testenv"
)
type Expectation interface {
	Check(State) Verdict
	Description() string
}
var (
	InitialWorkspaceLoad = CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromInitialWorkspaceLoad), 1, false)
)
type Verdict int
const (
	Met Verdict = iota
	Unmet
	Unmeetable
)
func (v Verdict) String() string {
	switch v {
	case Met:
		return "Met"
	case Unmet:
		return "Unmet"
	case Unmeetable:
		return "Unmeetable"
	}
	return fmt.Sprintf("unrecognized verdict %d", v)
}
type SimpleExpectation struct {
	check       func(State) Verdict
	description string
}
func (e SimpleExpectation) Check(s State) Verdict {
	return e.check(s)
}
func (e SimpleExpectation) Description() string {
	return e.description
}
func OnceMet(precondition Expectation, mustMeets ...Expectation) *SimpleExpectation {
	check := func(s State) Verdict {
		switch pre := precondition.Check(s); pre {
		case Unmeetable:
			return Unmeetable
		case Met:
			for _, mustMeet := range mustMeets {
				verdict := mustMeet.Check(s)
				if verdict != Met {
					return Unmeetable
				}
			}
			return Met
		default:
			return Unmet
		}
	}
	var descriptions []string
	for _, mustMeet := range mustMeets {
		descriptions = append(descriptions, mustMeet.Description())
	}
	return &SimpleExpectation{
		check:       check,
		description: fmt.Sprintf("once %q is met, must have %q", precondition.Description(), strings.Join(descriptions, "\n")),
	}
}
func ReadDiagnostics(fileName string, into *protocol.PublishDiagnosticsParams) *SimpleExpectation {
	check := func(s State) Verdict {
		diags, ok := s.diagnostics[fileName]
		if !ok {
			return Unmeetable
		}
		*into = *diags
		return Met
	}
	return &SimpleExpectation{
		check:       check,
		description: fmt.Sprintf("read diagnostics for %q", fileName),
	}
}
func NoOutstandingWork() SimpleExpectation {
	check := func(s State) Verdict {
		if len(s.outstandingWork) == 0 {
			return Met
		}
		return Unmet
	}
	return SimpleExpectation{
		check:       check,
		description: "no outstanding work",
	}
}
func NoShowMessage() SimpleExpectation {
	check := func(s State) Verdict {
		if len(s.showMessage) == 0 {
			return Met
		}
		return Unmeetable
	}
	return SimpleExpectation{
		check:       check,
		description: "no ShowMessage received",
	}
}
func ShownMessage(title string) SimpleExpectation {
	check := func(s State) Verdict {
		for _, m := range s.showMessage {
			if strings.Contains(m.Message, title) {
				return Met
			}
		}
		return Unmet
	}
	return SimpleExpectation{
		check:       check,
		description: "received ShowMessage",
	}
}
func ShowMessageRequest(title string) SimpleExpectation {
	check := func(s State) Verdict {
		if len(s.showMessageRequest) == 0 {
			return Unmet
		}
		m := s.showMessageRequest[len(s.showMessageRequest)-1]
		if len(m.Actions) == 0 || len(m.Actions) > 1 {
			return Unmet
		}
		if m.Actions[0].Title == title {
			return Met
		}
		return Unmet
	}
	return SimpleExpectation{
		check:       check,
		description: "received ShowMessageRequest",
	}
}
func (e *Env) DoneWithOpen() Expectation {
	opens := e.Editor.Stats().DidOpen
	return CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidOpen), opens, true)
}
func StartedChange(i uint64) Expectation {
	return StartedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChange), i)
}
func (e *Env) DoneWithChange() Expectation {
	changes := e.Editor.Stats().DidChange
	return CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChange), changes, true)
}
func (e *Env) DoneWithSave() Expectation {
	saves := e.Editor.Stats().DidSave
	return CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidSave), saves, true)
}
func (e *Env) DoneWithChangeWatchedFiles() Expectation {
	changes := e.Editor.Stats().DidChangeWatchedFiles
	return CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChangeWatchedFiles), changes, true)
}
func (e *Env) DoneWithClose() Expectation {
	changes := e.Editor.Stats().DidClose
	return CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidClose), changes, true)
}
func StartedWork(title string, atLeast uint64) SimpleExpectation {
	check := func(s State) Verdict {
		if s.startedWork[title] >= atLeast {
			return Met
		}
		return Unmet
	}
	return SimpleExpectation{
		check:       check,
		description: fmt.Sprintf("started work %q at least %d time(s)", title, atLeast),
	}
}
func CompletedWork(title string, count uint64, atLeast bool) SimpleExpectation {
	check := func(s State) Verdict {
		if s.completedWork[title] == count || atLeast && s.completedWork[title] > count {
			return Met
		}
		return Unmet
	}
	desc := fmt.Sprintf("completed work %q %v times", title, count)
	if atLeast {
		desc = fmt.Sprintf("completed work %q at least %d time(s)", title, count)
	}
	return SimpleExpectation{
		check:       check,
		description: desc,
	}
}
func OutstandingWork(title, msg string) SimpleExpectation {
	check := func(s State) Verdict {
		for _, work := range s.outstandingWork {
			if work.title == title && strings.Contains(work.msg, msg) {
				return Met
			}
		}
		return Unmet
	}
	return SimpleExpectation{
		check:       check,
		description: fmt.Sprintf("outstanding work: %s", title),
	}
}
type LogExpectation struct {
	check       func([]*protocol.LogMessageParams) Verdict
	description string
}
func (e LogExpectation) Check(s State) Verdict {
	return e.check(s.logs)
}
func (e LogExpectation) Description() string {
	return e.description
}
func NoErrorLogs() LogExpectation {
	return NoLogMatching(protocol.Error, "")
}
func LogMatching(typ protocol.MessageType, re string, count int, atLeast bool) LogExpectation {
	rec, err := regexp.Compile(re)
	if err != nil {
		panic(err)
	}
	check := func(msgs []*protocol.LogMessageParams) Verdict {
		var found int
		for _, msg := range msgs {
			if msg.Type == typ && rec.Match([]byte(msg.Message)) {
				found++
			}
		}
		if found == count || (found >= count && atLeast) {
			return Met
		}
		return Unmet
	}
	desc := fmt.Sprintf("log message matching %q expected %v times", re, count)
	if atLeast {
		desc = fmt.Sprintf("log message matching %q expected at least %v times", re, count)
	}
	return LogExpectation{
		check:       check,
		description: desc,
	}
}
func NoLogMatching(typ protocol.MessageType, re string) LogExpectation {
	var r *regexp.Regexp
	if re != "" {
		var err error
		r, err = regexp.Compile(re)
		if err != nil {
			panic(err)
		}
	}
	check := func(msgs []*protocol.LogMessageParams) Verdict {
		for _, msg := range msgs {
			if msg.Type != typ {
				continue
			}
			if r == nil || r.Match([]byte(msg.Message)) {
				return Unmeetable
			}
		}
		return Met
	}
	return LogExpectation{
		check:       check,
		description: fmt.Sprintf("no log message matching %q", re),
	}
}
type RegistrationExpectation struct {
	check       func([]*protocol.RegistrationParams) Verdict
	description string
}
func (e RegistrationExpectation) Check(s State) Verdict {
	return e.check(s.registrations)
}
func (e RegistrationExpectation) Description() string {
	return e.description
}
func RegistrationMatching(re string) RegistrationExpectation {
	rec, err := regexp.Compile(re)
	if err != nil {
		panic(err)
	}
	check := func(params []*protocol.RegistrationParams) Verdict {
		for _, p := range params {
			for _, r := range p.Registrations {
				if rec.Match([]byte(r.Method)) {
					return Met
				}
			}
		}
		return Unmet
	}
	return RegistrationExpectation{
		check:       check,
		description: fmt.Sprintf("registration matching %q", re),
	}
}
type UnregistrationExpectation struct {
	check       func([]*protocol.UnregistrationParams) Verdict
	description string
}
func (e UnregistrationExpectation) Check(s State) Verdict {
	return e.check(s.unregistrations)
}
func (e UnregistrationExpectation) Description() string {
	return e.description
}
func UnregistrationMatching(re string) UnregistrationExpectation {
	rec, err := regexp.Compile(re)
	if err != nil {
		panic(err)
	}
	check := func(params []*protocol.UnregistrationParams) Verdict {
		for _, p := range params {
			for _, r := range p.Unregisterations {
				if rec.Match([]byte(r.Method)) {
					return Met
				}
			}
		}
		return Unmet
	}
	return UnregistrationExpectation{
		check:       check,
		description: fmt.Sprintf("unregistration matching %q", re),
	}
}
type DiagnosticExpectation struct {
	pos *fake.Pos
	re  string
	message string
	present bool
	path string
}
func (e DiagnosticExpectation) Check(s State) Verdict {
	diags, ok := s.diagnostics[e.path]
	if !ok {
		if !e.present {
			return Met
		}
		return Unmet
	}
	found := false
	for _, d := range diags.Diagnostics {
		if e.pos != nil {
			if d.Range.Start.Line != uint32(e.pos.Line) || d.Range.Start.Character != uint32(e.pos.Column) {
				continue
			}
		}
		if e.message != "" {
			if !strings.Contains(d.Message, e.message) {
				continue
			}
		}
		found = true
		break
	}
	if found == e.present {
		return Met
	}
	return Unmet
}
func (e DiagnosticExpectation) Description() string {
	desc := e.path + ":"
	if !e.present {
		desc += " no"
	}
	desc += " diagnostic"
	if e.pos != nil {
		desc += fmt.Sprintf(" at {line:%d, column:%d}", e.pos.Line, e.pos.Column)
		if e.re != "" {
			desc += fmt.Sprintf(" (location of %q)", e.re)
		}
	}
	if e.message != "" {
		desc += fmt.Sprintf(" with message %q", e.message)
	}
	return desc
}
func EmptyDiagnostics(name string) Expectation {
	check := func(s State) Verdict {
		if diags := s.diagnostics[name]; diags != nil && len(diags.Diagnostics) == 0 {
			return Met
		}
		return Unmet
	}
	return SimpleExpectation{
		check:       check,
		description: fmt.Sprintf("empty diagnostics for %q", name),
	}
}
func EmptyOrNoDiagnostics(name string) Expectation {
	check := func(s State) Verdict {
		if diags := s.diagnostics[name]; diags == nil || len(diags.Diagnostics) == 0 {
			return Met
		}
		return Unmet
	}
	return SimpleExpectation{
		check:       check,
		description: fmt.Sprintf("empty or no diagnostics for %q", name),
	}
}
func NoDiagnostics(name string) Expectation {
	check := func(s State) Verdict {
		if _, ok := s.diagnostics[name]; !ok {
			return Met
		}
		return Unmet
	}
	return SimpleExpectation{
		check:       check,
		description: "no diagnostics",
	}
}
func (e *Env) AnyDiagnosticAtCurrentVersion(name string) Expectation {
	version := e.Editor.BufferVersion(name)
	check := func(s State) Verdict {
		diags, ok := s.diagnostics[name]
		if ok && diags.Version == int32(version) {
			return Met
		}
		return Unmet
	}
	return SimpleExpectation{
		check:       check,
		description: fmt.Sprintf("any diagnostics at version %d", version),
	}
}
func (e *Env) DiagnosticAtRegexp(name, re string) DiagnosticExpectation {
	e.T.Helper()
	pos := e.RegexpSearch(name, re)
	return DiagnosticExpectation{path: name, pos: &pos, re: re, present: true}
}
func (e *Env) DiagnosticAtRegexpWithMessage(name, re, msg string) DiagnosticExpectation {
	e.T.Helper()
	pos := e.RegexpSearch(name, re)
	return DiagnosticExpectation{path: name, pos: &pos, re: re, present: true, message: msg}
}
func DiagnosticAt(name string, line, col int) DiagnosticExpectation {
	return DiagnosticExpectation{path: name, pos: &fake.Pos{Line: line, Column: col}, present: true}
}