var InitialWorkspaceLoad … type Verdict … const Met … const Unmet … const Unmeetable … func (v Verdict) String() string { … } type Expectation … // OnceMet returns an Expectation that, once the precondition is met, asserts // that mustMeet is met. func OnceMet(precondition Expectation, mustMeets ...Expectation) Expectation { … } func describeExpectations(expectations ...Expectation) string { … } // Not inverts the sense of an expectation: a met expectation is unmet, and an // unmet expectation is met. func Not(e Expectation) Expectation { … } // AnyOf returns an expectation that is satisfied when any of the given // expectations is met. func AnyOf(anyOf ...Expectation) Expectation { … } // AllOf expects that all given expectations are met. // // TODO(rfindley): the problem with these types of combinators (OnceMet, AnyOf // and AllOf) is that we lose the information of *why* they failed: the Awaiter // is not smart enough to look inside. // // Refactor the API such that the Check function is responsible for explaining // 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) Expectation { … } // ReadDiagnostics is an Expectation that stores the current diagnostics for // fileName in into, whenever it is evaluated. // // It can be used in combination with OnceMet or AfterChange to capture the // state of diagnostics when other expectations are satisfied. func ReadDiagnostics(fileName string, into *protocol.PublishDiagnosticsParams) Expectation { … } // ReadAllDiagnostics is an expectation that stores all published diagnostics // into the provided map, whenever it is evaluated. // // It can be used in combination with OnceMet or AfterChange to capture the // state of diagnostics when other expectations are satisfied. func ReadAllDiagnostics(into *map[string]*protocol.PublishDiagnosticsParams) Expectation { … } // ShownDocument asserts that the client has received a // ShowDocumentRequest for the given URI. func ShownDocument(uri protocol.URI) Expectation { … } // ShownDocuments is an expectation that appends each showDocument // request into the provided slice, whenever it is evaluated. // // It can be used in combination with OnceMet or AfterChange to // capture the set of showDocument requests when other expectations // are satisfied. func ShownDocuments(into *[]*protocol.ShowDocumentParams) Expectation { … } // NoShownMessage asserts that the editor has not received a ShowMessage. func NoShownMessage(subString string) Expectation { … } // ShownMessage asserts that the editor has received a ShowMessageRequest // containing the given substring. func ShownMessage(containing string) Expectation { … } // ShownMessageRequest asserts that the editor has received a // ShowMessageRequest with message matching the given regular expression. func ShownMessageRequest(messageRegexp string) Expectation { … } // DoneDiagnosingChanges expects that diagnostics are complete from common // change notifications: didOpen, didChange, didSave, didChangeWatchedFiles, // and didClose. // // This can be used when multiple notifications may have been sent, such as // when a didChange is immediately followed by a didSave. It is insufficient to // simply await NoOutstandingWork, because the LSP client has no control over // when the server starts processing a notification. Therefore, we must keep // track of func (e *Env) DoneDiagnosingChanges() Expectation { … } // AfterChange expects that the given expectations will be met after all // state-changing notifications have been processed by the server. // Specifically, it awaits the awaits completion of the process of diagnosis // after the following notifications, before checking the given expectations: // - textDocument/didOpen // - textDocument/didChange // - textDocument/didSave // - textDocument/didClose // - workspace/didChangeWatchedFiles // - workspace/didChangeConfiguration func (e *Env) AfterChange(expectations ...Expectation) { … } // DoneWithOpen expects all didOpen notifications currently sent by the editor // to be completely processed. func (e *Env) DoneWithOpen() Expectation { … } // StartedChange expects that the server has at least started processing all // didChange notifications sent from the client. func (e *Env) StartedChange() Expectation { … } // DoneWithChange expects all didChange notifications currently sent by the // editor to be completely processed. func (e *Env) DoneWithChange() Expectation { … } // DoneWithSave expects all didSave notifications currently sent by the editor // to be completely processed. func (e *Env) DoneWithSave() Expectation { … } // StartedChangeWatchedFiles expects that the server has at least started // processing all didChangeWatchedFiles notifications sent from the client. func (e *Env) StartedChangeWatchedFiles() Expectation { … } // DoneWithChangeWatchedFiles expects all didChangeWatchedFiles notifications // currently sent by the editor to be completely processed. func (e *Env) DoneWithChangeWatchedFiles() Expectation { … } // DoneWithClose expects all didClose notifications currently sent by the // editor to be completely processed. func (e *Env) DoneWithClose() Expectation { … } // StartedWork expect a work item to have been started >= atLeast times. // // See CompletedWork. func StartedWork(title string, atLeast uint64) Expectation { … } // 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, count uint64, atLeast bool) Expectation { … } type WorkStatus … // CompletedProgress expects that there is exactly one workDone progress with // the given title, and is satisfied when that progress completes. If it is // met, the corresponding status is written to the into argument. // // TODO(rfindley): refactor to eliminate the redundancy with CompletedWork. // This expectation is a vestige of older workarounds for asynchronous command // execution. func CompletedProgress(title string, into *WorkStatus) Expectation { … } // 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) Expectation { … } // NoOutstandingWork asserts that there is no work initiated using the LSP // $/progress API that has not completed. // // If non-nil, the ignore func is used to ignore certain work items for the // purpose of this check. // // TODO(rfindley): consider refactoring to treat outstanding work the same way // we treat diagnostics: with an algebra of filters. func NoOutstandingWork(ignore func(title, msg string) bool) Expectation { … } // IgnoreTelemetryPromptWork may be used in conjunction with NoOutStandingWork // to ignore the telemetry prompt. func IgnoreTelemetryPromptWork(title, msg string) bool { … } // NoErrorLogs asserts that the client has not received any log messages of // error severity. func NoErrorLogs() Expectation { … } // LogMatching asserts that the client has received a log message // of type typ matching the regexp re a certain number of times. // // The count argument specifies the expected number of matching logs. If // atLeast is set, this is a lower bound, otherwise there must be exactly count // matching logs. // // Logs are asynchronous to other LSP messages, so this expectation should not // be used with combinators such as OnceMet or AfterChange that assert on // ordering with respect to other operations. func LogMatching(typ protocol.MessageType, re string, count int, atLeast bool) Expectation { … } // 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) Expectation { … } // FileWatchMatching expects that a file registration matches re. func FileWatchMatching(re string) Expectation { … } // NoFileWatchMatching expects that no file registration matches re. func NoFileWatchMatching(re string) Expectation { … } func checkFileWatch(re string, onMatch, onNoMatch Verdict) func(State) Verdict { … } // jsonProperty extracts a value from a path of JSON property names, assuming // the default encoding/json unmarshaling to the empty interface (i.e.: that // JSON objects are unmarshalled as map[string]interface{}) // // For example, if obj is unmarshalled from the following json: // // { // "foo": { "bar": 3 } // } // // Then jsonProperty(obj, "foo", "bar") will be 3. func jsonProperty(obj interface{ … } // Diagnostics asserts that there is at least one diagnostic matching the given // filters. func Diagnostics(filters ...DiagnosticFilter) Expectation { … } // NoDiagnostics asserts that there are no diagnostics matching the given // filters. Notably, if no filters are supplied this assertion checks that // there are no diagnostics at all, for any file. func NoDiagnostics(filters ...DiagnosticFilter) Expectation { … } type flatDiagnostic … func flattenDiagnostics(state State) []flatDiagnostic { … } type DiagnosticFilter … // ForFile filters to diagnostics matching the sandbox-relative file name. func ForFile(name string) DiagnosticFilter { … } // FromSource filters to diagnostics matching the given diagnostics source. func FromSource(source string) DiagnosticFilter { … } // AtRegexp filters to diagnostics in the file with sandbox-relative path name, // at the first position matching the given regexp pattern. // // TODO(rfindley): pass in the editor to expectations, so that they may depend // on editor state and AtRegexp can be a function rather than a method. func (e *Env) AtRegexp(name, pattern string) DiagnosticFilter { … } // AtPosition filters to diagnostics at location name:line:character, for a // sandbox-relative path name. // // Line and character are 0-based, and character measures UTF-16 codes. // // Note: prefer the more readable AtRegexp. func AtPosition(name string, line, character uint32) DiagnosticFilter { … } // WithMessage filters to diagnostics whose message contains the given // substring. func WithMessage(substring string) DiagnosticFilter { … } // WithSeverityTags filters to diagnostics whose severity and tags match // the given expectation. func WithSeverityTags(diagName string, severity protocol.DiagnosticSeverity, tags []protocol.DiagnosticTag) DiagnosticFilter { … }