.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools / gopls@v0.6.9 / internal / regtest / expectation.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools/gopls@v0.6.9/internal/regtest/expectation.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools/gopls@v0.6.9/internal/regtest/expectation.go
new file mode 100644 (file)
index 0000000..02e00dd
--- /dev/null
@@ -0,0 +1,596 @@
+// 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 regtest
+
+import (
+       "fmt"
+       "regexp"
+       "strings"
+
+       "golang.org/x/tools/internal/lsp"
+       "golang.org/x/tools/internal/lsp/fake"
+       "golang.org/x/tools/internal/lsp/protocol"
+       "golang.org/x/tools/internal/testenv"
+)
+
+// An Expectation asserts that the state of the editor at a point in time
+// matches an expected condition. This is used for signaling in tests when
+// certain conditions in the editor are met.
+type Expectation interface {
+       // Check determines whether the state of the editor satisfies the
+       // expectation, returning the results that met the condition.
+       Check(State) Verdict
+       // Description is a human-readable description of the expectation.
+       Description() string
+}
+
+var (
+       // InitialWorkspaceLoad is an expectation that the workspace initial load has
+       // completed. It is verified via workdone reporting.
+       InitialWorkspaceLoad = CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromInitialWorkspaceLoad), 1)
+)
+
+// A Verdict is the result of checking an expectation against the current
+// editor state.
+type Verdict int
+
+// Order matters for the following constants: verdicts are sorted in order of
+// decisiveness.
+const (
+       // Met indicates that an expectation is satisfied by the current state.
+       Met Verdict = iota
+       // Unmet indicates that an expectation is not currently met, but could be met
+       // in the future.
+       Unmet
+       // Unmeetable indicates that an expectation cannot be satisfied in the
+       // future.
+       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)
+}
+
+// SimpleExpectation holds an arbitrary check func, and implements the Expectation interface.
+type SimpleExpectation struct {
+       check       func(State) Verdict
+       description string
+}
+
+// Check invokes e.check.
+func (e SimpleExpectation) Check(s State) Verdict {
+       return e.check(s)
+}
+
+// Description returns e.descriptin.
+func (e SimpleExpectation) Description() string {
+       return e.description
+}
+
+// OnceMet returns an Expectation that, once the precondition is met, asserts
+// that mustMeet is met.
+func OnceMet(precondition Expectation, mustMeet Expectation) *SimpleExpectation {
+       check := func(s State) Verdict {
+               switch pre := precondition.Check(s); pre {
+               case Unmeetable:
+                       return Unmeetable
+               case Met:
+                       verdict := mustMeet.Check(s)
+                       if verdict != Met {
+                               return Unmeetable
+                       }
+                       return Met
+               default:
+                       return Unmet
+               }
+       }
+       return &SimpleExpectation{
+               check:       check,
+               description: fmt.Sprintf("once %q is met, must have %q", precondition.Description(), mustMeet.Description()),
+       }
+}
+
+// ReadDiagnostics is an 'expectation' that is used to read diagnostics
+// atomically. It is intended to be used with 'OnceMet'.
+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),
+       }
+}
+
+// NoOutstandingWork asserts that there is no work initiated using the LSP
+// $/progress API that has not completed.
+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",
+       }
+}
+
+// NoShowMessage asserts that the editor has not received a ShowMessage.
+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",
+       }
+}
+
+// ShownMessage asserts that the editor has received a ShownMessage with the
+// given title.
+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",
+       }
+}
+
+// ShowMessageRequest asserts that the editor has received a ShowMessageRequest
+// with an action item that has the given title.
+func ShowMessageRequest(title string) SimpleExpectation {
+       check := func(s State) Verdict {
+               if len(s.showMessageRequest) == 0 {
+                       return Unmet
+               }
+               // Only check the most recent one.
+               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",
+       }
+}
+
+// DoneWithOpen expects all didOpen notifications currently sent by the editor
+// to be completely processed.
+func (e *Env) DoneWithOpen() Expectation {
+       opens := e.Editor.Stats().DidOpen
+       return CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidOpen), opens)
+}
+
+// DoneWithChange expects all didChange notifications currently sent by the
+// editor to be completely processed.
+func (e *Env) DoneWithChange() Expectation {
+       changes := e.Editor.Stats().DidChange
+       return CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChange), changes)
+}
+
+// DoneWithSave expects all didSave notifications currently sent by the editor
+// to be completely processed.
+func (e *Env) DoneWithSave() Expectation {
+       saves := e.Editor.Stats().DidSave
+       return CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidSave), saves)
+}
+
+// DoneWithChangeWatchedFiles expects all didChangeWatchedFiles notifications
+// currently sent by the editor to be completely processed.
+func (e *Env) DoneWithChangeWatchedFiles() Expectation {
+       changes := e.Editor.Stats().DidChangeWatchedFiles
+       return CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChangeWatchedFiles), changes)
+}
+
+// DoneWithClose expects all didClose notifications currently sent by the
+// editor to be completely processed.
+func (e *Env) DoneWithClose() Expectation {
+       changes := e.Editor.Stats().DidClose
+       return CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidClose), changes)
+}
+
+// CompletedWork expects a work item to have been completed >= atLeast times.
+//
+// Since the Progress API doesn't include any hidden metadata, we must use the
+// progress notification title to identify the work we expect to be completed.
+func CompletedWork(title string, atLeast uint64) SimpleExpectation {
+       check := func(s State) Verdict {
+               if s.completedWork[title] >= atLeast {
+                       return Met
+               }
+               return Unmet
+       }
+       return SimpleExpectation{
+               check:       check,
+               description: fmt.Sprintf("completed work %q at least %d time(s)", title, atLeast),
+       }
+}
+
+// OutstandingWork expects a work item to be outstanding. The given title must
+// be an exact match, whereas the given msg must only be contained in the work
+// item's message.
+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),
+       }
+}
+
+// LogExpectation is an expectation on the log messages received by the editor
+// from gopls.
+type LogExpectation struct {
+       check       func([]*protocol.LogMessageParams) Verdict
+       description string
+}
+
+// Check implements the Expectation interface.
+func (e LogExpectation) Check(s State) Verdict {
+       return e.check(s.logs)
+}
+
+// Description implements the Expectation interface.
+func (e LogExpectation) Description() string {
+       return e.description
+}
+
+// NoErrorLogs asserts that the client has not received any log messages of
+// error severity.
+func NoErrorLogs() LogExpectation {
+       return NoLogMatching(protocol.Error, "")
+}
+
+// LogMatching asserts that the client has received a log message
+// of type typ matching the regexp re.
+func LogMatching(typ protocol.MessageType, re string, count int) 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 {
+                       return Met
+               }
+               return Unmet
+       }
+       return LogExpectation{
+               check:       check,
+               description: fmt.Sprintf("log message matching %q", re),
+       }
+}
+
+// NoLogMatching asserts that the client has not received a log message
+// of type typ matching the regexp re. If re is an empty string, any log
+// message is considered a match.
+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),
+       }
+}
+
+// RegistrationExpectation is an expectation on the capability registrations
+// received by the editor from gopls.
+type RegistrationExpectation struct {
+       check       func([]*protocol.RegistrationParams) Verdict
+       description string
+}
+
+// Check implements the Expectation interface.
+func (e RegistrationExpectation) Check(s State) Verdict {
+       return e.check(s.registrations)
+}
+
+// Description implements the Expectation interface.
+func (e RegistrationExpectation) Description() string {
+       return e.description
+}
+
+// RegistrationMatching asserts that the client has received a capability
+// registration matching the given regexp.
+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),
+       }
+}
+
+// UnregistrationExpectation is an expectation on the capability
+// unregistrations received by the editor from gopls.
+type UnregistrationExpectation struct {
+       check       func([]*protocol.UnregistrationParams) Verdict
+       description string
+}
+
+// Check implements the Expectation interface.
+func (e UnregistrationExpectation) Check(s State) Verdict {
+       return e.check(s.unregistrations)
+}
+
+// Description implements the Expectation interface.
+func (e UnregistrationExpectation) Description() string {
+       return e.description
+}
+
+// UnregistrationMatching asserts that the client has received an
+// unregistration whose ID matches the given regexp.
+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),
+       }
+}
+
+// A DiagnosticExpectation is a condition that must be met by the current set
+// of diagnostics for a file.
+type DiagnosticExpectation struct {
+       // optionally, the position of the diagnostic and the regex used to calculate it.
+       pos *fake.Pos
+       re  string
+
+       // optionally, the message that the diagnostic should contain.
+       message string
+
+       // whether the expectation is that the diagnostic is present, or absent.
+       present bool
+
+       // path is the scratch workdir-relative path to the file being asserted on.
+       path string
+}
+
+// Check implements the Expectation interface.
+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
+}
+
+// Description implements the Expectation interface.
+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
+}
+
+// EmptyDiagnostics asserts that empty diagnostics are sent for the
+// workspace-relative path name.
+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: "empty diagnostics",
+       }
+}
+
+// NoDiagnostics asserts that no diagnostics are sent for the
+// workspace-relative path name. It should be used primarily in conjunction
+// with a OnceMet, as it has to check that all outstanding diagnostics have
+// already been delivered.
+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",
+       }
+}
+
+// AnyDiagnosticAtCurrentVersion asserts that there is a diagnostic report for
+// the current edited version of the buffer corresponding to the given
+// workdir-relative pathname.
+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),
+       }
+}
+
+// DiagnosticAtRegexp expects that there is a 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.
+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}
+}
+
+// DiagnosticAtRegexpWithMessage is like DiagnosticAtRegexp, but it also
+// checks for the content of the diagnostic message,
+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}
+}
+
+// DiagnosticAt asserts that there is a diagnostic entry at the position
+// specified by line and col, for the workdir-relative path name.
+func DiagnosticAt(name string, line, col int) DiagnosticExpectation {
+       return DiagnosticExpectation{path: name, pos: &fake.Pos{Line: line, Column: col}, present: true}
+}
+
+// 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.
+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}
+}
+
+// NoDiagnosticAt asserts that there is no diagnostic entry at the position
+// specified by line and col, for the workdir-relative path name.
+// This should only be used in combination with OnceMet for a given condition,
+// otherwise it may always succeed.
+func NoDiagnosticAt(name string, line, col int) DiagnosticExpectation {
+       return DiagnosticExpectation{path: name, pos: &fake.Pos{Line: line, Column: col}, present: false}
+}
+
+// NoDiagnosticWithMessage asserts that there is no diagnostic entry with the
+// given message.
+//
+// This should only be used in combination with OnceMet for a given condition,
+// otherwise it may always succeed.
+func NoDiagnosticWithMessage(name, msg string) DiagnosticExpectation {
+       return DiagnosticExpectation{path: name, message: msg, present: false}
+}
+
+// GoSum asserts that a "go.sum is out of sync" diagnostic for the given module
+// (as formatted in a go.mod file, e.g. "example.com v1.0.0") is present.
+func (e *Env) GoSumDiagnostic(name, module string) Expectation {
+       e.T.Helper()
+       // In 1.16, go.sum diagnostics should appear on the relevant module. Earlier
+       // errors have no information and appear on the module declaration.
+       if testenv.Go1Point() >= 16 {
+               return e.DiagnosticAtRegexpWithMessage(name, module, "go.sum is out of sync")
+       } else {
+               return e.DiagnosticAtRegexpWithMessage(name, `module`, "go.sum is out of sync")
+       }
+}