diff --git a/gopls/internal/lsp/regtest/env.go b/gopls/internal/lsp/regtest/env.go index 73e8ef31cee..ad606587b0a 100644 --- a/gopls/internal/lsp/regtest/env.go +++ b/gopls/internal/lsp/regtest/env.go @@ -297,7 +297,7 @@ func checkExpectations(s State, expectations []Expectation) (Verdict, string) { if v > finalVerdict { finalVerdict = v } - summary.WriteString(fmt.Sprintf("%v: %s\n", v, e.Description())) + summary.WriteString(fmt.Sprintf("%v: %s\n", v, e.Description)) } return finalVerdict, summary.String() } diff --git a/gopls/internal/lsp/regtest/expectation.go b/gopls/internal/lsp/regtest/expectation.go index 1c359252f0e..d0896ff7e2d 100644 --- a/gopls/internal/lsp/regtest/expectation.go +++ b/gopls/internal/lsp/regtest/expectation.go @@ -14,17 +14,6 @@ import ( "golang.org/x/tools/gopls/internal/lsp/protocol" ) -// 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. @@ -60,25 +49,15 @@ func (v Verdict) String() string { 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.description. -func (e SimpleExpectation) Description() string { - return e.description +// Expectation holds an arbitrary check func, and implements the Expectation interface. +type Expectation struct { + Check func(State) Verdict + Description string } // OnceMet returns an Expectation that, once the precondition is met, asserts // that mustMeet is met. -func OnceMet(precondition Expectation, mustMeets ...Expectation) *SimpleExpectation { +func OnceMet(precondition Expectation, mustMeets ...Expectation) Expectation { check := func(s State) Verdict { switch pre := precondition.Check(s); pre { case Unmeetable: @@ -96,23 +75,23 @@ func OnceMet(precondition Expectation, mustMeets ...Expectation) *SimpleExpectat } } description := describeExpectations(mustMeets...) - return &SimpleExpectation{ - check: check, - description: fmt.Sprintf("once %q is met, must have:\n%s", precondition.Description(), description), + return Expectation{ + Check: check, + Description: fmt.Sprintf("once %q is met, must have:\n%s", precondition.Description, description), } } func describeExpectations(expectations ...Expectation) string { var descriptions []string for _, e := range expectations { - descriptions = append(descriptions, e.Description()) + descriptions = append(descriptions, e.Description) } return strings.Join(descriptions, "\n") } // AnyOf returns an expectation that is satisfied when any of the given // expectations is met. -func AnyOf(anyOf ...Expectation) *SimpleExpectation { +func AnyOf(anyOf ...Expectation) Expectation { check := func(s State) Verdict { for _, e := range anyOf { verdict := e.Check(s) @@ -123,9 +102,9 @@ func AnyOf(anyOf ...Expectation) *SimpleExpectation { return Unmet } description := describeExpectations(anyOf...) - return &SimpleExpectation{ - check: check, - description: fmt.Sprintf("Any of:\n%s", description), + return Expectation{ + Check: check, + Description: fmt.Sprintf("Any of:\n%s", description), } } @@ -139,7 +118,7 @@ func AnyOf(anyOf ...Expectation) *SimpleExpectation { // why an expectation failed. This should allow us to significantly improve // test output: we won't need to summarize state at all, as the verdict // explanation itself should describe clearly why the expectation not met. -func AllOf(allOf ...Expectation) *SimpleExpectation { +func AllOf(allOf ...Expectation) Expectation { check := func(s State) Verdict { verdict := Met for _, e := range allOf { @@ -150,15 +129,15 @@ func AllOf(allOf ...Expectation) *SimpleExpectation { return verdict } description := describeExpectations(allOf...) - return &SimpleExpectation{ - check: check, - description: fmt.Sprintf("All of:\n%s", description), + return Expectation{ + Check: check, + Description: fmt.Sprintf("All of:\n%s", 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 { +func ReadDiagnostics(fileName string, into *protocol.PublishDiagnosticsParams) Expectation { check := func(s State) Verdict { diags, ok := s.diagnostics[fileName] if !ok { @@ -167,29 +146,29 @@ func ReadDiagnostics(fileName string, into *protocol.PublishDiagnosticsParams) * *into = *diags return Met } - return &SimpleExpectation{ - check: check, - description: fmt.Sprintf("read diagnostics for %q", fileName), + return Expectation{ + 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 { +func NoOutstandingWork() Expectation { check := func(s State) Verdict { if len(s.outstandingWork()) == 0 { return Met } return Unmet } - return SimpleExpectation{ - check: check, - description: "no outstanding work", + return Expectation{ + Check: check, + Description: "no outstanding work", } } // NoShownMessage asserts that the editor has not received a ShowMessage. -func NoShownMessage(subString string) SimpleExpectation { +func NoShownMessage(subString string) Expectation { check := func(s State) Verdict { for _, m := range s.showMessage { if strings.Contains(m.Message, subString) { @@ -198,15 +177,15 @@ func NoShownMessage(subString string) SimpleExpectation { } return Met } - return SimpleExpectation{ - check: check, - description: fmt.Sprintf("no ShowMessage received containing %q", subString), + return Expectation{ + Check: check, + Description: fmt.Sprintf("no ShowMessage received containing %q", subString), } } // ShownMessage asserts that the editor has received a ShowMessageRequest // containing the given substring. -func ShownMessage(containing string) SimpleExpectation { +func ShownMessage(containing string) Expectation { check := func(s State) Verdict { for _, m := range s.showMessage { if strings.Contains(m.Message, containing) { @@ -215,15 +194,15 @@ func ShownMessage(containing string) SimpleExpectation { } return Unmet } - return SimpleExpectation{ - check: check, - description: "received ShowMessage", + return Expectation{ + 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 { +func ShowMessageRequest(title string) Expectation { check := func(s State) Verdict { if len(s.showMessageRequest) == 0 { return Unmet @@ -238,9 +217,9 @@ func ShowMessageRequest(title string) SimpleExpectation { } return Unmet } - return SimpleExpectation{ - check: check, - description: "received ShowMessageRequest", + return Expectation{ + Check: check, + Description: "received ShowMessageRequest", } } @@ -348,16 +327,16 @@ func (e *Env) DoneWithClose() Expectation { // StartedWork expect a work item to have been started >= atLeast times. // // See CompletedWork. -func StartedWork(title string, atLeast uint64) SimpleExpectation { +func StartedWork(title string, atLeast uint64) Expectation { 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), + return Expectation{ + Check: check, + Description: fmt.Sprintf("started work %q at least %d time(s)", title, atLeast), } } @@ -365,7 +344,7 @@ func StartedWork(title string, atLeast uint64) SimpleExpectation { // // 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, count uint64, atLeast bool) SimpleExpectation { +func CompletedWork(title string, count uint64, atLeast bool) Expectation { check := func(s State) Verdict { completed := s.completedWork() if completed[title] == count || atLeast && completed[title] > count { @@ -377,9 +356,9 @@ func CompletedWork(title string, count uint64, atLeast bool) SimpleExpectation { if atLeast { desc = fmt.Sprintf("completed work %q at least %d time(s)", title, count) } - return SimpleExpectation{ - check: check, - description: desc, + return Expectation{ + Check: check, + Description: desc, } } @@ -396,7 +375,7 @@ type WorkStatus struct { // // If the token is not a progress token that the client has seen, this // expectation is Unmeetable. -func CompletedProgress(token protocol.ProgressToken, into *WorkStatus) SimpleExpectation { +func CompletedProgress(token protocol.ProgressToken, into *WorkStatus) Expectation { check := func(s State) Verdict { work, ok := s.work[token] if !ok { @@ -412,16 +391,16 @@ func CompletedProgress(token protocol.ProgressToken, into *WorkStatus) SimpleExp return Unmet } desc := fmt.Sprintf("completed work for token %v", token) - return SimpleExpectation{ - check: check, - description: desc, + return Expectation{ + Check: check, + Description: desc, } } // 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 { +func OutstandingWork(title, msg string) Expectation { check := func(s State) Verdict { for _, work := range s.work { if work.complete { @@ -433,32 +412,15 @@ func OutstandingWork(title, msg string) SimpleExpectation { } return Unmet } - return SimpleExpectation{ - check: check, - description: fmt.Sprintf("outstanding work: %q containing %q", title, msg), + return Expectation{ + Check: check, + Description: fmt.Sprintf("outstanding work: %q containing %q", title, msg), } } -// 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 { +func NoErrorLogs() Expectation { return NoLogMatching(protocol.Error, "") } @@ -468,14 +430,14 @@ func NoErrorLogs() LogExpectation { // The count argument specifies the expected number of matching logs. If // atLeast is set, this is a lower bound, otherwise there must be exactly cound // matching logs. -func LogMatching(typ protocol.MessageType, re string, count int, atLeast bool) LogExpectation { +func LogMatching(typ protocol.MessageType, re string, count int, atLeast bool) Expectation { rec, err := regexp.Compile(re) if err != nil { panic(err) } - check := func(msgs []*protocol.LogMessageParams) Verdict { + check := func(state State) Verdict { var found int - for _, msg := range msgs { + for _, msg := range state.logs { if msg.Type == typ && rec.Match([]byte(msg.Message)) { found++ } @@ -490,16 +452,16 @@ func LogMatching(typ protocol.MessageType, re string, count int, atLeast bool) L if atLeast { desc = fmt.Sprintf("log message matching %q expected at least %v times", re, count) } - return LogExpectation{ - check: check, - description: desc, + return Expectation{ + Check: check, + Description: desc, } } // 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 { +func NoLogMatching(typ protocol.MessageType, re string) Expectation { var r *regexp.Regexp if re != "" { var err error @@ -508,8 +470,8 @@ func NoLogMatching(typ protocol.MessageType, re string) LogExpectation { panic(err) } } - check := func(msgs []*protocol.LogMessageParams) Verdict { - for _, msg := range msgs { + check := func(state State) Verdict { + for _, msg := range state.logs { if msg.Type != typ { continue } @@ -519,25 +481,25 @@ func NoLogMatching(typ protocol.MessageType, re string) LogExpectation { } return Met } - return LogExpectation{ - check: check, - description: fmt.Sprintf("no log message matching %q", re), + return Expectation{ + Check: check, + Description: fmt.Sprintf("no log message matching %q", re), } } // FileWatchMatching expects that a file registration matches re. -func FileWatchMatching(re string) SimpleExpectation { - return SimpleExpectation{ - check: checkFileWatch(re, Met, Unmet), - description: fmt.Sprintf("file watch matching %q", re), +func FileWatchMatching(re string) Expectation { + return Expectation{ + Check: checkFileWatch(re, Met, Unmet), + Description: fmt.Sprintf("file watch matching %q", re), } } // NoFileWatchMatching expects that no file registration matches re. -func NoFileWatchMatching(re string) SimpleExpectation { - return SimpleExpectation{ - check: checkFileWatch(re, Unmet, Met), - description: fmt.Sprintf("no file watch matching %q", re), +func NoFileWatchMatching(re string) Expectation { + return Expectation{ + Check: checkFileWatch(re, Unmet, Met), + Description: fmt.Sprintf("no file watch matching %q", re), } } @@ -581,7 +543,7 @@ func jsonProperty(obj interface{}, path ...string) interface{} { // TODO(rfindley): remove this once TestWatchReplaceTargets has been revisited. // // Deprecated: use (No)FileWatchMatching -func RegistrationMatching(re string) SimpleExpectation { +func RegistrationMatching(re string) Expectation { rec := regexp.MustCompile(re) check := func(s State) Verdict { for _, p := range s.registrations { @@ -593,15 +555,15 @@ func RegistrationMatching(re string) SimpleExpectation { } return Unmet } - return SimpleExpectation{ - check: check, - description: fmt.Sprintf("registration matching %q", re), + return Expectation{ + Check: check, + Description: fmt.Sprintf("registration matching %q", re), } } // UnregistrationMatching asserts that the client has received an // unregistration whose ID matches the given regexp. -func UnregistrationMatching(re string) SimpleExpectation { +func UnregistrationMatching(re string) Expectation { rec := regexp.MustCompile(re) check := func(s State) Verdict { for _, p := range s.unregistrations { @@ -613,89 +575,12 @@ func UnregistrationMatching(re string) SimpleExpectation { } return Unmet } - return SimpleExpectation{ - check: check, - description: fmt.Sprintf("unregistration matching %q", re), + return Expectation{ + 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 *protocol.Position - 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 - - // optionally, the diagnostic source - source 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 != *e.pos { - continue - } - } - if e.message != "" { - if !strings.Contains(d.Message, e.message) { - continue - } - } - if e.source != "" && e.source != d.Source { - 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.Character) - if e.re != "" { - desc += fmt.Sprintf(" (location of %q)", e.re) - } - } - if e.message != "" { - desc += fmt.Sprintf(" with message %q", e.message) - } - if e.source != "" { - desc += fmt.Sprintf(" from source %q", e.source) - } - return desc -} - // Diagnostics asserts that there is at least one diagnostic matching the given // filters. func Diagnostics(filters ...DiagnosticFilter) Expectation { @@ -722,9 +607,9 @@ func Diagnostics(filters ...DiagnosticFilter) Expectation { for _, filter := range filters { descs = append(descs, filter.desc) } - return SimpleExpectation{ - check: check, - description: "any diagnostics " + strings.Join(descs, ", "), + return Expectation{ + Check: check, + Description: "any diagnostics " + strings.Join(descs, ", "), } } @@ -752,9 +637,9 @@ func NoDiagnostics(filters ...DiagnosticFilter) Expectation { for _, filter := range filters { descs = append(descs, filter.desc) } - return SimpleExpectation{ - check: check, - description: "no diagnostics " + strings.Join(descs, ", "), + return Expectation{ + Check: check, + Description: "no diagnostics " + strings.Join(descs, ", "), } } @@ -839,14 +724,3 @@ func WithMessage(substring string) DiagnosticFilter { }, } } - -// TODO(rfindley): eliminate all expectations below this point. - -// 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} -} diff --git a/gopls/internal/regtest/completion/completion_test.go b/gopls/internal/regtest/completion/completion_test.go index c8674f04b7b..2f9b550ed28 100644 --- a/gopls/internal/regtest/completion/completion_test.go +++ b/gopls/internal/regtest/completion/completion_test.go @@ -319,7 +319,7 @@ func _() { // Await the diagnostics to add example.com/blah to the go.mod file. env.Await( - env.DiagnosticAtRegexp("main.go", `"example.com/blah"`), + Diagnostics(env.AtRegexp("main.go", `"example.com/blah"`)), ) }) } diff --git a/gopls/internal/regtest/diagnostics/analysis_test.go b/gopls/internal/regtest/diagnostics/analysis_test.go index a038d15aeea..308c25f13f6 100644 --- a/gopls/internal/regtest/diagnostics/analysis_test.go +++ b/gopls/internal/regtest/diagnostics/analysis_test.go @@ -39,7 +39,7 @@ func main() { var d protocol.PublishDiagnosticsParams env.AfterChange( - env.DiagnosticAtRegexp("main.go", "2006-02-01"), + Diagnostics(env.AtRegexp("main.go", "2006-02-01")), ReadDiagnostics("main.go", &d), ) diff --git a/gopls/internal/regtest/diagnostics/diagnostics_test.go b/gopls/internal/regtest/diagnostics/diagnostics_test.go index 1c1168199c7..4ce509c87ac 100644 --- a/gopls/internal/regtest/diagnostics/diagnostics_test.go +++ b/gopls/internal/regtest/diagnostics/diagnostics_test.go @@ -49,7 +49,7 @@ func TestDiagnosticErrorInEditedFile(t *testing.T) { env.OpenFile("main.go") env.RegexpReplace("main.go", "Printl(n)", "") env.AfterChange( - env.DiagnosticAtRegexp("main.go", "Printl"), + Diagnostics(env.AtRegexp("main.go", "Printl")), // Assert that this test has sent no error logs to the client. This is not // strictly necessary for testing this regression, but is included here // as an example of using the NoErrorLogs() expectation. Feel free to @@ -74,7 +74,7 @@ func m() { } `) env.Await( - env.DiagnosticAtRegexp("main.go", "log"), + Diagnostics(env.AtRegexp("main.go", "log")), ) env.SaveBuffer("main.go") env.AfterChange(NoDiagnostics(ForFile("main.go"))) @@ -88,7 +88,7 @@ const Foo = "abc ` Run(t, brokenFile, func(t *testing.T, env *Env) { env.CreateBuffer("broken.go", brokenFile) - env.Await(env.DiagnosticAtRegexp("broken.go", "\"abc")) + env.Await(Diagnostics(env.AtRegexp("broken.go", "\"abc"))) }) } @@ -112,8 +112,8 @@ func TestDiagnosticClearingOnEdit(t *testing.T) { Run(t, badPackage, func(t *testing.T, env *Env) { env.OpenFile("b.go") env.AfterChange( - env.DiagnosticAtRegexp("a.go", "a = 1"), - env.DiagnosticAtRegexp("b.go", "a = 2"), + Diagnostics(env.AtRegexp("a.go", "a = 1")), + Diagnostics(env.AtRegexp("b.go", "a = 2")), ) // Fix the error by editing the const name in b.go to `b`. @@ -128,7 +128,10 @@ func TestDiagnosticClearingOnEdit(t *testing.T) { func TestDiagnosticClearingOnDelete_Issue37049(t *testing.T) { Run(t, badPackage, func(t *testing.T, env *Env) { env.OpenFile("a.go") - env.Await(env.DiagnosticAtRegexp("a.go", "a = 1"), env.DiagnosticAtRegexp("b.go", "a = 2")) + env.Await( + Diagnostics(env.AtRegexp("a.go", "a = 1")), + Diagnostics(env.AtRegexp("b.go", "a = 2")), + ) env.RemoveWorkspaceFile("b.go") env.Await( @@ -144,14 +147,14 @@ func TestDiagnosticClearingOnClose(t *testing.T) { const a = 3`) env.AfterChange( - env.DiagnosticAtRegexp("a.go", "a = 1"), - env.DiagnosticAtRegexp("b.go", "a = 2"), - env.DiagnosticAtRegexp("c.go", "a = 3"), + Diagnostics(env.AtRegexp("a.go", "a = 1")), + Diagnostics(env.AtRegexp("b.go", "a = 2")), + Diagnostics(env.AtRegexp("c.go", "a = 3")), ) env.CloseBuffer("c.go") env.AfterChange( - env.DiagnosticAtRegexp("a.go", "a = 1"), - env.DiagnosticAtRegexp("b.go", "a = 2"), + Diagnostics(env.AtRegexp("a.go", "a = 1")), + Diagnostics(env.AtRegexp("b.go", "a = 2")), NoDiagnostics(ForFile("c.go")), ) }) @@ -171,7 +174,7 @@ const a = http.MethodGet `, }) env.AfterChange( - env.DiagnosticAtRegexp("c/c.go", "http.MethodGet"), + Diagnostics(env.AtRegexp("c/c.go", "http.MethodGet")), ) // Save file, which will organize imports, adding the expected import. // Expect the diagnostics to clear. @@ -211,7 +214,7 @@ func TestA(t *testing.T) { // not break the workspace. func TestDeleteTestVariant(t *testing.T) { Run(t, test38878, func(t *testing.T, env *Env) { - env.Await(env.DiagnosticAtRegexp("a_test.go", `f\((3)\)`)) + env.Await(Diagnostics(env.AtRegexp("a_test.go", `f\((3)\)`))) env.RemoveWorkspaceFile("a_test.go") env.AfterChange(NoDiagnostics(ForFile("a_test.go"))) @@ -219,7 +222,7 @@ func TestDeleteTestVariant(t *testing.T) { // triggering a metadata load. env.OpenFile("a.go") env.RegexpReplace("a.go", `// import`, "import") - env.AfterChange(env.DiagnosticAtRegexp("a.go", `"fmt"`)) + env.AfterChange(Diagnostics(env.AtRegexp("a.go", `"fmt"`))) }) } @@ -258,7 +261,7 @@ func Hello() { Run(t, noMod, func(t *testing.T, env *Env) { env.OnceMet( InitialWorkspaceLoad, - env.DiagnosticAtRegexp("main.go", `"mod.com/bob"`), + Diagnostics(env.AtRegexp("main.go", `"mod.com/bob"`)), ) env.CreateBuffer("go.mod", `module mod.com @@ -268,7 +271,7 @@ func Hello() { var d protocol.PublishDiagnosticsParams env.AfterChange( NoDiagnostics(ForFile("main.go")), - env.DiagnosticAtRegexp("bob/bob.go", "x"), + Diagnostics(env.AtRegexp("bob/bob.go", "x")), ReadDiagnostics("bob/bob.go", &d), ) if len(d.Diagnostics) != 1 { @@ -279,12 +282,12 @@ func Hello() { t.Run("initialized", func(t *testing.T) { Run(t, noMod, func(t *testing.T, env *Env) { env.Await( - env.DiagnosticAtRegexp("main.go", `"mod.com/bob"`), + Diagnostics(env.AtRegexp("main.go", `"mod.com/bob"`)), ) env.RunGoCommand("mod", "init", "mod.com") env.AfterChange( NoDiagnostics(ForFile("main.go")), - env.DiagnosticAtRegexp("bob/bob.go", "x"), + Diagnostics(env.AtRegexp("bob/bob.go", "x")), ) }) }) @@ -294,14 +297,14 @@ func Hello() { Modes(Default), ).Run(t, noMod, func(t *testing.T, env *Env) { env.Await( - env.DiagnosticAtRegexp("main.go", `"mod.com/bob"`), + Diagnostics(env.AtRegexp("main.go", `"mod.com/bob"`)), ) if err := env.Sandbox.RunGoCommand(env.Ctx, "", "mod", []string{"init", "mod.com"}, true); err != nil { t.Fatal(err) } env.AfterChange( NoDiagnostics(ForFile("main.go")), - env.DiagnosticAtRegexp("bob/bob.go", "x"), + Diagnostics(env.AtRegexp("bob/bob.go", "x")), ) }) }) @@ -349,7 +352,7 @@ func TestHello(t *testing.T) { env.OpenFile("lib.go") env.RegexpReplace("lib.go", "_ = x", "var y int") env.AfterChange( - env.DiagnosticAtRegexp("lib.go", "y int"), + Diagnostics(env.AtRegexp("lib.go", "y int")), NoDiagnostics(ForFile("lib_test.go")), ) }) @@ -418,7 +421,7 @@ func TestResolveDiagnosticWithDownload(t *testing.T) { // Check that gopackages correctly loaded this dependency. We should get a // diagnostic for the wrong formatting type. // TODO: we should be able to easily also match the diagnostic message. - env.Await(env.DiagnosticAtRegexp("print.go", "fmt.Printf")) + env.Await(Diagnostics(env.AtRegexp("print.go", "fmt.Printf"))) }) } @@ -441,7 +444,7 @@ func Hello() { ` Run(t, adHoc, func(t *testing.T, env *Env) { env.OpenFile("b/b.go") - env.Await(env.DiagnosticAtRegexp("b/b.go", "x")) + env.Await(Diagnostics(env.AtRegexp("b/b.go", "x"))) }) } @@ -462,7 +465,7 @@ func _() { }, ).Run(t, files, func(t *testing.T, env *Env) { env.OpenFile("main.go") - env.AfterChange(env.DiagnosticAtRegexp("main.go", "fmt")) + env.AfterChange(Diagnostics(env.AtRegexp("main.go", "fmt"))) env.SaveBuffer("main.go") env.AfterChange(NoDiagnostics(ForFile("main.go"))) }) @@ -602,7 +605,7 @@ func main() { if testenv.Go1Point() >= 16 { env.RegexpReplace("x/x.go", `package x`, `package main`) env.AfterChange( - env.DiagnosticAtRegexp("x/main.go", `fmt`), + Diagnostics(env.AtRegexp("x/main.go", `fmt`)), ) } }) @@ -644,7 +647,7 @@ func main() { env.OpenFile("main.go") var d protocol.PublishDiagnosticsParams env.AfterChange( - env.DiagnosticAtRegexp("main.go", `"github.com/ardanlabs/conf"`), + Diagnostics(env.AtRegexp("main.go", `"github.com/ardanlabs/conf"`)), ReadDiagnostics("main.go", &d), ) env.ApplyQuickFixes("main.go", d.Diagnostics) @@ -656,7 +659,7 @@ func main() { // diagnostic and a fix to remove the import. env.RegexpReplace("main.go", "_ = conf.ErrHelpWanted", "//_ = conf.ErrHelpWanted") env.AfterChange( - env.DiagnosticAtRegexp("main.go", `"github.com/ardanlabs/conf"`), + Diagnostics(env.AtRegexp("main.go", `"github.com/ardanlabs/conf"`)), ) env.SaveBuffer("main.go") // Expect a diagnostic and fix to remove the dependency in the go.mod. @@ -674,7 +677,7 @@ func main() { env.RegexpReplace("main.go", "//_ = conf.ErrHelpWanted", "_ = conf.ErrHelpWanted") env.SaveBuffer("main.go") env.AfterChange( - env.DiagnosticAtRegexp("main.go", `"github.com/ardanlabs/conf"`), + Diagnostics(env.AtRegexp("main.go", `"github.com/ardanlabs/conf"`)), ) }) } @@ -772,8 +775,8 @@ func TestHello(t *testing.T) { // There are errors in the code to ensure all is working as expected. env.OpenFile("hello/hello.go") env.AfterChange( - env.DiagnosticAtRegexp("hello/hello.go", "x"), - env.DiagnosticAtRegexp("hello/hello_test.go", "x"), + Diagnostics(env.AtRegexp("hello/hello.go", "x")), + Diagnostics(env.AtRegexp("hello/hello_test.go", "x")), ) // Create an empty file with the intention of making it an x test. @@ -801,7 +804,7 @@ func TestHello(t *testing.T) { // Expect a diagnostic for the missing import. Save, which should // trigger import organization. The diagnostic should clear. env.AfterChange( - env.DiagnosticAtRegexp("hello/hello_x_test.go", "hello.Hello"), + Diagnostics(env.AtRegexp("hello/hello_x_test.go", "hello.Hello")), ) env.SaveBuffer("hello/hello_x_test.go") env.AfterChange( @@ -834,7 +837,7 @@ func TestX(t *testing.T) { } `) env.Await( - env.DiagnosticAtRegexp("foo/bar_test.go", "x"), + Diagnostics(env.AtRegexp("foo/bar_test.go", "x")), ) }) } @@ -915,7 +918,7 @@ const C = a.A // We should still get diagnostics for files that exist. env.RegexpReplace("b/b.go", `a.A`, "a.Nonexistant") - env.Await(env.DiagnosticAtRegexp("b/b.go", `Nonexistant`)) + env.Await(Diagnostics(env.AtRegexp("b/b.go", `Nonexistant`))) }) } @@ -961,7 +964,7 @@ func main() { Run(t, mod, func(t *testing.T, env *Env) { writeGoVim(env, "p/p.go", p) writeGoVim(env, "main.go", main) - env.Await(env.DiagnosticAtRegexp("main.go", "5")) + env.Await(Diagnostics(env.AtRegexp("main.go", "5"))) }) }) @@ -991,9 +994,9 @@ func TestDoIt(t *testing.T) { } `) env.Await( - env.DiagnosticAtRegexp("main.go", "5"), - env.DiagnosticAtRegexp("p/p_test.go", "5"), - env.DiagnosticAtRegexp("p/x_test.go", "5"), + Diagnostics(env.AtRegexp("main.go", "5")), + Diagnostics(env.AtRegexp("p/p_test.go", "5")), + Diagnostics(env.AtRegexp("p/x_test.go", "5")), ) env.RegexpReplace("p/p.go", "s string", "i int") env.AfterChange( @@ -1024,7 +1027,7 @@ func _() { ).Run(t, mod, func(t *testing.T, env *Env) { env.OpenFile("a/a.go") env.Await( - env.DiagnosticAtRegexp("a/a.go", "x"), + Diagnostics(env.AtRegexp("a/a.go", "x")), ) }) } @@ -1116,7 +1119,7 @@ func main() { } `)) env.Await( - env.DiagnosticAtRegexp("main.go", "x"), + Diagnostics(env.AtRegexp("main.go", "x")), ) }) } @@ -1164,7 +1167,7 @@ func main() { ).Run(t, mod, func(t *testing.T, env *Env) { env.OpenFile("a/main.go") env.AfterChange( - env.DiagnosticAtRegexp("main.go", "x"), + Diagnostics(env.AtRegexp("main.go", "x")), ) }) WithOptions( @@ -1282,7 +1285,7 @@ func _() { Run(t, files, func(t *testing.T, env *Env) { env.OpenFile("a/a.go") env.Await( - env.DiagnosticAtRegexp("a/a.go", "x"), + Diagnostics(env.AtRegexp("a/a.go", "x")), ) env.OpenFile("a/a_exclude.go") env.Await( @@ -1497,7 +1500,7 @@ func main() { ) env.RemoveWorkspaceFile("bob") env.AfterChange( - env.DiagnosticAtRegexp("cmd/main.go", `"mod.com/bob"`), + Diagnostics(env.AtRegexp("cmd/main.go", `"mod.com/bob"`)), NoDiagnostics(ForFile("bob/bob.go")), NoFileWatchMatching("bob"), ) @@ -1675,7 +1678,7 @@ func helloHelper() {} // Expect a diagnostic in a nested module. env.OpenFile("nested/hello/hello.go") env.AfterChange( - env.DiagnosticAtRegexp("nested/hello/hello.go", "helloHelper"), + Diagnostics(env.AtRegexp("nested/hello/hello.go", "helloHelper")), Diagnostics(env.AtRegexp("nested/hello/hello.go", "package hello"), WithMessage("nested module")), OutstandingWork(lsp.WorkspaceLoadFailure, "nested module"), ) @@ -1716,7 +1719,7 @@ var Bar = Foo Run(t, files, func(t *testing.T, env *Env) { env.OpenFile("foo.go") - env.AfterChange(env.DiagnosticAtRegexp("bar.go", `Foo`)) + env.AfterChange(Diagnostics(env.AtRegexp("bar.go", `Foo`))) env.RegexpReplace("foo.go", `\+build`, "") env.AfterChange(NoDiagnostics(ForFile("bar.go"))) }) @@ -1747,14 +1750,14 @@ package main env.OpenFile("main.go") env.OpenFile("other.go") env.Await( - env.DiagnosticAtRegexp("main.go", "asdf"), - env.DiagnosticAtRegexp("main.go", "fdas"), + Diagnostics(env.AtRegexp("main.go", "asdf")), + Diagnostics(env.AtRegexp("main.go", "fdas")), ) env.SetBufferContent("other.go", "package main\n\nasdf") // The new diagnostic in other.go should not suppress diagnostics in main.go. env.AfterChange( Diagnostics(env.AtRegexp("other.go", "asdf"), WithMessage("expected declaration")), - env.DiagnosticAtRegexp("main.go", "asdf"), + Diagnostics(env.AtRegexp("main.go", "asdf")), ) }) } @@ -1842,7 +1845,7 @@ func F[T C](_ T) { var d protocol.PublishDiagnosticsParams env.OnceMet( InitialWorkspaceLoad, - env.DiagnosticAtRegexp("main.go", `C`), + Diagnostics(env.AtRegexp("main.go", `C`)), ReadDiagnostics("main.go", &d), ) if fixes := env.GetQuickFixes("main.go", d.Diagnostics); len(fixes) != 0 { diff --git a/gopls/internal/regtest/diagnostics/undeclared_test.go b/gopls/internal/regtest/diagnostics/undeclared_test.go index bba72c47237..a6289c9745a 100644 --- a/gopls/internal/regtest/diagnostics/undeclared_test.go +++ b/gopls/internal/regtest/diagnostics/undeclared_test.go @@ -46,7 +46,7 @@ func _() int { env.OpenFile("a/a.go") var adiags protocol.PublishDiagnosticsParams env.AfterChange( - env.DiagnosticAtRegexp("a/a.go", "x"), + Diagnostics(env.AtRegexp("a/a.go", "x")), ReadDiagnostics("a/a.go", &adiags), ) env.Await() @@ -61,7 +61,7 @@ func _() int { env.OpenFile("b/b.go") var bdiags protocol.PublishDiagnosticsParams env.AfterChange( - env.DiagnosticAtRegexp("b/b.go", "y = y"), + Diagnostics(env.AtRegexp("b/b.go", "y = y")), ReadDiagnostics("b/b.go", &bdiags), ) if got := len(bdiags.Diagnostics); got != 1 { diff --git a/gopls/internal/regtest/misc/generate_test.go b/gopls/internal/regtest/misc/generate_test.go index 9fd448cd849..69a28e23132 100644 --- a/gopls/internal/regtest/misc/generate_test.go +++ b/gopls/internal/regtest/misc/generate_test.go @@ -60,7 +60,7 @@ func main() { Run(t, generatedWorkspace, func(t *testing.T, env *Env) { env.Await( - env.DiagnosticAtRegexp("main.go", "lib1.(Answer)"), + Diagnostics(env.AtRegexp("main.go", "lib1.(Answer)")), ) env.RunGenerate("./lib1") env.RunGenerate("./lib2") diff --git a/gopls/internal/regtest/misc/imports_test.go b/gopls/internal/regtest/misc/imports_test.go index b9804d0c436..513171a1e69 100644 --- a/gopls/internal/regtest/misc/imports_test.go +++ b/gopls/internal/regtest/misc/imports_test.go @@ -156,7 +156,7 @@ var _, _ = x.X, y.Y ProxyFiles(proxy), ).Run(t, files, func(t *testing.T, env *Env) { env.OpenFile("main.go") - env.AfterChange(env.DiagnosticAtRegexp("main.go", `y.Y`)) + env.AfterChange(Diagnostics(env.AtRegexp("main.go", `y.Y`))) env.SaveBuffer("main.go") env.AfterChange(NoDiagnostics(ForFile("main.go"))) path, _ := env.GoToDefinition("main.go", env.RegexpSearch("main.go", `y.(Y)`)) @@ -200,7 +200,7 @@ func TestA(t *testing.T) { env.OpenFile("a/a.go") var d protocol.PublishDiagnosticsParams env.AfterChange( - env.DiagnosticAtRegexp("a/a.go", "os.Stat"), + Diagnostics(env.AtRegexp("a/a.go", "os.Stat")), ReadDiagnostics("a/a.go", &d), ) env.ApplyQuickFixes("a/a.go", d.Diagnostics) @@ -247,7 +247,7 @@ func Test() { ` Run(t, pkg, func(t *testing.T, env *Env) { env.OpenFile("caller/caller.go") - env.AfterChange(env.DiagnosticAtRegexp("caller/caller.go", "a.Test")) + env.AfterChange(Diagnostics(env.AtRegexp("caller/caller.go", "a.Test"))) // Saving caller.go should trigger goimports, which should find a.Test in // the mod.com module, thanks to the go.work file. diff --git a/gopls/internal/regtest/misc/rename_test.go b/gopls/internal/regtest/misc/rename_test.go index 81b3de8125a..86fd567cde7 100644 --- a/gopls/internal/regtest/misc/rename_test.go +++ b/gopls/internal/regtest/misc/rename_test.go @@ -405,15 +405,15 @@ package b // Initially, we should have diagnostics on both X's, for their duplicate declaration. env.OnceMet( InitialWorkspaceLoad, - env.DiagnosticAtRegexp("a/a.go", "X"), - env.DiagnosticAtRegexp("a/x.go", "X"), + Diagnostics(env.AtRegexp("a/a.go", "X")), + Diagnostics(env.AtRegexp("a/x.go", "X")), ) // Moving x.go should make the diagnostic go away. env.RenameFile("a/x.go", "b/x.go") env.AfterChange( - NoDiagnostics(ForFile("a/a.go")), // no more duplicate declarations - env.DiagnosticAtRegexp("b/b.go", "package"), // as package names mismatch + NoDiagnostics(ForFile("a/a.go")), // no more duplicate declarations + Diagnostics(env.AtRegexp("b/b.go", "package")), // as package names mismatch ) // Renaming should also work on open buffers. @@ -422,15 +422,15 @@ package b // Moving x.go back to a/ should cause the diagnostics to reappear. env.RenameFile("b/x.go", "a/x.go") env.AfterChange( - env.DiagnosticAtRegexp("a/a.go", "X"), - env.DiagnosticAtRegexp("a/x.go", "X"), + Diagnostics(env.AtRegexp("a/a.go", "X")), + Diagnostics(env.AtRegexp("a/x.go", "X")), ) // Renaming the entire directory should move both the open and closed file. env.RenameFile("a", "x") env.AfterChange( - env.DiagnosticAtRegexp("x/a.go", "X"), - env.DiagnosticAtRegexp("x/x.go", "X"), + Diagnostics(env.AtRegexp("x/a.go", "X")), + Diagnostics(env.AtRegexp("x/x.go", "X")), ) // As a sanity check, verify that x/x.go is open. diff --git a/gopls/internal/regtest/misc/semantictokens_test.go b/gopls/internal/regtest/misc/semantictokens_test.go index 422147cb33e..e083faa3912 100644 --- a/gopls/internal/regtest/misc/semantictokens_test.go +++ b/gopls/internal/regtest/misc/semantictokens_test.go @@ -93,7 +93,9 @@ func Add[T int](target T, l []T) []T { Settings{"semanticTokens": true}, ).Run(t, src, func(t *testing.T, env *Env) { env.OpenFile("main.go") - env.AfterChange(env.DiagnosticAtRegexp("main.go", "for range")) + env.AfterChange( + Diagnostics(env.AtRegexp("main.go", "for range")), + ) p := &protocol.SemanticTokensParams{ TextDocument: protocol.TextDocumentIdentifier{ URI: env.Sandbox.Workdir.URI("main.go"), diff --git a/gopls/internal/regtest/misc/shared_test.go b/gopls/internal/regtest/misc/shared_test.go index 84eb99f73de..de44167c291 100644 --- a/gopls/internal/regtest/misc/shared_test.go +++ b/gopls/internal/regtest/misc/shared_test.go @@ -54,8 +54,8 @@ func main() { env2.RegexpReplace("main.go", "\\)\n(})", "") // Now check that we got different diagnostics in each environment. - env1.Await(env1.DiagnosticAtRegexp("main.go", "Printl")) - env2.Await(env2.DiagnosticAtRegexp("main.go", "$")) + env1.Await(Diagnostics(env1.AtRegexp("main.go", "Printl"))) + env2.Await(Diagnostics(env2.AtRegexp("main.go", "$"))) // Now close editor #2, and verify that operation in editor #1 is // unaffected. diff --git a/gopls/internal/regtest/misc/vuln_test.go b/gopls/internal/regtest/misc/vuln_test.go index b34ddfc0a12..9d732727ea9 100644 --- a/gopls/internal/regtest/misc/vuln_test.go +++ b/gopls/internal/regtest/misc/vuln_test.go @@ -485,7 +485,7 @@ func TestRunVulncheckPackageDiagnostics(t *testing.T) { gotDiagnostics := &protocol.PublishDiagnosticsParams{} env.AfterChange( - env.DiagnosticAtRegexp("go.mod", `golang.org/amod`), + Diagnostics(env.AtRegexp("go.mod", `golang.org/amod`)), ReadDiagnostics("go.mod", gotDiagnostics), ) @@ -589,7 +589,7 @@ func TestRunVulncheckPackageDiagnostics(t *testing.T) { ShownMessage("Found"), ) env.OnceMet( - env.DiagnosticAtRegexp("go.mod", "golang.org/bmod"), + Diagnostics(env.AtRegexp("go.mod", "golang.org/bmod")), ReadDiagnostics("go.mod", gotDiagnostics), ) // We expect only one diagnostic for GO-2022-02. @@ -636,7 +636,7 @@ func TestRunVulncheckWarning(t *testing.T) { ) // Vulncheck diagnostics asynchronous to the vulncheck command. env.OnceMet( - env.DiagnosticAtRegexp("go.mod", `golang.org/amod`), + Diagnostics(env.AtRegexp("go.mod", `golang.org/amod`)), ReadDiagnostics("go.mod", gotDiagnostics), ) @@ -803,7 +803,7 @@ func TestGovulncheckInfo(t *testing.T) { // Vulncheck diagnostics asynchronous to the vulncheck command. env.OnceMet( - env.DiagnosticAtRegexp("go.mod", "golang.org/bmod"), + Diagnostics(env.AtRegexp("go.mod", "golang.org/bmod")), ReadDiagnostics("go.mod", gotDiagnostics), ) diff --git a/gopls/internal/regtest/modfile/modfile_test.go b/gopls/internal/regtest/modfile/modfile_test.go index e88368a3b14..d3df2155b2b 100644 --- a/gopls/internal/regtest/modfile/modfile_test.go +++ b/gopls/internal/regtest/modfile/modfile_test.go @@ -93,7 +93,7 @@ func main() { goModContent := env.ReadWorkspaceFile("a/go.mod") env.OpenFile("a/main.go") env.AfterChange( - env.DiagnosticAtRegexp("a/main.go", "\"example.com/blah\""), + Diagnostics(env.AtRegexp("a/main.go", "\"example.com/blah\"")), ) if got := env.ReadWorkspaceFile("a/go.mod"); got != goModContent { t.Fatalf("go.mod changed on disk:\n%s", compare.Text(goModContent, got)) @@ -102,7 +102,7 @@ func main() { // Confirm that the go.mod file still does not change. env.SaveBuffer("a/main.go") env.Await( - env.DiagnosticAtRegexp("a/main.go", "\"example.com/blah\""), + Diagnostics(env.AtRegexp("a/main.go", "\"example.com/blah\"")), ) if got := env.ReadWorkspaceFile("a/go.mod"); got != goModContent { t.Fatalf("go.mod changed on disk:\n%s", compare.Text(goModContent, got)) @@ -143,7 +143,7 @@ func main() { env.WriteWorkspaceFile("a/main.go", mainContent) env.AfterChange( - env.DiagnosticAtRegexp("a/main.go", "\"example.com/blah\""), + Diagnostics(env.AtRegexp("a/main.go", "\"example.com/blah\"")), ) if got := env.ReadWorkspaceFile("a/go.mod"); got != goModContent { t.Fatalf("go.mod changed on disk:\n%s", compare.Text(goModContent, got)) @@ -184,7 +184,7 @@ require example.com v1.2.3 env.OpenFile("a/main.go") var d protocol.PublishDiagnosticsParams env.AfterChange( - env.DiagnosticAtRegexp("a/main.go", `"example.com/blah"`), + Diagnostics(env.AtRegexp("a/main.go", `"example.com/blah"`)), ReadDiagnostics("a/main.go", &d), ) var goGetDiag protocol.Diagnostic @@ -231,7 +231,7 @@ require random.org v1.2.3 env.OpenFile("a/main.go") var d protocol.PublishDiagnosticsParams env.AfterChange( - env.DiagnosticAtRegexp("a/main.go", `"random.org/blah"`), + Diagnostics(env.AtRegexp("a/main.go", `"random.org/blah"`)), ReadDiagnostics("a/main.go", &d), ) var randomDiag protocol.Diagnostic @@ -285,7 +285,7 @@ require random.org v1.2.3 env.OpenFile("a/main.go") var d protocol.PublishDiagnosticsParams env.AfterChange( - env.DiagnosticAtRegexp("a/main.go", `"random.org/blah"`), + Diagnostics(env.AtRegexp("a/main.go", `"random.org/blah"`)), ReadDiagnostics("a/main.go", &d), ) var randomDiag protocol.Diagnostic @@ -334,7 +334,7 @@ require example.com v1.2.3 env.OpenFile("a/go.mod") var d protocol.PublishDiagnosticsParams env.AfterChange( - env.DiagnosticAtRegexp("a/go.mod", "// indirect"), + Diagnostics(env.AtRegexp("a/go.mod", "// indirect")), ReadDiagnostics("a/go.mod", &d), ) env.ApplyQuickFixes("a/go.mod", d.Diagnostics) @@ -376,7 +376,7 @@ go 1.14 env.OpenFile("a/go.mod") var d protocol.PublishDiagnosticsParams env.AfterChange( - env.DiagnosticAtRegexp("a/go.mod", `require example.com`), + Diagnostics(env.AtRegexp("a/go.mod", `require example.com`)), ReadDiagnostics("a/go.mod", &d), ) env.ApplyQuickFixes("a/go.mod", d.Diagnostics) @@ -436,7 +436,7 @@ func _() { env.OpenFile("a/main.go") var d protocol.PublishDiagnosticsParams env.AfterChange( - env.DiagnosticAtRegexp("a/main.go", `"github.com/esimov/caire"`), + Diagnostics(env.AtRegexp("a/main.go", `"github.com/esimov/caire"`)), ReadDiagnostics("a/main.go", &d), ) env.ApplyQuickFixes("a/main.go", d.Diagnostics) @@ -481,7 +481,7 @@ func main() { }.Run(t, mod, func(t *testing.T, env *Env) { env.OnceMet( InitialWorkspaceLoad, - env.DiagnosticAtRegexp("a/go.mod", "require"), + Diagnostics(env.AtRegexp("a/go.mod", "require")), ) env.RunGoCommandInDir("a", "mod", "tidy") env.AfterChange( @@ -596,7 +596,7 @@ func main() { runner.Run(t, unknown, func(t *testing.T, env *Env) { env.OpenFile("a/go.mod") env.Await( - env.DiagnosticAtRegexp("a/go.mod", "example.com v1.2.2"), + Diagnostics(env.AtRegexp("a/go.mod", "example.com v1.2.2")), ) env.RegexpReplace("a/go.mod", "v1.2.2", "v1.2.3") env.SaveBuffer("a/go.mod") // Save to trigger diagnostics. @@ -615,7 +615,7 @@ func main() { env.SaveBuffer("a/go.mod") // Save to trigger diagnostics. env.AfterChange( NoDiagnostics(ForFile("a/go.mod")), - env.DiagnosticAtRegexp("a/main.go", "x = "), + Diagnostics(env.AtRegexp("a/main.go", "x = ")), ) }) }) @@ -645,17 +645,17 @@ func main() { runner.Run(t, known, func(t *testing.T, env *Env) { env.OpenFile("a/go.mod") env.AfterChange( - env.DiagnosticAtRegexp("a/main.go", "x = "), + Diagnostics(env.AtRegexp("a/main.go", "x = ")), ) env.RegexpReplace("a/go.mod", "v1.2.3", "v1.2.2") env.Editor.SaveBuffer(env.Ctx, "a/go.mod") // go.mod changes must be on disk env.AfterChange( - env.DiagnosticAtRegexp("a/go.mod", "example.com v1.2.2"), + Diagnostics(env.AtRegexp("a/go.mod", "example.com v1.2.2")), ) env.RegexpReplace("a/go.mod", "v1.2.2", "v1.2.3") env.Editor.SaveBuffer(env.Ctx, "a/go.mod") // go.mod changes must be on disk env.AfterChange( - env.DiagnosticAtRegexp("a/main.go", "x = "), + Diagnostics(env.AtRegexp("a/main.go", "x = ")), ) }) }) @@ -706,7 +706,7 @@ func main() { }.Run(t, module, func(t *testing.T, env *Env) { env.OpenFile("a/go.mod") env.Await( - env.DiagnosticAtRegexp("a/go.mod", "require example.com v1.2.3"), + Diagnostics(env.AtRegexp("a/go.mod", "require example.com v1.2.3")), ) }) } @@ -735,7 +735,7 @@ func main() { env.OpenFile("main.go") original := env.ReadWorkspaceFile("go.mod") env.Await( - env.DiagnosticAtRegexp("main.go", `"example.com/blah"`), + Diagnostics(env.AtRegexp("main.go", `"example.com/blah"`)), ) got := env.ReadWorkspaceFile("go.mod") if got != original { @@ -820,7 +820,7 @@ func main() { Settings{"buildFlags": []string{"-tags", "bob"}}, ).Run(t, mod, func(t *testing.T, env *Env) { env.Await( - env.DiagnosticAtRegexp("main.go", `"example.com/blah"`), + Diagnostics(env.AtRegexp("main.go", `"example.com/blah"`)), ) }) } @@ -840,7 +840,7 @@ func main() {} env.OpenFile("go.mod") env.RegexpReplace("go.mod", "module", "modul") env.Await( - env.DiagnosticAtRegexp("go.mod", "modul"), + Diagnostics(env.AtRegexp("go.mod", "modul")), ) }) } @@ -981,7 +981,7 @@ func main() {} env.OpenFile("go.mod") d := &protocol.PublishDiagnosticsParams{} env.AfterChange( - env.DiagnosticAtRegexp("go.mod", "require hasdep.com v1.2.3"), + Diagnostics(env.AtRegexp("go.mod", "require hasdep.com v1.2.3")), ReadDiagnostics("go.mod", d), ) const want = `module mod.com diff --git a/gopls/internal/regtest/template/template_test.go b/gopls/internal/regtest/template/template_test.go index f3453d72cf8..c81bf1a1184 100644 --- a/gopls/internal/regtest/template/template_test.go +++ b/gopls/internal/regtest/template/template_test.go @@ -73,7 +73,7 @@ Hello {{}} <-- missing body var diags protocol.PublishDiagnosticsParams env.OnceMet( InitialWorkspaceLoad, - env.DiagnosticAtRegexp("hello.tmpl", "()Hello {{}}"), + Diagnostics(env.AtRegexp("hello.tmpl", "()Hello {{}}")), ReadDiagnostics("hello.tmpl", &diags), ) d := diags.Diagnostics // issue 50786: check for Source @@ -120,7 +120,7 @@ B {{}} <-- missing body ).Run(t, files, func(t *testing.T, env *Env) { env.OnceMet( InitialWorkspaceLoad, - env.DiagnosticAtRegexp("a/a.tmpl", "()A"), + Diagnostics(env.AtRegexp("a/a.tmpl", "()A")), NoDiagnostics(ForFile("b/b.tmpl")), ) }) @@ -140,7 +140,7 @@ go 1.12 NoDiagnostics(ForFile("hello.tmpl")), // Don't get spurious errors for empty templates. ) env.SetBufferContent("hello.tmpl", "{{range .Planets}}\nHello {{}}\n{{end}}") - env.Await(env.DiagnosticAtRegexp("hello.tmpl", "()Hello {{}}")) + env.Await(Diagnostics(env.AtRegexp("hello.tmpl", "()Hello {{}}"))) env.RegexpReplace("hello.tmpl", "{{}}", "{{.}}") env.Await(NoDiagnostics(ForFile("hello.tmpl"))) }) @@ -161,7 +161,7 @@ Hello {{}} <-- missing body Run(t, files, func(t *testing.T, env *Env) { env.OpenFile("hello.tmpl") env.AfterChange( - env.DiagnosticAtRegexp("hello.tmpl", "()Hello {{}}"), + Diagnostics(env.AtRegexp("hello.tmpl", "()Hello {{}}")), ) // Since we don't have templateExtensions configured, closing hello.tmpl // should make its diagnostics disappear. diff --git a/gopls/internal/regtest/watch/watch_test.go b/gopls/internal/regtest/watch/watch_test.go index b445f88b332..908648396ef 100644 --- a/gopls/internal/regtest/watch/watch_test.go +++ b/gopls/internal/regtest/watch/watch_test.go @@ -39,7 +39,7 @@ func _() { Run(t, pkg, func(t *testing.T, env *Env) { env.OnceMet( InitialWorkspaceLoad, - env.DiagnosticAtRegexp("a/a.go", "x"), + Diagnostics(env.AtRegexp("a/a.go", "x")), ) env.WriteWorkspaceFile("a/a.go", `package a; func _() {};`) env.AfterChange( @@ -59,7 +59,7 @@ func _() { env.AfterChange() env.WriteWorkspaceFile("a/a.go", `package a; func _() {};`) env.AfterChange( - env.DiagnosticAtRegexp("a/a.go", "x"), + Diagnostics(env.AtRegexp("a/a.go", "x")), ) }) }) @@ -92,7 +92,7 @@ func _() { env.Await(env.DoneWithOpen()) env.WriteWorkspaceFile("b/b.go", `package b; func B() {};`) env.Await( - env.DiagnosticAtRegexp("a/a.go", "b.B"), + Diagnostics(env.AtRegexp("a/a.go", "b.B")), ) }) } @@ -124,7 +124,7 @@ func _() { Run(t, pkg, func(t *testing.T, env *Env) { env.OnceMet( InitialWorkspaceLoad, - env.DiagnosticAtRegexp("a/a.go", "x"), + Diagnostics(env.AtRegexp("a/a.go", "x")), ) env.WriteWorkspaceFiles(map[string]string{ "b/b.go": `package b; func B() {};`, @@ -170,7 +170,7 @@ func _() { env.Await(env.DoneWithOpen()) env.RemoveWorkspaceFile("b/b.go") env.Await( - env.DiagnosticAtRegexp("a/a.go", "\"mod.com/b\""), + Diagnostics(env.AtRegexp("a/a.go", "\"mod.com/b\"")), ) }) } @@ -200,7 +200,7 @@ func _() { Run(t, missing, func(t *testing.T, env *Env) { env.OnceMet( InitialWorkspaceLoad, - env.DiagnosticAtRegexp("a/a.go", "\"mod.com/c\""), + Diagnostics(env.AtRegexp("a/a.go", "\"mod.com/c\"")), ) env.WriteWorkspaceFile("c/c.go", `package c; func C() {};`) env.AfterChange( @@ -248,7 +248,7 @@ func _() { Run(t, pkg, func(t *testing.T, env *Env) { env.OnceMet( InitialWorkspaceLoad, - env.DiagnosticAtRegexp("a/a.go", "hello"), + Diagnostics(env.AtRegexp("a/a.go", "hello")), ) env.WriteWorkspaceFile("a/a2.go", `package a; func hello() {};`) env.AfterChange( @@ -392,7 +392,7 @@ package a env.RemoveWorkspaceFile("a/a_unneeded.go") env.RegexpReplace("a/a.go", "var _ int", "fmt.Println(\"\")") env.AfterChange( - env.DiagnosticAtRegexp("a/a.go", "fmt"), + Diagnostics(env.AtRegexp("a/a.go", "fmt")), ) env.SaveBuffer("a/a.go") env.AfterChange( @@ -420,7 +420,7 @@ package a env.CloseBuffer("a/a_unneeded.go") env.RegexpReplace("a/a.go", "var _ int", "fmt.Println(\"\")") env.Await( - env.DiagnosticAtRegexp("a/a.go", "fmt"), + Diagnostics(env.AtRegexp("a/a.go", "fmt")), ) env.SaveBuffer("a/a.go") env.AfterChange( @@ -621,7 +621,7 @@ func main() { env.OpenFile("foo/main.go") env.RemoveWorkspaceFile("foo/go.mod") env.AfterChange( - env.DiagnosticAtRegexp("foo/main.go", `"mod.com/blah"`), + Diagnostics(env.AtRegexp("foo/main.go", `"mod.com/blah"`)), ) env.RegexpReplace("foo/main.go", `"mod.com/blah"`, `"foo/blah"`) env.AfterChange( diff --git a/gopls/internal/regtest/workspace/broken_test.go b/gopls/internal/regtest/workspace/broken_test.go index 0c718b339ea..5c5a68ae1dd 100644 --- a/gopls/internal/regtest/workspace/broken_test.go +++ b/gopls/internal/regtest/workspace/broken_test.go @@ -161,7 +161,7 @@ const F = named.D - 3 Run(t, files, func(t *testing.T, env *Env) { env.OpenFile("p/internal/bar/bar.go") env.AfterChange( - env.DiagnosticAtRegexp("p/internal/bar/bar.go", "\"mod.test/p/internal/foo\""), + Diagnostics(env.AtRegexp("p/internal/bar/bar.go", "\"mod.test/p/internal/foo\"")), ) env.OpenFile("go.mod") env.RegexpReplace("go.mod", "mod.testx", "mod.test") @@ -207,8 +207,8 @@ package b env.OpenFile("a/empty.go") env.OpenFile("b/go.mod") env.AfterChange( - env.DiagnosticAtRegexp("a/a.go", "package a"), - env.DiagnosticAtRegexp("b/go.mod", "module b.com"), + Diagnostics(env.AtRegexp("a/a.go", "package a")), + Diagnostics(env.AtRegexp("b/go.mod", "module b.com")), OutstandingWork(lsp.WorkspaceLoadFailure, msg), ) @@ -238,9 +238,9 @@ package b env.OpenFile("b/b.go") env.AfterChange( // TODO(rfindley): fix these missing diagnostics. - // env.DiagnosticAtRegexp("a/a.go", "package a"), - // env.DiagnosticAtRegexp("b/go.mod", "module b.com"), - env.DiagnosticAtRegexp("b/b.go", "package b"), + // Diagnostics(env.AtRegexp("a/a.go", "package a")), + // Diagnostics(env.AtRegexp("b/go.mod", "module b.com")), + Diagnostics(env.AtRegexp("b/b.go", "package b")), OutstandingWork(lsp.WorkspaceLoadFailure, msg), ) }) diff --git a/gopls/internal/regtest/workspace/directoryfilters_test.go b/gopls/internal/regtest/workspace/directoryfilters_test.go index f7c7153ec0e..5db8d897cf8 100644 --- a/gopls/internal/regtest/workspace/directoryfilters_test.go +++ b/gopls/internal/regtest/workspace/directoryfilters_test.go @@ -135,7 +135,7 @@ package exclude ProxyFiles(proxy), Settings{"directoryFilters": []string{"-exclude"}}, ).Run(t, files, func(t *testing.T, env *Env) { - env.Await(env.DiagnosticAtRegexp("include/include.go", `exclude.(X)`)) + env.Await(Diagnostics(env.AtRegexp("include/include.go", `exclude.(X)`))) }) } diff --git a/gopls/internal/regtest/workspace/metadata_test.go b/gopls/internal/regtest/workspace/metadata_test.go index 31663fbeb07..11dfe670c42 100644 --- a/gopls/internal/regtest/workspace/metadata_test.go +++ b/gopls/internal/regtest/workspace/metadata_test.go @@ -73,8 +73,8 @@ func main() {} env.OpenFile("bar.go") env.OnceMet( env.DoneWithOpen(), - env.DiagnosticAtRegexp("foo.go", "func (main)"), - env.DiagnosticAtRegexp("bar.go", "func (main)"), + Diagnostics(env.AtRegexp("foo.go", "func (main)")), + Diagnostics(env.AtRegexp("bar.go", "func (main)")), ) // Ignore bar.go. This should resolve diagnostics. diff --git a/gopls/internal/regtest/workspace/standalone_test.go b/gopls/internal/regtest/workspace/standalone_test.go index 7056f5464bb..d7f03469fc6 100644 --- a/gopls/internal/regtest/workspace/standalone_test.go +++ b/gopls/internal/regtest/workspace/standalone_test.go @@ -131,7 +131,7 @@ func main() { // Renaming "lib.C" to "lib.D" should cause a diagnostic in the standalone // file. env.RegexpReplace("lib/lib.go", "C", "D") - env.AfterChange(env.DiagnosticAtRegexp("lib/ignore.go", "lib.(C)")) + env.AfterChange(Diagnostics(env.AtRegexp("lib/ignore.go", "lib.(C)"))) // Undoing the replacement should fix diagnostics env.RegexpReplace("lib/lib.go", "D", "C") @@ -186,7 +186,7 @@ func main() {} env.OpenFile("standalone.go") env.AfterChange( - env.DiagnosticAtRegexp("ignore.go", "package (main)"), + Diagnostics(env.AtRegexp("ignore.go", "package (main)")), NoDiagnostics(ForFile("standalone.go")), ) @@ -202,7 +202,7 @@ func main() {} env.AfterChange( NoDiagnostics(ForFile("ignore.go")), - env.DiagnosticAtRegexp("standalone.go", "package (main)"), + Diagnostics(env.AtRegexp("standalone.go", "package (main)")), ) }) } diff --git a/gopls/internal/regtest/workspace/workspace_test.go b/gopls/internal/regtest/workspace/workspace_test.go index 3932648bdc1..0573455f396 100644 --- a/gopls/internal/regtest/workspace/workspace_test.go +++ b/gopls/internal/regtest/workspace/workspace_test.go @@ -152,7 +152,7 @@ func TestClearAnalysisDiagnostics(t *testing.T) { ).Run(t, workspaceModule, func(t *testing.T, env *Env) { env.OpenFile("pkg/main.go") env.AfterChange( - env.DiagnosticAtRegexp("pkg/main2.go", "fmt.Print"), + Diagnostics(env.AtRegexp("pkg/main2.go", "fmt.Print")), ) env.CloseBuffer("pkg/main.go") env.AfterChange( @@ -267,8 +267,8 @@ func Hello() int { env.RunGoCommand("work", "init") env.RunGoCommand("work", "use", "-r", ".") env.AfterChange( - env.DiagnosticAtRegexp("moda/a/a.go", "x"), - env.DiagnosticAtRegexp("modb/b/b.go", "x"), + Diagnostics(env.AtRegexp("moda/a/a.go", "x")), + Diagnostics(env.AtRegexp("modb/b/b.go", "x")), NoDiagnostics(env.AtRegexp("moda/a/a.go", `"b.com/b"`)), ) }) @@ -324,7 +324,7 @@ func main() { ProxyFiles(proxy), ).Run(t, multiModule, func(t *testing.T, env *Env) { env.Await( - env.DiagnosticAtRegexp("main.go", "x"), + Diagnostics(env.AtRegexp("main.go", "x")), ) }) } @@ -452,7 +452,7 @@ func Hello() int { } `, }) - env.AfterChange(env.DiagnosticAtRegexp("modb/b/b.go", "x")) + env.AfterChange(Diagnostics(env.AtRegexp("modb/b/b.go", "x"))) got, _ := env.GoToDefinition("moda/a/a.go", env.RegexpSearch("moda/a/a.go", "Hello")) if want := "modb/b/b.go"; !strings.HasSuffix(got, want) { t.Errorf("expected %s, got %v", want, original) @@ -508,7 +508,7 @@ func Hello() int { env.RegexpReplace("modb/go.mod", "modul", "module") env.SaveBufferWithoutActions("modb/go.mod") env.Await( - env.DiagnosticAtRegexp("modb/b/b.go", "x"), + Diagnostics(env.AtRegexp("modb/b/b.go", "x")), ) }) } @@ -607,7 +607,7 @@ use ( // As of golang/go#54069, writing go.work to the workspace triggers a // workspace reload. env.AfterChange( - env.DiagnosticAtRegexp("modb/b/b.go", "x"), + Diagnostics(env.AtRegexp("modb/b/b.go", "x")), ) // Jumping to definition should now go to b.com in the workspace. @@ -905,10 +905,10 @@ func main() { InitialWorkspaceLoad, // TODO(rfindley): assert on the full set of diagnostics here. We // should ensure that we don't have a diagnostic at b.Hi in a.go. - env.DiagnosticAtRegexp("moda/a/a.go", "x"), - env.DiagnosticAtRegexp("modb/b/b.go", "x"), - env.DiagnosticAtRegexp("modb/v2/b/b.go", "x"), - env.DiagnosticAtRegexp("modc/main.go", "x"), + Diagnostics(env.AtRegexp("moda/a/a.go", "x")), + Diagnostics(env.AtRegexp("modb/b/b.go", "x")), + Diagnostics(env.AtRegexp("modb/v2/b/b.go", "x")), + Diagnostics(env.AtRegexp("modc/main.go", "x")), ) }) } @@ -1114,8 +1114,8 @@ func (Server) Foo() {} // as invalid. So we need to wait for the metadata of main_test.go to be // updated before moving other_test.go back to the main_test package. env.Await( - env.DiagnosticAtRegexp("other_test.go", "Server"), - env.DiagnosticAtRegexp("main_test.go", "otherConst"), + Diagnostics(env.AtRegexp("other_test.go", "Server")), + Diagnostics(env.AtRegexp("main_test.go", "otherConst")), ) env.RegexpReplace("other_test.go", "main", "main_test") env.AfterChange(