golang.org/x/tools/gopls@v0.15.3/internal/test/marker/doc.go (about) 1 // Copyright 2023 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 /* 6 Package marker defines a framework for running "marker" tests, each 7 defined by a file in the testdata subdirectory. 8 9 Use this command to run the tests: 10 11 $ go test ./gopls/internal/test/marker [-update] 12 13 A marker test uses the '//@' marker syntax of the x/tools/go/expect package 14 to annotate source code with various information such as locations and 15 arguments of LSP operations to be executed by the test. The syntax following 16 '@' is parsed as a comma-separated list of ordinary Go function calls, for 17 example 18 19 //@foo(a, "b", 3),bar(0) 20 21 and delegates to a corresponding function to perform LSP-related operations. 22 See the Marker types documentation below for a list of supported markers. 23 24 Each call argument is converted to the type of the corresponding parameter of 25 the designated function. The conversion logic may use the surrounding context, 26 such as the position or nearby text. See the Argument conversion section below 27 for the full set of special conversions. As a special case, the blank 28 identifier '_' is treated as the zero value of the parameter type. 29 30 The test runner collects test cases by searching the given directory for 31 files with the .txt extension. Each file is interpreted as a txtar archive, 32 which is extracted to a temporary directory. The relative path to the .txt 33 file is used as the subtest name. The preliminary section of the file 34 (before the first archive entry) is a free-form comment. 35 36 # Special files 37 38 There are several types of file within the test archive that are given special 39 treatment by the test runner: 40 41 - "skip": the presence of this file causes the test to be skipped, with 42 the file content used as the skip message. 43 44 - "flags": this file is treated as a whitespace-separated list of flags 45 that configure the MarkerTest instance. Supported flags: 46 -{min,max}_go=go1.20 sets the {min,max}imum Go version for the test 47 (inclusive) 48 -cgo requires that CGO_ENABLED is set and the cgo tool is available 49 -write_sumfile=a,b,c instructs the test runner to generate go.sum files 50 in these directories before running the test. 51 -skip_goos=a,b,c instructs the test runner to skip the test for the 52 listed GOOS values. 53 -ignore_extra_diags suppresses errors for unmatched diagnostics 54 TODO(rfindley): using build constraint expressions for -skip_goos would 55 be clearer. 56 -filter_builtins=false disables the filtering of builtins from 57 completion results. 58 -filter_keywords=false disables the filtering of keywords from 59 completion results. 60 TODO(rfindley): support flag values containing whitespace. 61 62 - "settings.json": this file is parsed as JSON, and used as the 63 session configuration (see gopls/doc/settings.md) 64 65 - "capabilities.json": this file is parsed as JSON client capabilities, 66 and applied as an overlay over the default editor client capabilities. 67 see https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#clientCapabilities 68 for more details. 69 70 - "env": this file is parsed as a list of VAR=VALUE fields specifying the 71 editor environment. 72 73 - Golden files: Within the archive, file names starting with '@' are 74 treated as "golden" content, and are not written to disk, but instead are 75 made available to test methods expecting an argument of type *Golden, 76 using the identifier following '@'. For example, if the first parameter of 77 Foo were of type *Golden, the test runner would convert the identifier a 78 in the call @foo(a, "b", 3) into a *Golden by collecting golden file 79 data starting with "@a/". As a special case, for tests that only need one 80 golden file, the data contained in the file "@a" is indexed in the *Golden 81 value by the empty string "". 82 83 - proxy files: any file starting with proxy/ is treated as a Go proxy 84 file. If present, these files are written to a separate temporary 85 directory and GOPROXY is set to file://<proxy directory>. 86 87 # Marker types 88 89 Markers are of two kinds. A few are "value markers" (e.g. @item), which are 90 processed in a first pass and each computes a value that may be referred to 91 by name later. Most are "action markers", which are processed in a second 92 pass and take some action such as testing an LSP operation; they may refer 93 to values computed by value markers. 94 95 The following markers are supported within marker tests: 96 97 - acceptcompletion(location, label, golden): specifies that accepting the 98 completion candidate produced at the given location with provided label 99 results in the given golden state. 100 101 - codeaction(start, end, kind, golden, ...titles): specifies a code action 102 to request for the given range. To support multi-line ranges, the range 103 is defined to be between start.Start and end.End. The golden directory 104 contains changed file content after the code action is applied. 105 If titles are provided, they are used to filter the matching code 106 action. 107 108 TODO(rfindley): consolidate with codeactionedit, via a @loc2 marker that 109 allows binding multi-line locations. 110 111 - codeactionedit(range, kind, golden, ...titles): a shorter form of 112 codeaction. Invokes a code action of the given kind for the given 113 in-line range, and compares the resulting formatted unified *edits* 114 (notably, not the full file content) with the golden directory. 115 116 - codeactionerr(start, end, kind, wantError): specifies a codeaction that 117 fails with an error that matches the expectation. 118 119 - codelens(location, title): specifies that a codelens is expected at the 120 given location, with given title. Must be used in conjunction with 121 @codelenses. 122 123 - codelenses(): specifies that textDocument/codeLens should be run for the 124 current document, with results compared to the @codelens annotations in 125 the current document. 126 127 - complete(location, ...items): specifies expected completion results at 128 the given location. Must be used in conjunction with @item. 129 130 - diag(location, regexp): specifies an expected diagnostic matching the 131 given regexp at the given location. The test runner requires 132 a 1:1 correspondence between observed diagnostics and diag annotations. 133 The diagnostics source and kind fields are ignored, to reduce fuss. 134 135 The specified location must match the start position of the diagnostic, 136 but end positions are ignored. 137 138 TODO(adonovan): in the older marker framework, the annotation asserted 139 two additional fields (source="compiler", kind="error"). Restore them? 140 141 - def(src, dst location): performs a textDocument/definition request at 142 the src location, and check the result points to the dst location. 143 144 - documentLink(golden): asserts that textDocument/documentLink returns 145 links as described by the golden file. 146 147 - foldingrange(golden): performs a textDocument/foldingRange for the 148 current document, and compare with the golden content, which is the 149 original source annotated with numbered tags delimiting the resulting 150 ranges (e.g. <1 kind="..."> ... </1>). 151 152 - format(golden): performs a textDocument/format request for the enclosing 153 file, and compare against the named golden file. If the formatting 154 request succeeds, the golden file must contain the resulting formatted 155 source. If the formatting request fails, the golden file must contain 156 the error message. 157 158 - highlight(src location, dsts ...location): makes a 159 textDocument/highlight request at the given src location, which should 160 highlight the provided dst locations. 161 162 - hover(src, dst location, sm stringMatcher): performs a textDocument/hover 163 at the src location, and checks that the result is the dst location, with 164 matching hover content. 165 166 - hovererr(src, sm stringMatcher): performs a textDocument/hover at the src 167 location, and checks that the error matches the given stringMatcher. 168 169 - implementations(src location, want ...location): makes a 170 textDocument/implementation query at the src location and 171 checks that the resulting set of locations matches want. 172 173 - incomingcalls(src location, want ...location): makes a 174 callHierarchy/incomingCalls query at the src location, and checks that 175 the set of call.From locations matches want. 176 177 - item(label, details, kind): defines a completion item with the provided 178 fields. This information is not positional, and therefore @item markers 179 may occur anywhere in the source. Used in conjunction with @complete, 180 snippet, or rank. 181 182 TODO(rfindley): rethink whether floating @item annotations are the best 183 way to specify completion results. 184 185 - loc(name, location): specifies the name for a location in the source. These 186 locations may be referenced by other markers. 187 188 - outgoingcalls(src location, want ...location): makes a 189 callHierarchy/outgoingCalls query at the src location, and checks that 190 the set of call.To locations matches want. 191 192 - preparerename(src, spn, placeholder): asserts that a textDocument/prepareRename 193 request at the src location expands to the spn location, with given 194 placeholder. If placeholder is "", this is treated as a negative 195 assertion and prepareRename should return nil. 196 197 - rename(location, new, golden): specifies a renaming of the 198 identifier at the specified location to the new name. 199 The golden directory contains the transformed files. 200 201 - renameerr(location, new, wantError): specifies a renaming that 202 fails with an error that matches the expectation. 203 204 - signature(location, label, active): specifies that 205 signatureHelp at the given location should match the provided string, with 206 the active parameter (an index) highlighted. 207 208 - suggestedfix(location, regexp, golden): like diag, the location and 209 regexp identify an expected diagnostic. This diagnostic must 210 to have exactly one associated code action of the specified kind. 211 This action is executed for its editing effects on the source files. 212 Like rename, the golden directory contains the expected transformed files. 213 214 - suggestedfixerr(location, regexp, kind, wantError): specifies that the 215 suggestedfix operation should fail with an error that matches the expectation. 216 (Failures in the computation to offer a fix do not generally result 217 in LSP errors, so this marker is not appropriate for testing them.) 218 219 - rank(location, ...completionItem): executes a textDocument/completion 220 request at the given location, and verifies that each expected 221 completion item occurs in the results, in the expected order. Other 222 unexpected completion items may occur in the results. 223 TODO(rfindley): this exists for compatibility with the old marker tests. 224 Replace this with rankl, and rename. 225 226 - rankl(location, ...label): like rank, but only cares about completion 227 item labels. 228 229 - refs(location, want ...location): executes a textDocument/references 230 request at the first location and asserts that the result is the set of 231 'want' locations. The first want location must be the declaration 232 (assumedly unique). 233 234 - snippet(location, completionItem, snippet): executes a 235 textDocument/completion request at the location, and searches for a 236 result with label matching that of the provided completion item 237 (TODO(rfindley): accept a label rather than a completion item). Check 238 the the result snippet matches the provided snippet. 239 240 - symbol(golden): makes a textDocument/documentSymbol request 241 for the enclosing file, formats the response with one symbol 242 per line, sorts it, and compares against the named golden file. 243 Each line is of the form: 244 245 dotted.symbol.name kind "detail" +n lines 246 247 where the "+n lines" part indicates that the declaration spans 248 several lines. The test otherwise makes no attempt to check 249 location information. There is no point to using more than one 250 @symbol marker in a given file. 251 252 - token(location, tokenType, mod): makes a textDocument/semanticTokens/range 253 request at the given location, and asserts that the result includes 254 exactly one token with the given token type and modifier string. 255 256 - workspacesymbol(query, golden): makes a workspace/symbol request for the 257 given query, formats the response with one symbol per line, and compares 258 against the named golden file. As workspace symbols are by definition a 259 workspace-wide request, the location of the workspace symbol marker does 260 not matter. Each line is of the form: 261 262 location name kind 263 264 # Argument conversion 265 266 Marker arguments are first parsed by the go/expect package, which accepts 267 the following tokens as defined by the Go spec: 268 - string, int64, float64, and rune literals 269 - true and false 270 - nil 271 - identifiers (type expect.Identifier) 272 - regular expressions, denoted the two tokens re"abc" (type *regexp.Regexp) 273 274 These values are passed as arguments to the corresponding parameter of the 275 test function. Additional value conversions may occur for these argument -> 276 parameter type pairs: 277 - string->regexp: the argument is parsed as a regular expressions. 278 - string->location: the argument is converted to the location of the first 279 instance of the argument in the partial line preceding the note. 280 - regexp->location: the argument is converted to the location of the first 281 match for the argument in the partial line preceding the note. If the 282 regular expression contains exactly one subgroup, the position of the 283 subgroup is used rather than the position of the submatch. 284 - name->location: the argument is replaced by the named location. 285 - name->Golden: the argument is used to look up golden content prefixed by 286 @<argument>. 287 - {string,regexp,identifier}->stringMatcher: a stringMatcher type 288 specifies an expected string, either in the form of a substring 289 that must be present, a regular expression that it must match, or an 290 identifier (e.g. foo) such that the archive entry @foo exists and 291 contains the exact expected string. 292 stringMatchers are used by some markers to match positive results 293 (outputs) and by other markers to match error messages. 294 295 # Example 296 297 Here is a complete example: 298 299 This test checks hovering over constants. 300 301 -- a.go -- 302 package a 303 304 const abc = 0x2a //@hover("b", "abc", abc),hover(" =", "abc", abc) 305 306 -- @abc -- 307 ```go 308 const abc untyped int = 42 309 ``` 310 311 @hover("b", "abc", abc),hover(" =", "abc", abc) 312 313 In this example, the @hover annotation tells the test runner to run the 314 hoverMarker function, which has parameters: 315 316 (mark marker, src, dsc protocol.Location, g *Golden). 317 318 The first argument holds the test context, including fake editor with open 319 files, and sandboxed directory. 320 321 Argument converters translate the "b" and "abc" arguments into locations by 322 interpreting each one as a substring (or as a regular expression, if of the 323 form re"a|b") and finding the location of its first occurrence on the preceding 324 portion of the line, and the abc identifier into a the golden content contained 325 in the file @abc. Then the hoverMarker method executes a textDocument/hover LSP 326 request at the src position, and ensures the result spans "abc", with the 327 markdown content from @abc. (Note that the markdown content includes the expect 328 annotation as the doc comment.) 329 330 The next hover on the same line asserts the same result, but initiates the 331 hover immediately after "abc" in the source. This tests that we find the 332 preceding identifier when hovering. 333 334 # Updating golden files 335 336 To update golden content in the test archive, it is easier to regenerate 337 content automatically rather than edit it by hand. To do this, run the 338 tests with the -update flag. Only tests that actually run will be updated. 339 340 In some cases, golden content will vary by Go version (for example, gopls 341 produces different markdown at Go versions before the 1.19 go/doc update). 342 By convention, the golden content in test archives should match the output 343 at Go tip. Each test function can normalize golden content for older Go 344 versions. 345 346 Note that -update does not cause missing @diag or @loc markers to be added. 347 348 # TODO 349 350 - Rename the files .txtar. 351 - Provide some means by which locations in the standard library 352 (or builtin.go) can be named, so that, for example, we can we 353 can assert that MyError implements the built-in error type. 354 - If possible, improve handling for optional arguments. Rather than have 355 multiple variations of a marker, it would be nice to support a more 356 flexible signature: can codeaction, codeactionedit, codeactionerr, and 357 suggestedfix be consolidated? 358 */ 359 package marker